On Fri, Aug 20, 2004 at 04:15:43PM -0600, John Williams wrote:
: Adverbs are confusing me mightily lately.
: 
: It may be that Larry's A12 revision just needs a few examples
: *with* parenthesis to straighten me out.
: 
: Here are some semi-coherent attempts to sort it out
: in my mind.  Please correct me where I have made mistakes.
: 
: What is the rule(s) for when :foo is an adverb, and when :foo
: is just a pair constructor?
: 
: So far I think that :foo is an adverb where an operator
: is expected, but :for is a pair constructor where a term
: is expected.
: 
: Why is this difference important?
: 
: Perhaps because an adverb goes looking for something to
: apply itself to.

Yes.

: How does it decide what to apply itself to?
: 
: >    4) Adverbs apply to the previous unparenthesized prefix, infix,
: >    or postfix operator, bypassing simple terms and other "pill"
: >    operators such as circumfix or postcircumfix.
: 
: But what about the rules for "additional arguments as adverbs"?
: 
: >    1d) Additional [function] arguments may occur as adverbs *only* if
: >    there are explicit parens.
: 
: >    2d) Given 2c, additional [method] arguments may occur as adverbs
: >    whether or not there is an argument "pill":
: 
: I assume rule 1d only applies to arglist parenthesis,
: and not grouping parenthesis?

Yes.

: The legal syntaxes below all mean the same thing, right?
: 
:    func(1,2,3,:foo);  # ok
:    func 1,2,3,:foo ;  # ok

Those two are the same.

:    func(1,2,3):foo ;  # ok

That one is a little different.  Adverbs are always bound as named
arguments.  Pair arguments are bound as named arguments only if they
come between The Positional Arguments and The List.  So this example
is the same only if the function is declared with three positional
arguments:

    func(:foo, 1,2,3)   (+$foo, [EMAIL PROTECTED])
    func(1, :foo, 2,3)  ($a, +$foo, [EMAIL PROTECTED])
    func(1,2, :foo, 3)  ($a, $b, +$foo, [EMAIL PROTECTED])
    func(1,2,3, :foo)   ($a, $b, $c, +$foo, [EMAIL PROTECTED])

Which is why it's good to use <== to be explicit about where your
list starts in these cases.

:    func(1,2,3 :foo);  # ok (explicit parens)

That one is illegal because the comma between 2 and 3 doesn't take a
:foo adverb.  Rule 1d should probably read something like: "...only
if there are explicit parens before it."

Basically, the parens have to be there to direct the gaze of the adverb
at the function name.

:    func 1,2,3 :foo ;  # ILLEGAL (according to A12 revision)

Illegal for the same reason--the rules apply it to the comma.

: And for 2d, these are the same:
: 
:    .meth(1,2,3):foo ;
:    .meth(1,2,3 :foo);

The second one is illegal for the same reason.

: Does rule 1d or rule 4 does apply inside this parenthesized arglist?
: 
:    func( eeney, meeny, miney :moe );
: 
: Does :moe apply to func (rule 1d) or miney (rule 4)?

It can never apply to func.  It can only apply to comma or miney.

: Does it depend on the declaration of miney?

Yes.

:    sub miney {...}         # simple term: moe applies to func

No, that's not a simple term, but a list operator.  So you get miney(:moe)
instead of infix:,(miney, :moe).  If you want a bare term you need to say

    sub miney () {...}

:    sub miney(*%adv) {...}  # does a slurpy hash make a function a list operator?

Only a sig of () makes it *not* look for an argument as a list operator.

:    sub miney($+moe) {...}  # I'll take that moe

You can have it. :-)

(But only if you reverse the $ and the +.)

:    sub miney($+curly) {...}  # Arg OK, but not that one!

Correct (except for the reversed $ and + again).

: Is this correct according to 2d, assuming func and meth are 0-ary:
: 
:    say func :foo;     # say( func, foo=>1 )

This one's illegal.  Gotta have a comma to expect a term.

:    say .meth :foo;    # say( .meth( foo=>1 ) )

That one works.

: but if func is 2-or-more-ary, then:
: 
:    say func :foo;     # say( func( foo=>1 ) )

Yes.

: A unary function cannot take an adverb, because it has no slurpy hash.

Don't need a slurpy hash for adverbs.  Only a matching named parameter.
Unary just means there's exactly one non-optional positional parameter,
so this is a unary operator:

    sub prefix:-($x, +$with_prejudice) { negate($x, $with_prejudice) }

and can be called with any of:

    -$foo
    -$foo:with_prejudice
    -$foo:with_prejudice(0)

Likewise

    sqrt($x):both

could return both the positive and negative root.  In this case it's
ambiguous whether

    sqrt $x, :both

should treat sqrt as a named unary or a list operator.  I don't know
offhand which way to bias that, or whether the parser should just
throw up its hands in disgust.  Or just throw up...

: Is a function with a slurpy hash automatically a list operator,
: even if it has 0 or 1 positional arguments?

Yes.  Functions are strongly biased towards being list operators.
Which probably means that we should bias the sqrt example to a list
operator on the basis of the named argument.  (But not symbolic
unaries like '-'.)

: Do I have my whitespace rules right below?
: 
:    say  foo :bar;     # say( foo( bar=>1 ) )   assuming foo is listy
:    say .foo :bar;     # say( .foo( bar=>1 ) )
:    say  foo: bar;     # foo.say(bar)

Yes, but works only if "foo" is predeclared as a class.

:    say  foo:bar ;     # ?? say foo :bar ??

Yes, like the label colon, the invocant-terminating colon requires
whitespace after it if it would be confused with a longer term starting
with colon.  And /^\:\w+/ is always a named pair of some sort.  Otherwise
we couldn't string together :foo:bar:baz:utf($ate).

: Adverbs are still passed to the function as "just a pair",
: so they have to come after positional parameters.

They're always bound to named arguments.

: But that's kinda ugly in some cases.  Are there ways to get
: around it?
: 
: If I know the names of the positional parameters, I can put the
: adverb (aka pair constructor) first, and pass all the parameters
: in via names.
: 
:     sub foo( $bar, $baz, %*advs) {...}
:     foo :expletive bar=>3, baz=>42;

Yes, but only if you put a comma after :expletive, and don't necessarily
expect multimethod dispatch in 6.0.0, which may be restricted to positional
parameters.

: If I think my function would look better with the :adverb
: next to the function, and still have positional parameters,
: I can just declare foo with no named positional parameters,
: and any parameters after the adverb will go in the slurpy array.

That's always an option, as long as you're willing to take the speed hit
of parsing the args yourself, and can do it unambiguously without the
need for <==.

: Larry also shows this example:
: 
: >     @a.sort:quick:{ +$_ }   # both adverbs apply to .sort
: 
: Would that work for the functional form too?
: 
:      sort :quick :{ +$_ } @a;

Not unless you put a comma after the closing curly.  Otherwise it's
expecting an operator.

: Does adverbial block find its way into the block parameter,
: which was actually declared as an optional positional parameter
: (of type Criteria)?

I suspect adverbial block can find its way into either splatty
function or splatty scalar.  After all, &foo just means Code $foo,
give or take a 2 bit in the sigil.

Larry

Reply via email to