On Fri, Aug 13, 2004 at 08:41:35PM -0400, Matt Diephouse wrote:
: > You know, at some point you just break down and write them positionally:
: > 
: >     @array.each( { $^odd.bar() }, { $^even.baz() });
: 
: Speaking of which, let's talk a little bit about how I'd write these
: methods. After looking at Apocalypse, Exegesis, and Synopsis 6 again,
: I have a few more questions. There are two different ways used to
: declare a subroutine or method:
: 
:  sub foo (&block) {
:      &block('foo');
:  }

The second & is unnecessary there.  If you declare a &foo, you get foo() for free.

:  sub foo (Code $block) {
:      $block('foo');
:  }
: 
: Which is right? both? The second seems more extensible.

Either should work.  Scalars are always more general, since they can
hold anything.  But sometimes the point is to be less general...

: And that leads
: me to another question: can a slurpy array pick up a block?
: 
:  sub foo ([EMAIL PROTECTED]) {
:      say ref @args[0]; # @args[0].type?
:  }

Probably "typeof", actually, since "ref" is unclear, and "type" is
a keyword that prevents an indirect object syntax.  Though arguably
"type" should be "subtype" or "constrain" or some such, which would
free up "type" for a unary.

:  foo { $^a =~ /bar/ }; # does this print "Block\n"?

Maybe something more like "Code<scalar>". Haven't revisited the
Code hierarchy in a while though.  But the signature type
is in angles (this week), since parens are taken for actual
arguments.

: It'd be nice to be able to declare my each method like so:
: 
: class Array {
:     method each($self: [EMAIL PROTECTED]) {

Could go as far as to say Code [EMAIL PROTECTED], I expect.  And you can
probably get away with @self too.  (I also wouldn't call it "each",
since there's likely to be a built-in of that name, but I understand
you're just playing here...)

    method roundrobin(@self: Code [EMAIL PROTECTED]) {

:         my $i = 0;
:         my @results;
:         for @$self -> $elem {
:             my $block = @blocks[ $i++ % [EMAIL PROTECTED] ];

The + is redundant there, though okay as documentation, which
I suppose is why you put it.

:             @results.push( $block($elem) );

You can also write those two lines as:

            my &block = @blocks[ $i++ % [EMAIL PROTECTED] ];
            @results.push( block($elem) );

or as

            @results.push( @blocks[ $i++ % [EMAIL PROTECTED] ]($elem) );

:         }
:         return @results;
:     }
: }
: 
: But that still doesn't let me call that like I'd want;
: 
: my @r = @array.each :{ $^first * 2 }
:                     :{ $^second * 9 }
:                     :{ $^third * 42 };

Which would take some special dispensation like "Multiple anonymous
closures are pushed onto the slurp array if there's no slurp closure."

On the other hand, we've not really specified very well what happens
if you pass two named parameters of the same name, other than saying
the first one binds to the named parameter (if any) and the second
one ends up in the slurpy hash.  But what happens to the third one?
An argument could be made for creating a subarray in the hash when
there are multiples, in which case your multiple blocks would
come through as %hash{""}[].  But I hate it that you'd have to
treat a single argument differently.

Maybe there's some way to extend signature syntax similarly to what
we did for [$head, [EMAIL PROTECTED] arguments.  There seems to be some kind
of generic problem here with assuming named array arguments are always
passed as a reference to a single array rather than a list of arguments
with the same name.  I'd much prefer a general solution than a bandaid
just for blocks.

: The other thing I'm wondering is how to apply adverbs to the results
: of a function, if that's even possible. I believe this is valid:

Adverbs by definition modify verbs, not nouns.

:  my $odd = 1... :by(2) # an infinite list of odd numbers 

I suppose an adverb can apply itself directly to a postfix operator
like that, given that it still sets up the expectation for an
operator rather than a term.

: But this?
: 
:  sub odd_numbers([EMAIL PROTECTED] of Pair) {
:      return 1...;
:  }
:  my $odd = odd_numbers :by(2);
: 
: Does that pass C<by => 2> as a Pair to the function?

Yes.  A term is expected, :by(2) is just a pair.

: Or does it apply the adverb to the result? Maybe I need to do this?
: 
:  my $odd = (odd_numbers) :by(2);
: 
: My head is swimming at this point, so I'd better give it a rest.

That would apply the adverb to the =, which would make anyone's
head swim, especially anyone trying to figure out how to implement
assignment "by 2".

Larry

Reply via email to