As a heads-up, ...
I've decided to make a couple of related large refactorings to Muldis D for the
next release or two of the spec.
Feedback on this plan is welcome, but not required.
1. Currently, any built-in function which could conceivably be N-adic is
N-adic, and that is the only version. There are several dozen of these,
including [+, *, ~, and, or, join, union, intersect, min, max] etc.
The planned change is that, for any N-adic functions whose definition is the
repetition of a dyadic operation (such as everything in the above list), the
N-adic function would be replaced with a dyadic version, and users wanting to
use N-adic syntax must then use a generic reduction function, giving the dyadic
function as a closure argument to it.
Said generic reduction function already exists, to support user-defined N-adic
functions, but now it will be used for all the relevant built-ins as well.
The primary reason for this change is to let user code be simpler, because for
the majority of the times when they just want to have 2 arguments for a
function, they can supply them directly rather than having to construct a
set/array/bag/etc containing them, as N-adic versions require.
Moreover, users won't have to remember which functions need to be called with a
collection argument just because they could possibly be used with more than 2
arguments; so the function-call syntax for addition and subtraction will now be
the same, rather than different.
A related change is that the syntax for defining functions, and the system
catalog structures they parse into, will be enhanced so that one can now
explicitly declare traits of the functions. For example, whether dyadic
functions are self-commutative or associative or idempotent or symmetric etc.
An additional trait would declare the identity value of the function where
applicable. Other traits might be possible.
Advantages of this change is that implementations, or user code, can discover
and utilize, such as for optimization, automatically how to treat the functions
such as in a generic reduction, to produce the correct results efficiently.
I have no plans currently for letting the syntax/catalog declare the interaction
of different functions, such as when foo() commutes over bar(), simply because
this may be complicated. But implementations can of course have hard-wired
knowledge for say commuting restrictions/filters relative to joins.
2. Another major planned change is the creation and exploitation of some
meta-operators, in the same sense as Perl 6 has them. See
http://perlcabal.org/syn/S03.html#Meta_operators for reference.
I can think immediately of 3 meta-operators that I would use, and possibly a
4th.
The first one is logical-not.
Any Bool-resulting op "foo" can have "!" prepended to the operator itself to
reverse the result. For example, rather than having to write "!(x foo y)" or
"not x foo y", they can write "x !foo y" or maybe "x not-foo y". Both of these
would parse into the same thing as if you had written them in generic functional
form, as "not(foo(x,y))". But for the sole purpose of preserving the user's
lexical intent, I may make an alias function for "not" which the parser uses
when parsing "x !foo y" versus "!(x foo y)", so that a code generator later can
make code closer to what the user wrote.
Currently, every system-defined Bool-resulting function "foo" has an associated
function "not_foo" which takes the same arguments but returns the opposite
result. This was a historical decision based on several reasons including the
desire to better preserve the user's chosen syntax. All current "!foo" syntax
is system-defined and not extensible, mapping to the "not_foo" function.
A large part of the change would involve eliminating all the system-defined
"not_foo" functions so that users must write "not(foo())" instead fundamentally,
though the new meta-operator would mean that most common code, using "x != y"
say, would not change, and hence this is a quasi-internal change.
I fully expect now that any decent implementation can easily optimize away any
changes brought on by the conceptually larger call stack that the use of
meta-operators would have, such as by compiling into implementation-native
combined operations.
The second one is assignment.
Any function "foo" can effectively become an updater by prefixing ":=". For
example, any "x := x foo y" can be written as "x :=foo y", and both would parse
into the same thing as "assign(&x,foo(x,y))" would either way. But once again,
I may add an alias for "assign" to use by the parser to preserve the user's
actual syntax.
Currently, Muldis D has a couple dozen updaters named "assign_foo" that are
typically the same as functions "foo" (except when "foo" is N-adic) but for
assigning rather than returning the result, as in the previous example. And you
can only use ":=foo" syntax for a subset of these updaters, not anything else.
A large part of the change would be in eliminating all of these updaters, and
the meta-ing of :=foo means that you can use it with any function having the
function infix/etc syntax.
The third one is reduction, related to change #1.
I'm not sure yet what syntax this would take, but Perl 6's version puts square
brackets around the other operator being meta'd, eg letting one say "[+]
(1,2,3)" rather than "1 + 2 + 3".
Another candidate for adoption is
http://perlcabal.org/syn/S03.html#Hyper_operators but that I see the usefulness
of this as being more limited as the generic relational "map" or "extend" etc
provides the same hyper-meta functionality. But this alternate hyper-operator
type syntax may be useful for sets/arrays/bags, if not relations in general.
See http://github.com/muldis/Muldis-D/commit/460f936 for my ramblings on these
plans as TODO file items; some of this I've reworded in this email.
Feedback on this plan is welcome, but not required.
Thank you. -- Darren Duncan
_______________________________________________
muldis-db-users mailing list
muldis-db-users@mm.darrenduncan.net
http://mm.darrenduncan.net/mailman/listinfo/muldis-db-users