I'm writing a new module that optimizes sets of conditions into
decision trees. Initially I allowed the user to specify conditions as
strings, and if that condition began with a "!", it would be the
inverse of the condition without the "!".

Advertising

But then I thought, "the user will more than likely have condition
*objects* if the conditions are anything but trivial". Then you can't
just put a "!" on the front. The way Haskell and ML do this is by
allowing data constructors: symbols that can take arguments and be
pattern matched against. I thought that this was a particularly
elegant way to solve the problem, so I implemented it in the
Symbol::Opaque module. Now I want it for Perl 6.
Here's my proposal. Let's generalize the backtick from unit support
into data constructor support. The following are equivalent:
4`meters
`meters(4)
The postfix form is only available for single-argument constructors,
but the prefix form can be used with more than one argument:
`foo(4, 5)
These things don't need to be declared, but you can use a "data"
declaration to give them a type (which does Symbol, the type of all
such constructors):
data Quux (`foo, `bar, `baz);
Now whenever you create a `foo, it is a Quux. These can overlap:
data Foo (`baz);
data Bar (`baz);
A `baz object is now both a Foo and a Bar. These could be easily
extended to allow type signatures, to come up with those nice
type-checked data structures that we're using for PIL. But I'm not
proposing that part yet.
Here's what makes them so useful: they can be bound against:
sub to_SI (`meters($m)) { `meters($m) }
sub to_SI (`feet($f)) { `meters(feet_to_meters($f)) }
Here's an excerpt from my module (perl6ized):
sub invert ($in) {
my `not($x) := $in ?? $x :: `not($in);
}
Or maybe that's:
sub invert ($in) {
`not(my $x) := $in ?? $x :: `not($in);
}
Anyway, the point is that bindings can fail. In boolean context, they
return whether they succeed; in void context, they blow up if they
fail (probably "fail").
As multimethods:
multi invert (`not($x)) { $x }
multi invert ($x) { `not($x) }
Which I like the best.
Pairs are values: like numbers. `foo =:= `foo. They can just have sub-values.