I didn't sleep well last night, and woke up with a sudden sense of uncertainty about lhs overloading of smartmatching in almost all cases. I think I didn't sleep well because my brain was working on this, but it's possible that my brain thought of this because it didn't sleep well, and it's nuts. But let's find out together. * Damian Conway <damian@conway.org> [2012-08-23T21:08:27] > Here are six cases where LHS overloading would matter too: > > 1. A lazy string class, which loads text from disk on-demand: > > if ($lazystring ~~ qr/pattern/) {...} > > # i.e. want LazyString's overloading, not a regex match against > # stringified $lazystring object's address No, we want the same as C< $lazystring =~ qr/pattern/ >. That can't be overloaded now, but if it could, that's what we'd want. > 2. An interval class: > > my $reading = Interval->new($raw_data, plus_minus=>$uncertainty); > > if ($reading ~~ 0) {...} > > # i.e. want Interval's overloading, not a numeric match against > # $reading object's address No, we want the same as C< $reading == 0 >, which can be done with current overloading. (In fact, which is done in my own Number::Tolerant for just this means.) > 3. A query-result class, which encapsulates the outcome of a > database lookup: > > my $result = $db->find($query); > > if ($result ~~ 'camel') {...} > > # i.e. want QueryResult's overloading, not string match against > # $result object's address No. Either we're passing the $result to a hunk of code that expects C< $x ~~ 'camel'> to act like `eq` or we're not passing the $result anywhere and we can write a more special-cased dispatch that knows it can call $result->matches > 4. An iterator object: > > my $iter = get_iterator_over($data_structure); > > until ($iter ~~ undef) { > ... > } > > # i.e. want Iterator's overloading, not definedness match against > # $iter object's address if (defined $var and $var ~~ undef) { $rjbs->will( 'cry cry cry' ); } > 5. A DNA sequence object: > > if ($dna_sequence ~~ qr/GATTACA/) {...} > > # i.e. want DNASeq's overloading, not regex match against > # $dna_sequence object's address This is just #1. > 6. Prototyping a smarter dualvar with a Chip-like memory of its origins: > > my $dv_n = SmartDualVar->new(0) > my $dv_s = SmartDualVar->new("zero"); > > say $dv_n; > say 0+$dv_s; > > if ($dv_n ~~ 0) {...} # succeeds > if ($dv_s ~~ 0) {...} # fails > > # i.e. want SmartDualVar's overloading, not numeric matches > # against the $dv_n and $dv_s object's addresses Does C< $dv_s == 0 >? If so, I think the smart match should also succeed. > In other words, every single time an object is the LHS operand of a > smartmatch, we need (at least the option) to be able to have that object > decide how the match should work. I soundly disagree. Every single time the user writes C< $a ~~ "string literal" > we need it to be equivalent to using eq. Otherwise, I see this future: "Well, I used to use `when(4)` here, but it turned out that sometimes I was getting an object that didn't handle being on the lhs of the smart match correctly, so now I write `when { $_ == 4 }`" ...and then we're back to me cry cry crying. David Golden said that "smart matching" was "generic matching." The behaviors you suggested above were not always generic. If you know you've got special data, you should give it a method and there you go. In every case of the dispatch table, the kind of overloading required for the lhs is clear: $b | equivalent to | $a should overload --------+-------------------+----------------------------------------- 1. CodeRef | $b->($a) | nothing; can't be done 2. Object | $b->somecode($a) | nothing; can't be done 3. Regex | $a =~ $b | "" (for now) 4. String | $a eq $b | eq 5. Number | $a == $b | == Cases (1) and (2) most clearly demonstrate the problem to me. It means these two things will not be equivalent: if (sub { return }->($x)) { ... } if ($x ~~ sub { return }) { ... } This seems like complete madness. (As an aside, I imagine what I might do is this: my $object = acquire_object; given ($object->matcher) { when (...) { ... } when (...) { ... } when {...} { ... } } There, I can avoid putting goofy overloads for eq and =~ on the object, but return a proxy that implements them. I still get a nice "compute once" and the compactness of given/when, but we've established that we're working with a particular kind of object. But this idea is definitely less slept-upon than the rest of this post.) -- rjbsThread Previous | Thread Next