MzScheme's "infix" notation

6 views

felix

Feb 23, 2004, 1:51:44 AM2/23/04
to
While skimming the MzScheme manual I found an interesting syntactic
extension:

(X ... . Y . Z ...)

is transformed by the reader into

(Y X ... Z ...)

Could this been considered useful? And if yes, for what aplications?

cheers,
felix

Anton van Straaten

Feb 23, 2004, 2:30:31 AM2/23/04
to

Maybe it's there for symmetry with ML's 'op' form, which does the opposite.
Or, it's for people like me, who can only marginally comprehend certain
non-commutative relational prefix operators (as described in the thread
"errors in HtDP"). So I can do this instead:

(4 . < . 5) => #t

:o))

Anton
--
; .sig included to bolster self-esteem:
(list->string(call-with-current-continuation(lambda(x)(let*((z(map(lambda
(c)(reverse(cons c(call-with-current-continuation(lambda(k)(list k 0))))))
(string->list"patsonm")))(i(apply max(map car z)))(cs(cddr(assoc i z)))(xs
(append(string->list(case i((4)"ul")((5)"@")((6)"i")((12)"c.")((15)(x cs))
(else"")))cs))(k(cadr(list-ref(map(lambda(i)(list-ref z i))(list 3 0 4 1 2
5 4 4 5 2 3 5 4 1 6))i))))(k `(,@xs ,k ,(+ i 1)))))))

Grzegorz Chrupala

Feb 23, 2004, 7:10:28 AM2/23/04
to

> While skimming the MzScheme manual I found an interesting syntactic
> extension:
>
> (X ... . Y . Z ...)
>
> is transformed by the reader into
>
> (Y X ... Z ...)
>
[ ... ]

Talking about syntactic extensions, is there any scheme implementation
where the following:
(let ((args (list 1 2)))
(+ . args))
would be expanded to this:
(let ((args (list 1 2)))
(apply + args))
or where one could define such an extension? Wouldn't that be a useful
notation?

--
Grzegorz

Shriram Krishnamurthi

Feb 23, 2004, 9:23:25 AM2/23/04
to
Here are a few illustrative examples excerpted at random from the PLT
source:

(unless (text%-obj . is-a? . html-text<%>)

(and (val . is-a? . app%)

((syntax-position x) . >= . (syntax-position y))

(symbol? any? . -> . void?)

(let* ([whole (if (number . < . 0)

(define mixin-contract (class? . ->d . subclass?/c))

Shriram

Barry Margolin

Feb 23, 2004, 11:26:58 AM2/23/04
to
grze...@pithekos.net (Grzegorz Chrupala) wrote:

> Talking about syntactic extensions, is there any scheme implementation
> where the following:
> (let ((args (list 1 2)))
> (+ . args))
> would be expanded to this:
> (let ((args (list 1 2)))
> (apply + args))
> or where one could define such an extension? Wouldn't that be a useful
> notation?

I think it would be a bad idea. Throughout the language, wherever a
variable can appear and be evaluated, so can an arbitrary expression.
But that wouldn't be the case here.

(+ . (some function call))

is syntactically equivalent to:

(+ some function call)

so it won't be treated like:

(apply + (some function call))

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Grzegorz Chrupała

Feb 23, 2004, 12:30:37 PM2/23/04
to
Barry Margolin wrote:

> I think it would be a bad idea. Throughout the language, wherever a
> variable can appear and be evaluated, so can an arbitrary expression.
> But that wouldn't be the case here.
>
> (+ . (some function call))
>
> is syntactically equivalent to:
>
> (+ some function call)
>
> so it won't be treated like:
>
> (apply + (some function call))
>

Throughout the language, apparently with the exception of SYNTAX-RULE, where
(+ . args) can be used, and where the problem you point at actually does
arise. Compare the trivial macro on the left, which works correctly, with
the one on the right, which doesn't.

(define-syntax plus | (define-syntax plus1
(syntax-rules () | (syntax-rules ()
((plus . args) | ((plus1 . args)
(+ . args)))) | (+ . (map (cut + 1 <>) args))))

I have to agree that maybe it's not such a good idea then.
Cheers,
--
Grzegorz Chrupała | http://pithekos.net | grze...@jabber.org
gosh -bE "begin (print \
(map (cut number->string <> 36) '(18 806564 1714020422))) (exit)"

Eli Barzilay

Feb 23, 2004, 2:30:29 PM2/23/04
to
grze...@pithekos.net (Grzegorz Chrupala) writes:

> Talking about syntactic extensions, is there any scheme implementation
> where the following:
> (let ((args (list 1 2)))
> (+ . args))
> would be expanded to this:
> (let ((args (list 1 2)))
> (apply + args))
> or where one could define such an extension? Wouldn't that be a useful
> notation?

This is one of the things I added to Swindle and not sure about
keeping it. To avoid confusion, it works only for identifiers, so the
(+ . (some function call)) example is still behaving in the same way.

--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!

Alex Shinn

Feb 23, 2004, 9:56:32 PM2/23/04
to

But this just doesn't make any sense. It's overloading "." to mean
something completely different from what it means in other contexts. It
also doesn't gain you anything: all of the above cases are more concise
in straight prefix notation, and easier to read in the context of prefix
Scheme source. It's the worse type of infix hack because it's not even
extensible to general infix.

If you really want to be able to use infix where it's actually more
readable and/or concise than prefix (e.g. dense math formulae), then
provide one of the full-blown infix macros that keep getting proposed
time and again. Make it something like:

(with-infix (- b + (b ^ 2 - 4 * a * c) ^ 0.5) / 2 * a)

and if your Scheme is really fancy you can extend the reader to treat
{...} as read-syntax for (with-infix ...)

Then write a SRFI that says "This is how you do infix - don't do it

--
Alex, who thinks (/ (- (sqrt (- (square b) (* 4 a c))) b) (* 2 a)) is
not only shorter but easier to read

Shriram Krishnamurthi

Feb 24, 2004, 7:16:35 AM2/24/04
to
Alex Shinn <fo...@synthcode.com> writes:

> But this just doesn't make any sense.

Okay.

> something completely different from what it means in other contexts.

Otherwise the original poster wouldn't have asked the question, no?

(I won't be so crass as to point out that "." already means "optional
argument" in one context and "improper list" in another context, so
perhaps this veneration for "."'s consistency is already unwarranted.)

> It
> also doesn't gain you anything: all of the above cases are more concise
> in straight prefix notation, and easier to read in the context of prefix
> Scheme source.

Okay.

> It's the worse type of infix hack because it's not even
> extensible to general infix.

Okay (but is it the *worst* type?).

> If you really want to be able to use infix where it's actually more
> readable and/or concise than prefix (e.g. dense math formulae), then
> provide one of the full-blown infix macros that keep getting proposed
> time and again. Make it something like:
>
> (with-infix (- b + (b ^ 2 - 4 * a * c) ^ 0.5) / 2 * a)
>
> and if your Scheme is really fancy you can extend the reader to treat
> {...} as read-syntax for (with-infix ...)

Okay.

> Then write a SRFI that says "This is how you do infix - don't do it

Yes, sir.

Shriram

Lauri Alanko

Feb 24, 2004, 10:04:50 AM2/24/04
to
In article <barmar-C0EA92....@comcast.ash.giganews.com>,

Barry Margolin <bar...@alum.mit.edu> wrote:
> (+ . (some function call))
>
> is syntactically equivalent to:
>
> (+ some function call)

It's not. As a <datum> they represent the same data structure, but the
former is not a valid scheme expression while the latter is, so
clearly there is a syntactic distinction.

Eg. syntax-case can distinguish between those two forms, so it's
fairly easy to implement the proposed extension.

Lauri Alanko
l...@iki.fi

Joe Marshall

Feb 24, 2004, 12:29:55 PM2/24/04
to
Lauri Alanko <l...@iki.fi> writes:

I don't believe that syntax-case can distinguish between these.

Lauri Alanko

Feb 24, 2004, 1:25:01 PM2/24/04
to
In article <wu6cjs...@ccs.neu.edu>, Joe Marshall <j...@ccs.neu.edu> wrote:

> Lauri Alanko <l...@iki.fi> writes:
> > Eg. syntax-case can distinguish between those two forms, so it's
> > fairly easy to implement the proposed extension.
>
> I don't believe that syntax-case can distinguish between these.

Ah, sorry, this seems to be a PLT extension. See syntax-e in

Lauri Alanko
l...@iki.fi

Ray Dillinger

Feb 24, 2004, 2:40:50 PM2/24/04
to

??? Syntax-case ought not be able to distinguish between these two forms.
Syntax-case operates on list structure, and these have identical list
structure.

Bear

Lauri Alanko

Feb 24, 2004, 3:24:53 PM2/24/04
to
In article <403BAAF9...@sonic.net>,

Ray Dillinger <be...@sonic.net> wrote:
> > Eg. syntax-case can distinguish between those two forms, so it's
> > fairly easy to implement the proposed extension.
>
> ??? Syntax-case ought not be able to distinguish between these two forms.
> Syntax-case operates on list structure, and these have identical list
> structure.

Even in Dybvig's original paper, syntax-case operates explicitly on
syntax objects, although it also accepts lists as an added
convenience.

But apparently syntax-e, which distinguishes between dotted pairs and
lists, is a PLT extension.

Lauri Alanko
l...@iki.fi

Joe Marshall

Feb 24, 2004, 4:06:11 PM2/24/04
to
Lauri Alanko <l...@iki.fi> writes:

The syntax objects have enough structure to recover the difference,
but the pattern matched against does not. This would cause problems
if you used `read' to get some data and then attempted to syntax it
rather than use the repl to get the syntaxed form.

Alex Shinn

Feb 24, 2004, 8:29:51 PM2/24/04
to
At 24 Feb 2004 07:16:35 -0500, Shriram Krishnamurthi wrote:
>
> > something completely different from what it means in other contexts.
>
> Otherwise the original poster wouldn't have asked the question, no?

Exactly, which is why I'm responding that I don't think it's a good
idea.

> (I won't be so crass as to point out that "." already means "optional
> argument" in one context and "improper list" in another context, so
> perhaps this veneration for "."'s consistency is already unwarranted.)

They're the same thing, when you view the lambda arguments as a pattern
matching on the whole argument list. It's arguable if this is a natural
view to take or not, but it at least makes sense and "chunks" well.
People don't stop and wonder in (x . rest) whether the rest comes before
or after the x.

When I said "completely" unrelated I meant precisely that. It overloads
"." not only syntactically but conceptually. Though I'd be open to
ideas about how to reason the infix notation :)

> > It's the worse type of infix hack because it's not even
> > extensible to general infix.
>
> Okay (but is it the *worst* type?).

You're so stumped for a counter argument that you have to stoop to
correcting my grammar?

--
Alex

Shriram Krishnamurthi

Feb 24, 2004, 9:15:00 PM2/24/04
to
Alex Shinn <fo...@synthcode.com> writes:

> You're so stumped for a counter argument that you have to stoop to
> correcting my grammar?

No, I'm that bored by arguments about syntax.

Shriram

Alex Shinn

Feb 24, 2004, 9:28:59 PM2/24/04
to

Then don't argue :) Better yet, don't foment arguments by creating new
syntax.

I'm bored by syntax too, which is why I half-seriously suggested writing
an infix SRFI so the topic doesn't keep coming up.

--
Alex

Michele Simionato

Feb 25, 2004, 6:17:53 AM2/25/04
to
grze...@pithekos.net (Grzegorz Chrupala) wrote in message news:<8b9e2260.04022...@posting.google.com>...

> Talking about syntactic extensions, is there any scheme implementation
> where the following:
> (let ((args (list 1 2)))
> (+ . args))
> would be expanded to this:
> (let ((args (list 1 2)))
> (apply + args))
> or where one could define such an extension? Wouldn't that be a useful
> notation?

When I started learning Scheme (not so long ago) I didn't know about
"apply" and I expected something like (+ . args) to work. I see now
that this would be a bad idea due to the confusion with the notation
for improper lists. Nevertheless, having a better notation
for "apply" would not be such a bad thing. For instance, Python removed
the "apply" operator by using the * notation, i.e. in Python f(*args)
means apply(f,args) and everybody feels this improved readability.
In Scheme one could implement something similar, maybe using a
different character.

I haven't done any serious testing, but this works in simple cases:

(define apply-char '~) ; or any other identifier

;; convert the magic apply char into calls to apply
(define (magic-apply ls)
(define found-apply-char #f)
(define output
(fold-right
(lambda (el out)
(cond
((list? el) (cons (magic-apply el) out))
((eq? el apply-char) (set! found-apply-char #t) out)
(else (cons el out)))) '() ls))
(if found-apply-char (cons 'apply output) output))

(define-macro (with-magic-apply . body)
(magic-apply (cons 'begin body)))

(with-magic-apply
(define (anti f)
(lambda args (not (f ~ args)))))

and the code would be expanded to

(begin
(define (anti f)
(lambda args (not (apply f args)))))

The discussion about what char to use as magic char is open ;)

Michele Simionato

Lauri Alanko

Feb 25, 2004, 6:25:00 AM2/25/04
to

Michele Simionato <michele....@poste.it> wrote:
> When I started learning Scheme (not so long ago) I didn't know about
> "apply" and I expected something like (+ . args) to work. I see now
> that this would be a bad idea due to the confusion with the notation
> for improper lists.

Why would this be any worse than the confusion between eg. the
notation for lambda abstractions and lists with the symbol 'lambda as
the first element?

Lauri Alanko
l...@iki.fi

Michele Simionato

Feb 27, 2004, 2:08:01 AM2/27/04
to
Lauri Alanko <l...@iki.fi> wrote in message news:<c1i0mc\$f7d\$1...@oravannahka.helsinki.fi>...

I am not sure if I understand your concern and probably I am giving
to you an answer which is not what you asked, but anyway ...

Consider the following example:

(apply + 1 numbers))

With the "~" notation I would write it as

(+ 1 ~ numbers))

The converter I posted would read 'define as a symbol, '(add1 . numbers)
as a pair, '(+ 1 ~ numbers) as a list containing the symbol ~ and would
convert it into '(apply + 1 numbers). With the dot notation there would
be confusion, since in

(+ 1 . numbers))

'(+ 1 . numbers). A smarter converter could understand than the first
improper list is an argument list, since it is preceded by a 'define,
and convert only the second one, but I think this would be asking
for trouble. Also, for the sake of the reader, I think to distinguish
between the two concepts would be better. BTW, I am not doing
any proposal here, I think "apply" is fine, it was just for the sake
of the exercise.

Michele Simionato

Michele Simionato

Feb 27, 2004, 2:09:41 AM2/27/04
to

I didn't find this extension particularly useful; I tried to use it
to write mathematical formulas but the result was not that readable.
Not only the overload of "dot" is questionable, but even using
another char would not help readability, at least IMHO. Having a
"with-infix" macro would make more sense than the dot notation.

If you are looking for ideas to steal from MzScheme, I would forget
are quite handy.

Michele Simionato

Lauri Alanko

Feb 27, 2004, 1:39:45 PM2/27/04
to
Michele Simionato <michele....@poste.it> wrote:
> > > When I started learning Scheme (not so long ago) I didn't know about
> > > "apply" and I expected something like (+ . args) to work. I see now
> > > that this would be a bad idea due to the confusion with the notation
> > > for improper lists.
> >
> > Why would this be any worse than the confusion between eg. the
> > notation for lambda abstractions and lists with the symbol 'lambda as
> > the first element?
>
> I am not sure if I understand your concern and probably I am giving
> to you an answer which is not what you asked, but anyway ...

Your argument seems to be mostly "I cannot implement it". This ought
to do the job in PLT Scheme:

(module dotapply mzscheme
(provide (rename app #%app))
(define-syntax (app stx)
(define (improper->list l)
(if (pair? l)
(cons (car l) (improper->list (cdr l)))
(list l)))
(syntax-case stx ()
((_ . a)
(let ((e (syntax-e #'a)))
(if (and (pair? e) (not (list? e)))
#`(#%app apply #,@(improper->list e))
#'(#%app . a)))))))

> Also, for the sake of the reader, I think to distinguish
> between the two concepts would be better.

Here the two concepts are apparently syntactic sugar for apply, and
the dot is also used for improper list literals. And it is used in
syntax-rules and syntax-case for pattern matching "expression
splices". Yet another use isn't _that_ big a deal.

Especially considering that the entire syntax of scheme is _based_ on
overloading: a term of the form (t1 t2 t3) can mean anything at all
depending on the context and on the particular values of the
constituent terms...

Lauri Alanko
l...@iki.fi