On Apr 23, 2015, at 12:51 PM, Jos Koot <jos.k...@gmail.com> wrote:

> Long ago I made various parsers (most of them in Fortran or assembler) for 
> expressions with infix notation. I always used push-down automata with two or 
> more stacks. Now I am playing with macros in Racket that allow infix notation 
> embedded in Racket without explicitly using push-down automata. However, I 
> encounter a contradiction in my desires as explained below.

> I have looked at 'Infix expressions for PLT Scheme' available in planet and 
> made by Jens Axel Søgaard. In his approach a+b is evaluated as though written 
> as (+ a b). However:
>  
> #lang at-exp scheme
> (require (planet soegaard/infix))
> (define a+b 4)
> (define a 1) (define b 2)
> @${a+b}  ; evaluates to 3
>  
> A Racket variable can contain characters such as +, -, * etc.
> This makes @${a+b} confusing
> (not necessarily ambiguous, though, depending on syntax and semantics.
>  
> In my own toy I require variables and operators to be separated by spaces.
> So I write (infix b ^ 2 - 4 * a * c), not (infix b^2-4*a*c).
> In my toy b^2-4*a*c is read as a single variable.

You might be interested in:
https://github.com/AlexKnauth/infix-macro
It does a similar thing, but with a more general way of defining operations so 
that you can write something like:
#lang racket
(require infix/general-infix (for-syntax infix/general-infix-ct))
(define-infix-macro/infix-parser infix1
  (ops->parser add-op (unary-prefix-op #:sym 'sqrt #:id #'sqrt) expt-op))
(define-infix-macro/infix-parser infix2
  (ops->parser (unary-prefix-op #:sym 'sqrt #:id #'sqrt) add-op expt-op))
(infix1 sqrt 3 ^ 2 + 4 ^ 2) ; 19 ; equivalent to (+ (sqrt (expt 3 2)) (expt 4 
2))
(infix2 sqrt 3 ^ 2 + 4 ^ 2) ; 5  ; equivalent to (sqrt (+ (expt 3 2) (expt 4 
2)))

> Of course notation b^2-4*a*c is attractive.

If you want that you could try looking at:
https://github.com/AlexKnauth/postfix-dot-notation
It provides two things.  One is a #lang postfix-dot-notation which is a 
meta-language, and the other is a require-able module which provides 
dot-notation by redefining #%top.
If you want to, you could start with either of these approaches to make 
b^2-4*a*c (or even b^2-4ac) work.
Or I suppose you could also define an extension to 
https://github.com/AlexKnauth/infix-macro that does this.

> b ^ 2 - 4 * a * c looks rather ugly,
> but allows unambiguous discrimination between operators and variables.
> Furthermore my infix can be required within #lang racket.
> It does not need at-exp.

What’s wrong with at-exp though?
I personally don’t like (planet soegaard/infix) as much mostly because the 
other options have the benefit of working with DrRacket features such as 
check-syntax arrows and blue-boxes, but that’s just because DrRacket is 
awesome, not because at-exp is bad.  

> (infix list('a, 'b ,'c)) and
> (infix if(test, then-case, else-case))

Also you could look at this:
https://github.com/takikawa/sweet-racket

> Even more attractive than b^2-4*a*c would be b^2-4ac,
> but this would delimit variables to consist of one character only.
>  
> On one hand I want an attractive notation. On the other hand I want easy 
> embedding in Racket allowing the use of Racket variables in my infix 
> expressions
> and allowing renames of operators.

I can understand why you would want to use racket variables that might include 
+, or especially -, *, or / (!), but is there a reason why you would want to be 
able to rename operators by (require (only-in racket/base [+ plus]))? 

I can understand the need to define a new infix operator, which is what 
https://github.com/AlexKnauth/infix-macro does, or the desire to throw away 
precedence and order of operations to be able to use any identifier as an infix 
operator, which is what https://github.com/takikawa/sweet-racket does.

> The two hands contradict each other.

It seems to me like there are two problems here, or two contradictions:
First: racket identifiers with +, -, *, and / in them, versus math expressions 
without spaces
Second: generality of operators versus order of operations and precedence
Both of these are mainly about generality versus special-case convenience.  

For the first issue:
(planet soegaard/infix) takes the side of math expressions without spaces, but 
creates a clear separation between what follows racket’s rules and that follows 
math-expression rules.  This is nice because it provides both worlds without 
trying to mix them up in a weird way. 
Your infix macro, my infix macro, and sweet-exp all take the side of racket 
identifiers, which allow it to be much more general, but can make it look a 
little uglier.
One possible middle-ground here is to use #%top so that it only tries to use 
infix when it finds an identifier that would otherwise be undefined, but that’s 
conceptually more confusing. 

For the second issue:
Mathematical notation is not very general at all.
(planet soegaard/infix) takes the side of precedence, while, as far as I know, 
not allowing definitions of new infix operations.
Your infix macro takes the side of precedence, but I don’t know, can you define 
new infix operations with it?
My infix macro takes the side of precedence, but does that coming from an angle 
of more generality, so you can define new infix operations, switch the order of 
operations around, and that kind of thing. 
Sweet-exp takes the side of generality, which means that any identifier can be 
used as an infix operation, not just predefined ones, which means, you can use, 
{obj is-a? my-class%}, {Number U String}, {a depends-on? b}, {a dot b}, and all 
of this without anyone needing to say that these identifiers can be used as 
infix operators and specify their precedence. And really, {{b ^ 2} - {4 * a * 
c}} isn’t bad. But sweet-exp also allows you to define or import an nfx macro 
to handle precedence, so I think sweet-exp really hit a sweet-spot here (no pun 
intended).
For a completely different approach, this: 
http://pizzaforthought.blogspot.in/2015/01/maya-dsl-for-math-and-numerical-work.html
It uses infix-style syntax with a more general postfix-ish feel that I actually 
quite like.  So for instance (maya a + b / 2) is (/ (+ a b) 2), but it doesn’t 
treat any identifiers or operations specially (it does treats :as specially). 
If you let go of some things you learned about precedence, it’s actually quite 
natural.  My version of that in racket: 
https://github.com/AlexKnauth/heresy/commit/6164ef10aecb85d673cd33d48d0dd3b90d007db8
So there’s that, too.


-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to