top | item 18638422

(no title)

herrosheep | 7 years ago

Things like this seem like odd design choices:

  my @menu = <hamburger fries milkshake>;
  say @menu.contains('hamburger');            # True 
  say @menu.contains('hot dog');              # False 
  say @menu.contains('milk');                 # True! 
  say @menu.contains('er fr');                # True! 
  say @menu.contains(<es mi>);                # True!

discuss

order

xisukar|7 years ago

From https://docs.perl6.org/routine/contains, `contains` coerces its invocant to a string and searches for a substring starting from a certain position (index 0 by default):

    # Let's drop `<>` (quote-words constructor) and 
    # use a more familiar array of strings:
      
    my @menu = 'hamburger', 'fries', 'milkshake';
      
    # Let's look at the definition of the `Str` method in 
    # the `List` class from which the `Array` class inherits:
    
    #`{
      method Str(List:D: --> Str:D)
      Stringifies the elements of the list and joins
      them with spaces (same as .join(' ')).
    }

    # Thus, after being stringfied, @menu is treated as 
    # the string 'hamburger fries milkshake'
    
    # With this is in hand, we can gauge the possible
    # result of the following statements:
    
    say @menu.contains('hamburger');            # True 
    say @menu.contains('hot dog');              # False 
    say @menu.contains('milk');                 # True
    say @menu.contains('er fr');                # True 
    say @menu.contains(<es mi>);                # True


If you'd like instead to search the array for words as elements, we could use Perl 6's set functions. However, I don't know if they're as performant as regular string searches:

    say 'hamburger' (<=) @menu;  # True 
    say 'fries' (<=) @menu;      # True 
    say 'hot dog' ∈ @menu;       # False 
    say 'milk' ∈ @menu;          # False 
    say 'er fr' ∈ @menu;         # False 
`∈` is the unicode equivalent of `(<=)`.

---

I'm not sure if I'm missing something in the "odd design choices" in this specific case so it'd be great if you could elaborate a little bit further here.

lizmat|7 years ago

The ASCII equivalent of `∈` is `(elem)`.

raiph|7 years ago

English contains ambiguous words. What does "contains" mean in the previous sentence? In P6 it means searching a string for a substring. Your code asks P6 to treat @menu as a string. If you want to treat it as a list and grep that list then use grep:

    my @menu = <hamburger fries milkshake>;
    say so @menu.grep('hamburger');            # True 
    say so @menu.grep('hot dog');              # False 
    say so @menu.grep('milk');                 # False 
    say so @menu.grep('er fr');                # False 
    say so @menu.grep(<es mi>);                # False

b2gills|7 years ago

You are sort-of right.

It should have used a different word.

A similar example would be the word `length`.

There is no `length` in Perl 6 because it is ambiguous. Instead there is `.elems` and `.chars`.

It is perhaps even a worse because there are other languages which use `contains` to see if the container has a given element.