Enhanced infix syntax in new version of Scheme+

Hello,

I present a new version of Scheme+ that allow better infix notation.
For Racket R6RS for now (A Racket version will be soon available also) it requires also a new version of SRFI-105 curly-infix reader and parser.

All code available on github and package manager.

TL;DR:

New features:

use of normal parenthesis ( ) for nested infix notation (feature asked by an internet user) , examples taken from real code :

{(a * x) + y + (d * x) / (add1 (x ** 2))}
{(ksx / (sqrt 2)) * (x + y)}
{unit-axis-in-pixel ← (min xws yws) / (2 * (sqrt max-norm-x-y))}
{(ksy / (sqrt 2)) * ((- x) + y)}
(define (der_atan z z̃)
  {1 / (1 + z̃ ** 2)})
(define (σ z̃) 
  {1 / (1 + (exp (- z̃)))} )

the parser auto-detect infix, prefix notation can still be used.

I provide too a little REPL (Read Eval Print Loop) for Scheme+ with R6RS for testing your code.

New define that allow infix expressions with parenthesis ( ) without using { } and keep all compatibility with RNRS define syntax,examples:

note: this features does not require the parser, it could directly be used in any R6RS Scheme code with:

(import (Scheme+R6RS def-nfx))
(define z   3 * 5 + 2)
z
17
(define a   2 * (cos (2 * pi * p / q)) )

define-infix (rarely need to be used) to avoid any risk of confusing infix and prefix:

(define-infix ksx  (sqrt ((2 + a) / 2)) )
{ksy := (sqrt ((2 - a) / 2))}

all the previous operators still works (:= or <-,etc...)

note that := , <- , ← are equivalent in Scheme+.

Long explanation now:

A few explanation from SRFI 105:

Why not autodetect infix?
Some past efforts tried to automatically detect infix operators, but this turns out to not work well. It’s hard to express good rules for detecting infix operators, and the rules become too complex for users (e.g., “punctuation-only symbols” doesn’t detect “and” or “or”). And in any case, if they were automatically detected, an escape mechanism would be needed anyway - consider (map - ns) for getting a new list with the numbers in ns negated. Allowing the user to expressly notate when infix was intended, using {...}, turns out to be clearer and more intuitive. In particular, curly-infix-expressions allow the use of infix with any symbol, whenever you want... and where it’s not convenient, you don’t need to use it. It is also very backwards-compatible: Normal lists work normally, and if you want infix, use {...}.

Note that the above critic, apply very little to my implementation because:

-i still use { } for infix, only nested expressions are in ( )
-and and or are parsed at syntax level so the problem is solved (and they are still short-circuited)
-the (map - ns) problem is also solved by using define instead of define-infix
or writing the code like this:

the problem comes from the fact that - is detected as an infix operator, as being in middle of 2 expressions (right and left ones),so do:

(define op- -)

and use (map op- ns) in any context ,inside { } or not,as op- is not detected as an operator by the syntax transformers.

or:

(define result (map - ns))

or:

{ns := (list 1 2 3 4)}
{op- := -}
{result := (map op- ns)}
result
(-1 -2 -3 -4)

or:

{ns <- (list 1 2 3 4)}
{op- <- -}
{result <- (map op- ns)}
result
(-1 -2 -3 -4)

still 100% compatible with Scheme and previous versions of Scheme+.

New debugging system, as it is hard with reader , you do not have the exact line of error, i provide a generic Makefile that will parse any Scheme+ file in a Scheme file that you can launch in Racket GUI and have all the debug info, macro stepper,etc. Just put the Makefile in your project directory and type make and the scheme+ file will be parsed and put in a subdirectory.

Just for information the updated schema of the inner implementation is :

But understanding this picture is not mandatory for coding in Scheme+ :slight_smile:

1 Like

It is done, after R6RS,the Racket version is now available:

https://github.com/damien-mattei/Scheme-PLUS-for-Racket

note that it requires the new version of the parser:
https://github.com/damien-mattei/SRFI-105-for-Racket

it is available too in the Racket packager system when it will update itself from my github account.