Set in Your Ways: Perl 6’s Setty and Baggy Types
perl6advent.wordpress.com
perl6advent.wordpress.com
It's so ugly, with so many arcane things to remember, with so many weird naming conventions that just don't make any sense to me.
> We intersected two sets with the ∩, U+2229 INTERSECTION, intersection operator and received a set that contains only the elements present in both original sets.
I'm not against having built-in Unicode operators, but the non-Unicode version should be the name of the character. What's the non-Unicode version of "∩"? Obviously it's "(&)"! Good thing there are only 57 of them to remember!
I tried to enter "∩" just now in Emacs: (ctrl-x, 8, enter, i, n, t, tab, r, tab, s, e, c, tab). It would have been shorter to just type "intersection"... And why is that called the "Texas" version?
I find that pretty obvious, actually. After all
A ∩ B = { x ∈ A & x ∈ B }And it's still kind of confusing. If the goal is to match math notation then wouldn't (^) or (+) make more sense?
A ∩ B = { x ∈ A ∧ x ∈ B }Not necessarily. & is the ASCII symbol associated with logical 'and' that most programming languages have settled on, including Perl6, so for internal consistency, it makes sense to use it. Also note that the ampersand, while pretty rare, is sometimes used for that purpose in mahematical notation (https://en.wikipedia.org/wiki/List_of_logic_symbols).
That convention has decades of precedence in programming:
int bitset_a = 0x01234567, bitset_b = 0x89ABCDEF;
int bitset_c = bitset_a & bitset_b;
And at least a century in math.It also has an Emacs section. For a more detailed explanation for Emacs see my blog post: https://blog.ciavash.name/2016/01/09/entering-perl6-unicode-...
say 42 ∈ <42 55 1>; # False; ∈ operator cares about object identity
As an outsider, this seems like a huge gotcha. I suppose the weirdest thing (after reading some docs) is why < > quotation is used as a set literal here. Would something like say 42 ∈ (42, 55, 1);
work as expected? Or what would be the canonical way of writing an Int (not IntStr) set literal? perl6 -e 'say 42 ∈ (42, 55, 1)'
True
That works fine -- and probably better than the quote-words operator <>. ∈ works on anything list-like, not just set types.Edit: these things are weird though. https://docs.perl6.org/type/IntStr
Allomorphs are tricky things, but I think it was the right decision to treat them separately in collections.
`Set.new(42, 55, 1)` is the most formal way to create a new set, but Perl 6 provides `set(42, 55, 1)` as a shorthand.
.put for @wanted.combinations.grep: { $materials ≽ [⊎] |$^stuff-we-want };
and the preceding lines for some time, and then read the description, clicked through a few of the links on the different operators and read the explanations of those, and then I finally understood what was happening here. I worry, though, that at this point in my life I would either 1) never be able to remember all this stuff; 2) even if I could remember it, never be in a position where it would dawn on me that whatever I was trying to do was a good fit for it.[1] Meaning I like having lots of features in my toolbox.
[2] And, amazingly, Rakudo is a pretty compact executable compared to most other langs.
In Perl? Never!
> Set types always have True as values, and since we don’t care about iterating over Pair objects in our loop, we use the keys [function] to get just the keys of the set: the email addresses.
The impression I took away from that was that you needed to make sure to pass keys(@set) rather than just @set in the operator, or else you'd get weirdness in the result. Having just installed Rakudo and fired up a REPL to find out for myself what'd happen, I find:
- that my understanding from the post was erroneous
- that there's some kind of weird set/string coercion going on that isn't replicable in the terms the REPL uses to describe it
- that the given examples do not reliably generalize
- that nothing which seems to make sense actually works
- that nothing which seems to work actually makes sense
- that I'm now bleeding slightly from both caruncles.
Having not closely followed the Perl 6 development process, I am very glad to see it has taken on board the frequently uttered and extremely well justified criticism of Perl 5 that it's not consistent enough, and that there are so many syntactic and semantic special cases that no one who doesn't heavily specialize in the language can use it very reliably.
I think you are mistaking `<a b c d>` with a `Set`. `< >` is a shorthand for "give me a `List` of these words" (or in this case, characters). `<a b c d>.Set` would coerce you a `Set` from that list. The set operators coerce by default, so you can pass it a list of words without requiring you to coerce it yourself beforehand.
The OP had some snark to offer on the subject of "Texas" operators, and the documentation lists them by their Unicode glyphs. That they work I get. But I think it's reasonable to gather a sense of second-class citizenship from their presentation.
my $set-of-sets = set $set;
The above will create a new set with $set as its only member.
Are things not working as described by that documentation?
Having read that documentation, I don't believe I saw anything inconsistent with it. I also really don't see what I'm getting here that I can't have in any language with basic collection types, and this is the only language I've ever run across that really wants me to buy new keycaps, which seems like a rather bold UI design choice.
No need for new keycaps :)
The ability to perform native operations on collections is really nice, I agree. But Perl 6 isn't the only language that has it, either. From what I've seen today, it looks like Haskell without the rigor. Maybe that makes it easier to approach, but Perl 5 has long since taught me to mistrust such appealing shortcuts for the long-term cost they impose.
Also all of the Set/Bag/Mix ASCII equivalents are fairly easy to remember or to guess once you know that they all have parens around them. ( as in guess how to spell it, and guess what it does )
(elem) left value is an element of the right value
(cont) left value contains the right value ( dual of previous )
(|) returns a superset of both sides ( or )
(&) returns a set of values that are on both sides ( and )
(-) set that contains the values that are on the left but not the right ( minus )
(^) set that contains the values that are only on one side ( xor )
(<=) left value is a subset or equal to right value ( less than or equal to )
(<) left value is only a subset of right value ( less than )
(>=) (>) duals of previous two
(.) multiset multiplication ( looks a bit like the Unicode version )
(+) Bag/Mix addition
(<+) left value has fewer or equal numbers than right value ( Bag less than or equal )
(>+) left value has more or equal numbers than right value ( Bag greater than or equal )
< a B > (<+) <a B B c> # True
< a B B > (<+) <a B B c> # True
< a B B B > (<+) <a B B c> # False
< a d > (<+) <a B B c> # False
The ones with + all can be thought of as counting variations of the or equal operators.The only one I would really complain about is the multiplication one, and there is nothing stopping someone from doing this:
my &infix:< (*) > := &infix:< (.) >;
If you really don't like them, don't use them.
I mean they are mostly wrappers around other functionality anyway https://github.com/rakudo/rakudo/blob/nom/src/core/set_opera... proto sub infix:<(elem)>($, $ --> Bool) is pure {*}
multi sub infix:<(elem)>($a, Any $b --> Bool) {
$a (elem) $b.Set(:view);
}
multi sub infix:<(elem)>($a, Set $b --> Bool) {
$b.EXISTS-KEY($a); # internal method for implementing $b{ $a } :exists
}