Google 网上论坛不再支持新的 Usenet 帖子或订阅项。历史内容仍可供查看。

Capture Object: why no verb?

已查看 1 次
跳至第一个未读帖子

Dave Whipp

未读,
2006年4月17日 17:29:032006/4/17
收件人 perl6-l...@perl.org
Reading about capture objects, I see that they represent an arglist, and
the the object to which you going to send those args. What is doesn't
capture is the method name (the verb) that's being called. This feels
like a slightly strange ommission.

Compare:

$message = &Shape::draw.prebind( x=>0, y=>0 );
$capture = \( $shape: x=>0, y=>0 );

$shape.$message;
draw *$capture;

These are both doing very similar things. The difference is only in the
thing that's being associated with the arglist. In the case of currying
it's the method whereas for the capture it's the invocant.

Perhaps I'm not fully groking the abstraction of the capture-object, but
it seems to me that there should be a slot in it for the method. For
dispatch, all three things are needed (invocant, method, args); so if
you're going to put two of them in one object, then maybe the third
thing belongs, too.

Audrey Tang

未读,
2006年4月17日 23:31:292006/4/17
收件人 Dave Whipp、perl6-l...@perl.org
Dave Whipp wrote:
> Perhaps I'm not fully groking the abstraction of the capture-object, but
> it seems to me that there should be a slot in it for the method. For
> dispatch, all three things are needed (invocant, method, args); so if
> you're going to put two of them in one object, then maybe the third
> thing belongs, too.

Hm, Perl 6 actually has two different ways of putting Capture to some
Code object... Following yesterday's P6AST draft I'll call them Call and
Apply respectively:

moose($obj: 1, 2); # this is Call
&moose.($obj: 1, 2); # this is Apply

elk(named => 'arg'); # this is Call
&elk.(named => 'arg'); # this is Apply

The difference is whether the Code is an object (Apply), or a "message"
name (Call). As the same argument list can be reused in both cases, it
seems the "method" part is better left out from the abstraction. That
allows:

my $cap = \("Hello", "World");
outs(*$cap); # Sub Call (may optimize to Apply if &outs is lexical)
$fh.say(*$cap); # Method Call
$output(*$cap); # Apply

This also makes multiple Captures easily composable:

say(*$cap, *$cap, *$cap); # "HelloWorldHelloWorldHelloWorld"

<P6C>
Of course, if we go all Smalltalkish, we can say that Apply is merely
sending the "postcircumfix:<( )>" message to the Code object, so that we
can treat _everything_ as a closure by defining:

# Below demonstrates a (IMHO) bad idea
sub postcircumfix:<( )> ($inv: \$cap) { say "Foo!" }
1.(); # "Foo!" - method call falling back to sub call

But this defeats common closure-based optimizations, and penalizes
functional programming style for no apparent gain, so I think the
method-full form and method-less form are still better separated in the AST.
</P6C>

Audrey

signature.asc

Dave Whipp

未读,
2006年4月22日 17:04:532006/4/22
收件人 perl6-l...@perl.org
Audrey Tang wrote:

> Hm, Perl 6 actually has two different ways of putting Capture to some
> Code object... Following yesterday's P6AST draft I'll call them Call and
> Apply respectively:
>
> moose($obj: 1, 2); # this is Call
> &moose.($obj: 1, 2); # this is Apply
>
> elk(named => 'arg'); # this is Call
> &elk.(named => 'arg'); # this is Apply
>
> The difference is whether the Code is an object (Apply), or a "message"
> name (Call). As the same argument list can be reused in both cases, it
> seems the "method" part is better left out from the abstraction. That
> allows:

My understanding is that Capture objects are intended to superceed perl5
references. Synopsys 2 states:

| You may retrieve parts from a Capture object with a prefix sigil
| operator:
|
| $args = \3; # same as "$args = \(3)"
| $$args; # same as "$args as Scalar" or "Scalar($args)"
| @$args; # same as '$args as Array" or "Array($args)"
| %$args; # same as '$args as Hash" or "Hash($args)"
|
| When cast into an array, you can access all the positional arguments;
| into a hash, all named arguments; into a scalar, its invocant.

I find myself wanting to add the obvious extra case to this list. Should
it read:

&$args; # 'fail' ? (runtime error, or compile time?)

I'd prefer it to do something more analagous to a perl5 coderef
dereference -- assuming that it is possible to create a reference to
code using a Capture.

Also, I'm a bit confused By the idea that the invocant is obtained by a
scalar dereference, because I know that arrays and hashes can be
invocants, too. E.g. @a.pop. So, If I do:

my $args = \(@a:);
my $b = $$args; # @a as a scalar
my @c = @$args; # empty list
my @d := $$args; # bound to @a

Is there any way that a deref can determine that the invocant stored in
the capture was placed there using the '@' sigil? Perhpas this leads to
the question of whether there is ever a reason for code to distinguish
between @ invocants and $ invocants. I'm guessing that the answer must
be "no".

Audrey Tang

未读,
2006年4月22日 20:09:162006/4/22
收件人 Dave Whipp、perl6-l...@perl.org
Dave Whipp wrote:
> Also, I'm a bit confused By the idea that the invocant is obtained by a
> scalar dereference, because I know that arrays and hashes can be
> invocants, too. E.g. @a.pop. So, If I do:
>
> my $args = \(@a:);
> my $b = $$args; # @a as a scalar
> my @c = @$args; # empty list
> my @d := $$args; # bound to @a

That is totally correct. "Scalar" here really means "any one thing", any
Array is but one kind of one-thing.

> Is there any way that a deref can determine that the invocant stored in
> the capture was placed there using the '@' sigil? Perhpas this leads to
> the question of whether there is ever a reason for code to distinguish
> between @ invocants and $ invocants. I'm guessing that the answer must
> be "no".

No. If you really want to flatten at list context the content of
invocant, then @$$args will do what you want, though it's a bit heavy. :)

Audrey

signature.asc
0 个新帖子