On Wednesday, March 19, 2003, at 08:30 AM, Larry Wall wrote:
Well, people *will* write<snip>
state $foo = 0;
The question is what that should mean, and which major set of people we want to give the minor surprise to, and how much effort we want to expend in training to avoid the surprise in the first place. There's something to be said for keeping = as assignment outside of sigs. But it's not clear whether that = is part of a sig...
Most use will be to init with a compile-time constant, so I suppose we could train people to just say:
state $foo ::= 0;
We don't have a word for "START" right now. It's somewhat equivalent to
state $foo //= 0
unless $foo gets undefined, I suppose.
That's where that particular thread ended -- from there, it diverged into a subthread about C<state> behavior within nested subs/closures. Ignoring the closure parts, and getting back to the more generic idea of C<state>:
Assuming we have a static-like scope called C<state>, one can definitely see the use of having an assignment variant for "not yet initialized" or "doesn't yet exist", the proposed spelling of which was C<::=>. That gives us:
state $baz = 0;
state $baz ::= 'blah'; # if doesn't "exist" or not "initialized"
state $baz //= 'blah'; # if $baz is undefined
state $baz ||= 'blah'; # if $baz is false
state $baz &&= 'blah'; # if $baz is true
state $baz ??= 'blah' :: 'blarp'; # if $baz is true|false
Of course, for C<state> scoped vars, C<::=> is the only one that makes much sense, and C<::=> doesn't make much sense for lexical vars. (One could argue that C<=> should just mimic C<::=> for C<state>-scoped, but I'm not going to.)
---
OK, so tying that back in to A6... people have suggested extending //= and/or ::= into signatures. The more I think about it, the better I like this approach, and the more justified it seems. Right now we have:
sub foo($x = 0) {...} # same as C<$x is default(0)>
to set the $x param to 0 _if it was not specified by the caller_. But it is certainly possible to extend the initialization capabilities to be more robust:
sub foo($x = 'blah') {...} # wrong: use one of the below sub foo($x ::= 'blah') {...} # same as C<$x is default('blah')> sub foo($x //= 'blah') {...} # sets $x whenever $x is undefined sub foo($x ||= 'blah') {...} # sets $x whenever $x is false
The utility of this is that it gives the signature significantly more control over the initialization of individual parameters, regardless of the actual function/method "implementation". Maybe sigs _should_ be able to make certain assertions about their arguments, and even adjustments to them, before they hit the 'real' implementation.
There has been some debate about the power that sigs should be given. Specifically, I'm thinking of the old "how do you make an assertion upon an argument" debate of a few months ago, and the terror of ten-line-long function sigs with assertions attached to the various parameters. But it's largely a false debate, I would argue: if you want all possible implementations of a given function/method to share the same precise parameter assertions, they _should_ be specified in one place, not in twenty. (subs are objects, have inheritance, etc... more on this later). But TMTOWTDI, if that's not your style.
Anyway, I can definitely see merit in allowing those particular constructs for the sake of significantly smarter sigs. I can see _practical_ uses for C<::=>, C<//=>, and <||=> -- enough so that they probably should be differentiated, and that I would even propose the C<=> spelling, in sigs, be dropped as ambiguous/meaningless.
?
MikeL