On Tuesday, March 25, 2003, at 11:08 AM, Jonathan Scott Duff wrote:
On Tue, Mar 25, 2003 at 10:42:39AM -0800, Michael Lazzaro wrote: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
While this looks pretty in email, it makes me wonder what the :: operator does outside of regular expressions and how that operator interacts with ??::
Well, := is the binding operator, and ::= is the "compile-time" binding operator. For some definition of "compile-time"(?)... I'm not sure whether it can be reused for this "init-time" purpose or not. So ::= does what := does, but does it sooner. :-)
It has been proposed on several occasions that
$foo ??= 'baz' :: 'zap';
be equiv to
$foo = ($foo ?? 'baz' :: 'zap');
But I don't think ??= and ::= conflict in any (technical) way.
And don't forget these other argument initializations:
sub foo($x &&= 'blah') {...} # sets $x whenever $x is true sub foo($x += 1) {...} # add 1 to whatever $x given sub foo($x -= 1) {...} # subtract 1 to whatever $x given sub foo($x *= 2) {...} # multiply by 2 whatever $x given sub foo($x /= 2) {...} # divide by 2 whatever $x given sub foo($x ~= "foo") {...} # Append "foo" to whatever $x given
True, most of those are not useful. But the ones that potentially are (::=, //=, ||=), should we support them? It would seem that all three of those notions are quite often used, even in quickndirty code.
I'm arguing for these three defaulting options in particular, but my more encompassing argument is the wrapper-like notion that signatures should be able to specify assertions, invariants, and initializations that may then be "inherited" by all implementations of that function/method.
Placing such extensive capabilities in the sig is especially useful if we can 'typecast' subs, as others have pointed out.
class mysub is sub(...big long signature...) returns int {...}
sub foo is mysub { # actual implementation goes here }
sub bar is mysub { # same signature, different function }
If ...big long signature... contains initializations and assertions that are required to be shared by all sub implementations, than it makes the sig a quite powerful thing. Sure, a complex sig could be pretty big. But it's one big thing, as opposed to repeating the same assertions in N implementations.
MikeL