In a message dated Thu, 29 Aug 2002, Damian Conway writes: > And, of course, the C<is valued> property would smart-match its value > against the corrresponding argument, so one could also code optimized > variants like: > > sub repeat is multi ($desc is valued(1), &body) { > body(1); > } > > sub repeat is multi ($desc is valued(0), &body) { > } > > sub repeat is multi ($desc is valued(['A'..'F']), &body) { > die "Can't repeat hexadecimally"; > } > > Come to think of it, maybe the property name probably should be C<is when>.
This is very nice. But ordering of multimethod declarations suddenly matters, doesn't it? With simple multimethods based on class structures, you use the best match (if the actual argument is Integer, I'll prefer the method where the corresponding signature is Integer, then Rational, then Real, then Complex), right? But with this mechanism, you just have boolean acceptance of the argument, so I assume that ordering will be how you decide which multimethod to call--the first to accept its argument wins. If you want to define a new multimethod using the valued() property, ou're left in a slightly awkward situation here--you can't install a multimethod with a prior ordering to what's already been defined, can you? So, if you have something like the following: module Repeater { sub repeat is multi ($desc is valued(/\d+/), &body) { ... } } # In a later file sub Repeater::repeat is multi ($desc is valued(/\d*<[02468]>/), &body) { ... } # deal with even cases specially That second sub would never get called, would it? In general, though, I like it. I've found myself making a lot of use lately of the Virtual Constructor pattern, where you offer some free-form data to a bunch of classes and they tell you which one can best instantiate it, i.e., sub createObject (*@data) { my @scores = for @.classes { $_.recognize(@data) but classOf($_)}; my $bestClass = (sort byScore @scores)[0].classOf; return $bestClass.new(@data); } # Is my syntax right here? A valued() property would obviate the common case where the recognition scores are all boolean--I'd just have each class define a createObject multimethod instead. It would be kind of nice if the valued() property could return a value, however. > > I don't particularly like the old map and grep syntax. > > Recently someone suggested to me (sorry, whoever it was, my memory > is still in anyother timezone) that, since C<given> returns a value: > > $val = given $digit { > case [0..9] { $_ } > case ['A'..'F'] { 10+ord($_)-ord('A') } > default { undef } > }; > > then maybe the other control structues should as well: > > @squares = map { $_**2 } @nums; > > @squares = for @nums { $_**2 }; This makes a lot of sense to me--notice I used it in my example above. :-) > Of course, this example is trivially done with a hyperoperation: > > @ squares = @nums ^** 2; > > But more complex examples could easily be constructed where even C<map> > looks clunky and a list context C<for> would be a nice solution. > > It would also solve the problem of early escape: > > @smallsquares = for @nums { last if $_ > 10; $_**2 }; Yes. I think it works great as a C<map> replacement. For a C<grep> replacement, it's a little unwieldy: P5: @odds = grep { $_ % 2 } @nums; P6: @odds = for @nums { next unless $_ % 2; $_}; Trey