On Sun, Nov 03, 2002 at 11:17:32PM -0600, Me wrote:
> 
> I started with a simple thought:
> 
>     is given($foo)
> 
> seems to jar with
> 
>     given $foo { ... }
> 
> One pulls in the topic from outside and
> calls it $foo, the other does the reverse --
> it pulls in $foo from the outside and makes
> it the topic.

It comes from is using 'given' as a noun (meaning the same thing as
'topic') instead of a verb. So, this:

  given $foo { ... }

means "make $foo become the given" or "Given-ify $foo". While:

  is given($foo)

means "$foo takes the value of the given".

There may be room for a better parameter name. We considered quite a few
before picking this one, though, and I'm pretty happy with it for now.

> On its own this was no big deal, but it got
> me thinking.
> 
> The key thing I realized was that (naming)
> the invocant of a method involves something
> very like (naming) the topic of a method,
> and ultimately a sub and other constructs.

The similarity is that both are implicit parameters, i.e. they're
accessible to the sub/method but aren't explicitly passed when it's
called. They're not quite the same though, as the C<is given> parameter
is entirely out-of-band (in P5 terms, it wouldn't appear in @_).

Also, both may be the topic under certain circumstances. But then, any
variable can be the topic.

Generally, there's no conceptual link between the invocant of a method
and the topic in the caller's scope. 

> Thus it seems that whatever syntax you pick
> for the former is likely to work well for
> the latter.
> 
> Afaik, the syntax for invocant naming is:
> 
>     method f ($self : $a, $b) { ... }
> 
> But whatever it is, I think one can build
> on it for topic transfer / naming too in a
> wide range of contexts.
> 
> With apologies for talking about Larry's
> colon, something that really does sound
> like it is taboo for good reason, I'll
> assume the above invocant naming syntax
> for the rest of this email.
> 
> So, perhaps:
> 
>     sub f ($a, $b) is given($c) { ... }
>     sub f ($a, $b) is given($c is topic) { ... }
>     sub f ($a, $b) is given($_) { ... }
> 
> could be something like:
> 
>     sub f ($c : $a is topic, $b) { ... }
>     sub f ($c : $a, $b) { ... }
>     sub f ($_ : $a, $b) { ... }
> 
> where the first arg to be mentioned is the
> topic unless otherwise specified.
> 
> (The first line of the alternates is not
> semantically the same as the line it is a
> suggested replacement for, in that the
> current scheme would not set the topic --
> its value would be the value of $_ in
> the lexical block surrounding the sub
> definition. It's not obvious to me why
> the current scheme has it that way and
> what would best be done about it in the
> new scheme I suggest, so I'll just move on.)

Even though both features have something to do with topic, they're
really independent. There are times when it's useful to access the
caller's topic without setting the current topic and times when it's
useful to just set the current topic.

  sub f ($a, $b) { ... } # use neither feature
  sub f ($a is topic, $b) { ... } # topic setting
  sub f ($a, $b) is given($c) { ... } # access caller's topic 
  sub f ($a, $b) is given($c is topic) { ... } # combine

When you have a system with two independent but interacting features,
it's far more efficient to define two independent flags than to define 4
flags to represent the 4 combinations. It's also easier to learn.

> The obvious (to me) thing to do for methods
> is to have /two/ colon separated prefixes of
> the arg list. So one ends up with either one,
> two, or three sections of the arg list:
> 
>     # $_ is invocant:
>     method f ($a, $b) { ... }
> 
>     # $_ and $self are both invocant:
>     method f ($self : $a, $b) { ... }
>     
>     # $_/$self are invocant, $c caller's topic
>     method f ($self : $c : $a, $b) { ... }

Any two constructs with the same syntax but an entirely different
meaning exponentially increase the chance of confusion. Confusion
increases the likelyhood of bugs. Not to mention frustrating the
programmer. 

> One question is what happens if one writes:
> 
>     method f (: $c : $a, $b) { ... }
> 
> Is the invocant the topic, or $c, ie what
> does a missing invocant field signify?

The invocant would be the topic still. It is now with:

    method f (: $a, $b) { ... }

> Jumping to a different topic for one moment,
> I think it would be nice to provide some
> punctuation instead of (or as an alternate
> to) a property for setting 'is topic'. Maybe:
> 
>     method f ($self : $c : $a*, $b) { ... }
> 
> or maybe something like:
> 
>     method f ($self : $c : $aT, $b) { ... }
> 
> (Unicode TM for Topic Marker? Apologies if I
> screwed up and the TM character comes through
> as something else.)

Huffman encoding comes to mind. Is this really common enough to merit a
single punctuation character?

> Anyhow, a further plausible tweak that builds
> on the above colon stuff is that one could
> plausibly do:
> 
>     sub f ($bar : $a, $b) {
>         ...
>     }
> 
> and then call f() like so:
> 
>     f (20 : 30, 40)
> 
> as a shortcut for setting $_ before calling f(),
> ie to set $_ in the body of f to 20, $a to 30.

So, in this system, the colon is used for both explicit parameters and
implicit parameters. Sometimes its only purpose is to set the topic in
the body of the sub/method and sometimes it doesn't set the topic. I'd
prefer more consistency.

> Unfortunately that conflicts with use of colon
> as an operator adverb. Conclusion: if y'all
> end up using a different syntax for specifying
> the variable name of the invocant for a method,
> and go with the extension I suggested earlier
> for replacing 'is given', then maybe the above
> can still work, and maybe it would be a good
> idea to allow it.
> 
> And if you do, I can see a further trick being:
> 
>     given $foo {
>         # $_ = $foo here, hiding outer topic
>     }
> 
>     given $c : $foo {
>         # $_ = $foo here, hiding outer topic
>         # $c = outer $_
>     }
> 
> And likewise for other topicalizers.

It would be much more transparent to simply name the outer topic. It
would be more convenient too, if there are other nested topicalizers.
It's better to attack the problem at the root than to apply a series of
cosmetic fixes.

    given $whatever -> $c {
        given $foo {
            # $_ = $foo here, hiding outer topic
            # $c = outer $_
                }
        for @bar {
            # $c = outer $_
                }
    }

Allison

Reply via email to