[racket-dev] alt-exp syntax

From: Everett Morse (webj2 at unoc.net)
Date: Tue Oct 12 15:53:35 EDT 2010

A while ago I thought up an alternate syntax that converts directly into 
S-Exp in an effort to reduce the number of parenthesis, hopefully 
simplify the way a program looked, and still be completely compatible 
(including macros) with the current Racket API.  To test out my solution 
I've been using it to implement my projects for CS 450 "Digital Signal 
and Image Processing".  This involves reading and writing image files 
(in PPM or PGM format), using structs for internal representations, 
doing numerical computations, and writing GUI code.

Overall Conclusion:
It does reduce parenthesis, but it isn't necessarily easier to 
understand because you still need markers for all the groupings of 
parentheses. It inter-operates with all Racket features, including 
macros, and I think it makes _some_ code look a little cleaner. But it 
isn't so fantastic that I would advocate it.


Detailed Explanation:

The syntax allows a great deal of freedom in style -- whether the user 
chooses to use a function call notation or a colon, for example -- which 
means 1: sometimes parenthesis are removed and sometimes they aren't, 
and 2: the user could be inconsistent.

Example:
     if( (|a < b|) ):
       doX()
       doY()
     if: and: (|a < b|)
              (|a > 0|)
       doX()
       doY()
It looks cleaner to use "and:" rather than "and(...)", but that means 
the "if" looks stupid with the control-structure syntax "if( e ... ): e 
..." so it just uses the colon syntax instead.  I also tend to use "if" 
with the function application form when it is conceptually inline in an 
expression. (Where an "arithmetic if", or "ternary operator" would be 
used in other languages.)  This matches conceptually with other 
languages, even though it is exactly the same "if" construct used in a 
more control-flow-styled syntax.  This does, however, emphasize that it 
is very easy to be inconsistent in how syntax is used for the same 
operation.

Here's another example, which shows OO code looking reasonably well, but 
also the fact that I treat "new" as a function call conceptually so I 
have parenthesis around some of the expression mixed with expressions 
that use colon:
     define: load-img(path)
       set!(src-img read-pxm(path))
       set!(out-img #f)
       set!(src-bmp #f)
       set!(out-bmp #f)
       set!(src-hist send(plot-histogram(src-img 500 250) get-bitmap))
       set!(out-hist #f)
       send(frame modified #f)
       send(src-canvas refresh)
       send(out-canvas refresh)
       send(src-hist-canvas refresh)
       send(out-hist-canvas refresh)
     new(button% [parent btn-pane]
                 [label "Load"]
                 [callback
                  lambda: [button event]
                    define: path get-file("Please select a file to load" 
frame directory-part(last-in-path) #f #f null load-filters)
                    when( path ):
                      begin:
                        set!(last-in-path path)
                        load-img(path)
                  ])
I think putting the "send" outside the parens lets me focus on the 
object and method being called, so I worry less about the magic word 
"send" in there.  I also considered parsing out a "." in an id and 
converting it to a send call, but I'm not annoyed enough at this current 
notation to bother yet.

This colon syntax looks great for things like "begin", and reasonably 
well for define.  It is easy to follow these blocks with the eye and no 
closing parenthesis is needed. The control-structure syntax is nice for 
defining structs too, like:
     define-struct(image):
       [color? width height maxval rs gs bs]
     define-struct(kernel):
       :width    ;dim of kernel
        height   ;dim of kernel
        weights  ;vector in ...
        offset   ;value added ...
        scale    ;after summing ...
Since I did not anticipate this case it shows that making a general-case 
alternate syntax can be used in many features, which may even be added 
to the language later via macros.  This is an improvement over the 
approach of hard-coding certain control structures into the syntax.

It still has oddities that must be remembered, like the use of the let 
and for constructs:
     let: :[a 1]
           [b 2]
       doX(a b)
     for: :[a in-range(10)]
       display(a)
In these examples, it isn't intuitive to have the colon after the let or 
for and then the colon in front of the variable pairings.  I find myself 
thinking about what the s-exp form is and doing the conversion in my 
head.  I suppose if I learned alt-exp better I would just remember these 
patterns, but they are no more intuitive than the current s-exp forms.

I never once used the "_(f a b)" form, since the "f(a b)" form is just 
fine and for anything that needed to be grouped I would just use the "[e 
e]" form.  This left me with just one form of braces, though, so any 
data structure that needs to be highly nested might not look as good.  
E.g. the list of file dialog filters (which is a quoted list of lists, 
so not too deep):
     define: load-filters
       '[["Any" "*.*"]
         ["PPM" "*.ppm"]
         ["PGM" "*.pgm"]]
Though that could be written as:
     define: load-filters
       ':["Any" "*.*"]
         ["PPM" "*.ppm"]
         ["PGM" "*.pgm"]
Is that any clearer?

I find that the infix form is useful for functions that are not 
commutative, like - / < and >. But for everything else I tend to use the 
prefix form.  I do, however, like the way function application looks.


Thanks,
-Everett Morse

p.s. Implementation of alt-exp available at 
http://www.neptic.com/np/software/alt-exp.php

> -----Original Message-----
> From: dev-bounces at racket-lang.org
> [mailto:dev-bounces at racket-lang.org] On Behalf Of Everett
> Sent: 26 August 2010 20:10
> To: plt-dev Developers
> Subject: [racket-dev] alt-exp syntax
>
> I don't know if anyone cares about this, but I made a reader
> and #lang language for the alternate syntax I came up with
> (direct, obvious conversion to s-exp but allows writing fewer
> parens). Implementations are usually better appreciated than
> mere proposals. You can get at it
> here: http://www.neptic.com/np/software/alt-exp.php
>
> I noticed that one can provide a syntax colorer (the default
> is fine for my #lang language), but is there a way to provide
> an indenter since the default handling makes editing my
> alt-exp syntax slightly annoying in DrRacket.
>
>
> Thanks,
> -Everett
>
> _________________________________________________
>    For list-related administrative tasks:
>    http://lists.racket-lang.org/listinfo/dev



Posted on the dev mailing list.