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



Reply via email to