Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smartmatching $item ~~ list does not DWIM (4 ~~ (4,5,6,7)) #5263

Closed
p6rt opened this issue Apr 24, 2016 · 8 comments
Closed

Smartmatching $item ~~ list does not DWIM (4 ~~ (4,5,6,7)) #5263

p6rt opened this issue Apr 24, 2016 · 8 comments

Comments

@p6rt
Copy link

p6rt commented Apr 24, 2016

Migrated from rt.perl.org#127980 (status was 'rejected')

Searchable as RT127980$

@p6rt
Copy link
Author

p6rt commented Apr 24, 2016

From @AlexDaniel

Code​:
say 4 ~~ (4,5,6,7)

Result​:
False

Most people expect that it will check if the list on the RHS contains 4, but that's not what it does. The right way to do it is to use any(4,5,6,7).

Another thing that it could possibly do is to count the number of elements in the list, as in 4 == +(4,5,6,7), but again that's not what it does.

Example above clearly shows that both of these assumptions are wrong.

So what does it do?

The relevant piece of code is here​: https://github.com/rakudo/rakudo/blob/nom/src/core/List.pm#L426 . In other words, it always returns False, but it also returns empty list if RHS list is empty or a RHS list itself if the first element of it is a Match object.

Does it make any sense? Not at all, at least to a typical user.

The proposal is to make it DWIM. That is, make 4 ~~ (4,5,6,7) work like 4 (elem) (4,5,6,7).

See also IRC log​: http://irclog.perlgeek.de/perl6/2016-04-24#i_12386065

@p6rt
Copy link
Author

p6rt commented Apr 25, 2016

From @smls

No, the base behavior does make sense.

The concept of the Perl 6 smart-matching operator, is not "Do whatever operation the developer thinks would be most useful in the given situation so he doesn't have to write it out explicitly".

It is, instead​: "Treat the RHS as a template for Perl 6 values, and test if the LHS fits that template".

When the RHS is a list, this sensibly means that only those values are accepted which are list-like (Iterable) themselves, have the correct number of elements, and where each element smart-matches the corresponding RHS element​:

  say ("foo", "bar", 42) ~~ ("foo", /^b/, Numeric); # True

In case you want to make a one-against-many comparison, you can use Junctions which are built into the language with very simple syntax precisely for reasons like this. This also forces you to be explicit about the *kind* of comparison you want, which is important - e.g. compare​:

  say so 2 == any(<1.0 2.0 3.0>); # True
  say so 2 eq any(<1.0 2.0 3.0>); # False

(This may all seem strange if you come from Python or other languages, but it is a design that resulted from the premise of making Perl 6 an operator-rich language with "coercive operators" that do one specific thing and coerce their inputs accordingly, rather than relying on heavily overloaded generic operators more than necessary.)


That said, two of the edge cases you have discovered, *do* feel pretty strange​:

  - An *empty* RHS list returning self instead of False.
  - A RHS list with a Match as its first element returning self instead of False.

It may make sense to investigate if those edge cases can be "fixed" - but don't throw out the baby with the bathwater.

@p6rt
Copy link
Author

p6rt commented Apr 25, 2016

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Apr 25, 2016

From @AlexDaniel

“[…] it is a design that resulted from the premise of making Perl 6 an
operator-rich language with "coercive operators" that do one specific
thing and coerce their inputs accordingly, rather than relying on
heavily overloaded generic operators more than necessary.)”

I fail to see why an operator-rich language can't throw in a couple of
extra operators to allow easy explicit list comparisons. Like this​:

say ?all(("foo", "bar", 42) Zeq ("foz", "bar", 42))

Note that the code above is not entirely correct because it fails to do
what is required when the number of elements is different. And somehow
there is no Z-like roundrobin in Perl 6 yet. Perhaps another metaop for
comparing lists (let's say M) which would return False if the number of
elements is different could do the trick. Current behavior would then
be achieved with M~~ and the code above will turn into just this​:

say ("foo", "bar", 42) Meq ("foz", "bar", 42)

“It is, instead​: "Treat the RHS as a template for Perl 6 values, and
test if the LHS fits that template".”

Yeah, but current behavior (with $item ~~ list) is not even close to that.

So you make a good point. Instead of making it DWIM, we can
* make it return False for any $item ~~ list comparison
* make it throw an error

These are indeed possible and it will fix the problem. However, I think
that these alternatives are probably not better than having a dwimmy
Another Way To Do It™.

@p6rt
Copy link
Author

p6rt commented Apr 26, 2016

From @LLFourn

I may not be the typical user but I like 4 ~~ (1,2,3,4) not meaning 4 ~~
any(1,2,3,4). I would only want ~~ List to be True if the LHS is Positional
(maybe Iterable) that has the same values in the same order.

If 4 ~~ (1,2,3,4) returns true, shoulnd't (1,4) ~~ (1,2,3,4) also be true?
I don't think we want to go down this path.

LL

On Mon, Apr 25, 2016 at 4​:36 AM Alex Jakimenko <perl6-bugs-followup@​perl.org>
wrote​:

# New Ticket Created by Alex Jakimenko
# Please include the string​: [perl #​127980]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl6/Ticket/Display.html?id=127980 >

Code​:
say 4 ~~ (4,5,6,7)

Result​:
False

Most people expect that it will check if the list on the RHS contains 4,
but that's not what it does. The right way to do it is to use any(4,5,6,7).

Another thing that it could possibly do is to count the number of elements
in the list, as in 4 == +(4,5,6,7), but again that's not what it does.

Example above clearly shows that both of these assumptions are wrong.

So what does it do?

The relevant piece of code is here​:
https://github.com/rakudo/rakudo/blob/nom/src/core/List.pm#L426 . In
other words, it always returns False, but it also returns empty list if RHS
list is empty or a RHS list itself if the first element of it is a Match
object.

Does it make any sense? Not at all, at least to a typical user.

The proposal is to make it DWIM. That is, make 4 ~~ (4,5,6,7) work like 4
(elem) (4,5,6,7).

See also IRC log​: http://irclog.perlgeek.de/perl6/2016-04-24#i_12386065

@p6rt
Copy link
Author

p6rt commented Apr 27, 2016

From @jnthn

On Mon Apr 25 07​:54​:18 2016, smls75@​gmail.com wrote​:

That said, two of the edge cases you have discovered, *do* feel pretty
strange​:

- An *empty* RHS list returning self instead of False.
- A RHS list with a Match as its first element returning self instead
of False.

It may make sense to investigate if those edge cases can be "fixed" -
but don't throw out the baby with the bathwater.

They're there for a very practical, rather than a very beautiful, reason. :-) They are there to make​:

  say 'abc' ~~ m​:g/\d/

And​:

  say 'abc' ~~ m​:g/\w/

Do the right thing, and produce a List of Match results (which may be empty). Even before this, it was decided that `4 ~~ (4,5,6,7)` should not magically mean testing for inclusion in the list (I forget the exact reasoning, but confusion when considering lists of lists would be one good one). There are plenty of other ways to do that, such as​:

  say 4 (elem) (4,5,6,7)

So, ticket rejected since the current behavior is both serving an important purpose and the proposed DWIMmery has, best I can recall, been tried and rejected in the past.

Thanks,

/jnthn

@p6rt p6rt closed this as completed Apr 27, 2016
@p6rt
Copy link
Author

p6rt commented Apr 27, 2016

@jnthn - Status changed from 'open' to 'rejected'

@p6rt
Copy link
Author

p6rt commented Apr 27, 2016

From 1parrota@gmail.com

It appears, then, that the problem is managing the user's
understanding of the construction and expectations about results.

On 4/27/16, jnthn@​jnthn.net via RT <perl6-bugs-followup@​perl.org> wrote​:

On Mon Apr 25 07​:54​:18 2016, smls75@​gmail.com wrote​:

That said, two of the edge cases you have discovered, *do* feel pretty
strange​:

- An *empty* RHS list returning self instead of False.
- A RHS list with a Match as its first element returning self instead
of False.

It may make sense to investigate if those edge cases can be "fixed" -
but don't throw out the baby with the bathwater.

They're there for a very practical, rather than a very beautiful, reason.
:-) They are there to make​:

say 'abc' ~~ m&#8203;:g/\\d/

And​:

say 'abc' ~~ m&#8203;:g/\\w/

Do the right thing, and produce a List of Match results (which may be
empty). Even before this, it was decided that `4 ~~ (4,5,6,7)` should not
magically mean testing for inclusion in the list (I forget the exact
reasoning, but confusion when considering lists of lists would be one good
one). There are plenty of other ways to do that, such as​:

say 4 \(elem\) \(4,5,6,7\)

So, ticket rejected since the current behavior is both serving an important
purpose and the proposed DWIMmery has, best I can recall, been tried and
rejected in the past.

Thanks,

/jnthn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant