Simply, Quantum::Superpositions (hereafter called Qm::Sp) allows one
to replace code like ($x == 1 || $x == 3 || $x == 5 || $x == 7) with
($x == any(1, 3, 5, 7)) -- decreasing keystrokes and repetition.
and a similar equivalence between a function called 'all' and the &&
operator. (In Qm::Sp's case this works by creating "superpositions" of
the data given, which are actually first class objects, but that's not
what I'm interested in for this.)
I wondered if this could be implemented as a "continuation macro"
system, where the macro receives information not only about the
expression it is transforming, but the expression which contains
that expression, also. It is that outer expression which is transformed.
This way, eg. (= (any 1 3 5 7)) could be auto expanded to
(or (= x 1) (= x 3) …).
Such a definition might look like this (in a Common Lisp-like manner, to
keep matters like hygiene out of this theoretical discussion):
(defcmacro all xs kexp self
`(and ,(mapcar #'(lambda (x)
(list-replace kexp self x)) xs)))
* defcmacro is a primitive special form for defining a continuation macro.
* all is the name of this macro
* xs is the name we assign to a list of arguments
(previous three are just like defmacro/defun)
* kexp is the "continuation expression", the expression which contains
the expression which caused the expansion of the continuation macro.
* self is the complete expression being expanded
* list-replace is a utility function (list-replace list old-val new-val)
which searches the list for old-val, replacing each object equal to it
with new-val. (It returns a new list, not modifying the original.)
My concern is that it will lead to subtle bugs and confusing code, and
that this is a generalisation which doesn't need to be made, and that
it would be better to have first-class superpositions/junctions like
in Qm::Sp and Perl 6.
— dpk.
What I find dubious about the feature is that it's a subset of array
programming written backwards.
For contrast, here's the first example (from the module description) in
Python:
result = numpy.array([1, 2, 3]) * 2
if any(result == 4): print "fore!"
Martin
Here's the synopsis with standard Python lists (although most of
Qm::Sp could be written in Python with just operator overloading):
use Quantum::Superpositions;
if ($x == any($a, $b, $c)) { ... }
if x in [a, b, c]:
while ($nextval < all(@thresholds)) { ... }
while nextval < min(thresholds):
$max = any(@value) < all(@values);
min_ = min(values)
max_ = (v for v in value if v < min_).next()
print index( any("opts","tops","spot"), "o" );
# why would you want to do this?
strings = ['opts', 'tops', 'spot']
print filter(lambda idx: idx != -1, map(lambda s: s.find('o'), strings))[0]
print index( "stop", any("p","s") );
print re.search('[ps]', 'stop').start()
I think there's a difference between doing the same thing and arriving
at the same result.
Martin
Considering Qm::Sp's very high potential for confusion or accidentally
inefficient code (I believe several of the examples fall into the
latter class), if explicitly arriving at the same result for its own
examples takes only a small amount of additional code, there isn't a
very strong argument for creating a new type of macro just to
implement it.