"Continuation macros"

38 views
Skip to first unread message

David Kendal

unread,
Feb 24, 2012, 5:43:09 PM2/24/12
to ll-...@googlegroups.com
One of the most interesting Perl 5 modules, which seems to be
becoming a core language feature in Perl 6 as "junctions", is
Quantum::Superpositions. <http://dpk.org.uk/1b>

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.

Manuel Simoni

unread,
Feb 27, 2012, 12:00:44 PM2/27/12
to LL.next
On Feb 24, 11:43 pm, David Kendal <dpken...@dpk.org.uk> wrote:
> One of the most interesting Perl 5 modules, which seems to be
> becoming a core language feature in Perl 6 as "junctions", is
> Quantum::Superpositions. <http://dpk.org.uk/1b>
>
> 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.

This Perl 6 feature, like the rest of the language, is highly dubious.

How often do you see a condition like ($x == 1 || $x == 3 || $x == 5
|| $x == 7) in well-factored code?

Manuel

Martin Kühl

unread,
Feb 27, 2012, 12:33:53 PM2/27/12
to ll-...@googlegroups.com

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

comex

unread,
Feb 27, 2012, 4:13:28 PM2/27/12
to ll-...@googlegroups.com
On Mon, Feb 27, 2012 at 12:33 PM, Martin Kühl <martin...@gmail.com> wrote:
> 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!"

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()

Martin Kühl

unread,
Feb 27, 2012, 4:34:27 PM2/27/12
to ll-...@googlegroups.com
On Mon, Feb 27, 2012 at 22:13, comex <com...@gmail.com> wrote:
> On Mon, Feb 27, 2012 at 12:33 PM, Martin Kühl <martin...@gmail.com> wrote:
>> 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!"
>
> Here's the synopsis with standard Python lists (although most of
> Qm::Sp could be written in Python with just operator overloading):
[snip]

I think there's a difference between doing the same thing and arriving
at the same result.

Martin

Peteris Erins

unread,
Feb 27, 2012, 4:40:13 PM2/27/12
to LL.next
Remind me of logic variables. Not sure it's the semantics in question,
but Narrowing http://en.wikipedia.org/wiki/Curry_(programming_language)#Narrowing
is an interesting concept. I'd like to think that is more the point
here than being able to save characters on a single if statement.

While `any` is a finite domain constraint on the logic variable it
represents, `all` is a bit more interesting from this perspective. I
suppose you can do it via failure of an inverted `any`.

--
Peteris Erins

On Feb 27, 5:33 pm, Martin Kühl <martin.ku...@gmail.com> wrote:

comex

unread,
Feb 27, 2012, 5:04:10 PM2/27/12
to ll-...@googlegroups.com

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.

Gabe

unread,
Feb 27, 2012, 7:56:07 PM2/27/12
to ll-...@googlegroups.com
Arguing about Perl syntax or semantics is a bit like arguing about which end of the camel smells worst. But, the person who wrote this gave an absolutely stunning talk -- one of my favorites -- that I think everyone here might be interested in:


You learn a bit about why what he is trying to capture in the module, which may illuminate some of the semantics that might be transferrable.

-Gabe
Reply all
Reply to author
Forward
0 new messages