Previous chapter: #36: Remove Trivial Logical Operators (Change)

Dylan Design Notes

Dylan Design Notes: #37: Variadic Operators (Change)

#37: Variadic Operators (Change)

Version 1, January 1994 Copyright (c) 1993-1994, Apple Computer
The presence of separate binary and variadic versions of some functions complicates the Dylan language. This design note removes several variadic operators that are no longer needed in infix Dylan, and renames the binary versions of those operators.
Remove the variadic functions *, +, -, and /.

Rename the generic functions binary*, binary+, binary-, and binary/ to *, +, -, and /.

Rename the generic function unary- to negative.

Remove the function unary/.

Remove the variadic functions < and =.

Rename the generic functions binary< and binary= to < and =.

Remove the ability to call <=, >, and >= with more or fewer than two arguments. (/= is already a binary function.)

Remove the variadic functions gcd and lcm.

Rename the generic functions binary-gcd and binary-lcm to gcd and lcm.

Rename the variadic function id? to == and remove the ability to call it with more than two arguments.


Notes

Wporkarounds for removed constructs:
`+`(x, y, z)                    =>       x + y + z

apply(`+`, stuff) => reduce(`+`, 0, stuff)

unary/(x) => 1 / x

map(`+`, s1, s2, s3) => map(method (x,y,z) x + y + z end, s1, s2, s3); `<`(x, y, z) => (x < y) & (y < z)

Note: The workaround is less trivial when y is a more complex expression.
logand(x, y, z)                 =>      logand(logand(x, y), z)

apply(logand, stuff) => reduce(logand, -1, stuff)

gcd(x, y, z) => gcd(gcd(x, y), z)

apply(gcd, stuff) => reduce(gcd, 0, stuff)

apply(lcm, stuff) => reduce(lcm, 1, stuff)

id?(x, y, z) => (x == y) & (y == z) apply(`<`, stuff) => let (init, limit, next, end?, key, elt) = forward-iteration-protocol(stuff); if (end?(stuff, init, limit)) error("at least one argument required."); else let value = elt(stuff, init); let state = next(stuff, init); local method loop (value, state) if (end?(stuff, state, limit)) #t; else let new-value = elt(stuff, state); if (value < new-value) loop(new-value, next(stuff, state)); end if; end if; end method; # assume l-to-r evaluation, else bind temp to first element # before potentially clobbering initial state. loop(elt(stuff, init), next(stuff, init)); end if; apply(id?, stuff) => let (init, limit, next, end?, key, elt) = forward-iteration-protocol(stuff); if (end?(stuff, init, limit)) error("at least two arguments required"); else let value = elt(stuff, init); let state = next(stuff, init); if (end?(stuff, state, limit)) error("at least two arguments required"); else local method loop (state) if (value == elt(stuff, state)) let nstate = next(stuff, state); end?(stuff, nstate, limit) | loop(nstate); end if; end method; loop(state); end if; end if;