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: [email protected]
[mailto:[email protected]] 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

_________________________________________________
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev

Reply via email to