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 "!".

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.

Reply via email to