Discussion:
[racket] Writing algebraic maths expressions
Norman Gray
2015-03-07 12:11:28 UTC
Permalink
Greetings.

Is there a recommended way of writing algebraic maths expressions within Racket programs? I mean something like (maths 1 + 3 * x) rather than (+ 1 (* 3 x)).

I'm trying to evaluate a number of expressions which aren't mathematically exotic, but which are numerous and fiddly, and it's really painful trying to convince myself that what I've transcribed into Racket matches the expression on the paper. I've briefly considered writing a parser myself, and writing a LaTeX prettyprinter, to help compare what I've transcribed with what I started with, but while both of these are doubtless feasible and educational, neither should be my first priority at this point in this project.

----

What I've got so far:

Honu is an obvious place to look, but it appears that it's expected to be used as the syntax for a complete module rather than fragments, and that's unattractive, because then I'd have to familiarise myself with the complete syntax rather than just the syntax of mathematical expressions (interesting, of course, but in this context a distraction). Also, because (i) the documentation stresses that it's provisional. I thought (ii) I might be able to use (require honu/core/read) and honu-read, but when I try (call-with-input-string "a * b" honu-read) I get '(a * b) which makes me think that Honu's goals are not what I think they are, and a skim through <http://www.cs.utah.edu/~rafkind/papers/honu11.pdf> corroborates that.

Another possibility is Sweet expressions, as described at <http://pkg-build.racket-lang.org/doc/sweet/index.html> and <http://readable.sourceforge.net>. That feels plausible, but (i) the port doesn't seem complete, since when I try:

#lang sweet-exp racket/base

let
\\
a 1
*(a a)

(see <http://sourceforge.net/p/readable/wiki/Scheme-tutorial/>, at 'Grouping and Splitting'), I get 'let: bad syntax (not an identifier and expression for a binding) in: |\\|'. Also, because (ii) while the syntax does have provision for including sweet-expressions within normal Racket syntax (the inline {...}) syntax), it's clear that this interacts in a slightly complicated way with the surrounding syntax, so that one has to be mindful of where semicolons and closing braces go; that again makes it a little harder to be confident I'm evaluating the expression I think I'm evaluating. Finally, (iii) the inline syntax deliberately (and intelligibly) doesn't support a precedence-based syntax for things like '1 + 2*3'.

I don't see anything in the list at <http://pkgs.racket-lang.org>, searching for 'algebra', 'math' or 'syntax' (well, looking at the goodies in the last case lets me find 'ragg', which might be useful if I do write myself a parser, but... must. not. get. deflected...)

----

So:

I'm sure I can work through the puzzles above, but at this point the path is feeling awfully untrodden, and since I can't believe I'm the first person with this goal, I feel sure I've taken a wrong turning someplace.

Thanks for any pointers. Best wishes,

Norman
--
Norman Gray : http://nxg.me.uk
SUPA School of Physics and Astronomy, University of Glasgow, UK


____________________
Racket Users list:
http://lists.racket-lang.org/users
Alexander D. Knauth
2015-03-07 12:34:32 UTC
Permalink
Would this work for you:
https://github.com/AlexKnauth/infix-macro
It’s a macro, not a reader extension, so you would need to put spaces.
And for sweet-exp (ii), the braces don’t interact in a complicated way with the surrounding syntax (no worrying about where semicolons go, and you don’t have to worry about where braces go either, except that where there are braces, it’s a infix expression).
And for supporting precedence, you could always use https://github.com/AlexKnauth/infix-macro and define it as nfx.
There’s also this:
http://planet.racket-lang.org/display.ss?package=infix.plt&owner=soegaard
http://planet.racket-lang.org/package-source/soegaard/infix.plt/1/0/planet-docs/manual/index.html
Post by Norman Gray
Greetings.
Is there a recommended way of writing algebraic maths expressions within Racket programs? I mean something like (maths 1 + 3 * x) rather than (+ 1 (* 3 x)).
I'm trying to evaluate a number of expressions which aren't mathematically exotic, but which are numerous and fiddly, and it's really painful trying to convince myself that what I've transcribed into Racket matches the expression on the paper. I've briefly considered writing a parser myself, and writing a LaTeX prettyprinter, to help compare what I've transcribed with what I started with, but while both of these are doubtless feasible and educational, neither should be my first priority at this point in this project.
----
Honu is an obvious place to look, but it appears that it's expected to be used as the syntax for a complete module rather than fragments, and that's unattractive, because then I'd have to familiarise myself with the complete syntax rather than just the syntax of mathematical expressions (interesting, of course, but in this context a distraction). Also, because (i) the documentation stresses that it's provisional. I thought (ii) I might be able to use (require honu/core/read) and honu-read, but when I try (call-with-input-string "a * b" honu-read) I get '(a * b) which makes me think that Honu's goals are not what I think they are, and a skim through <http://www.cs.utah.edu/~rafkind/papers/honu11.pdf> corroborates that.
#lang sweet-exp racket/base
let
\\
a 1
*(a a)
(see <http://sourceforge.net/p/readable/wiki/Scheme-tutorial/>, at 'Grouping and Splitting'), I get 'let: bad syntax (not an identifier and expression for a binding) in: |\\|'. Also, because (ii) while the syntax does have provision for including sweet-expressions within normal Racket syntax (the inline {...}) syntax), it's clear that this interacts in a slightly complicated way with the surrounding syntax, so that one has to be mindful of where semicolons and closing braces go; that again makes it a little harder to be confident I'm evaluating the expression I think I'm evaluating. Finally, (iii) the inline syntax deliberately (and intelligibly) doesn't support a precedence-based syntax for things like '1 + 2*3'.
I don't see anything in the list at <http://pkgs.racket-lang.org>, searching for 'algebra', 'math' or 'syntax' (well, looking at the goodies in the last case lets me find 'ragg', which might be useful if I do write myself a parser, but... must. not. get. deflected...)
----
I'm sure I can work through the puzzles above, but at this point the path is feeling awfully untrodden, and since I can't believe I'm the first person with this goal, I feel sure I've taken a wrong turning someplace.
Thanks for any pointers. Best wishes,
Norman
--
Norman Gray : http://nxg.me.uk
SUPA School of Physics and Astronomy, University of Glasgow, UK
____________________
http://lists.racket-lang.org/users
____________________
Racket Users list:
http://lists.racket-lang.org/users
Norman Gray
2015-03-07 16:04:05 UTC
Permalink
Alexander, hello.
Post by Alexander D. Knauth
https://github.com/AlexKnauth/infix-macro
It’s a macro, not a reader extension, so you would need to put spaces.
[...]
Post by Alexander D. Knauth
http://planet.racket-lang.org/display.ss?package=infix.plt&owner=soegaard
Many thanks for this! Jens Axel's infix parser appears to be exactly the thing I was imagining. The fact that it doesn't need the intervening spaces is attractive: otherwise, it feels like a sort of half-way house, where I've got to mentally overload two different syntaxes (in a sense) rather than simply page in one or the other.

And thanks for the explanation about 'group' as opposed to '\\'.
Post by Alexander D. Knauth
And for sweet-exp (ii), the braces don’t interact in a complicated way with the surrounding syntax (no worrying about where semicolons go, and you don’t have to worry about where braces go either, except that where there are braces, it’s a infix expression).
There's clearly _something_ going on with the parsing, though. For example

#lang sweet-exp racket/base

(define (f x)
{x * x}
;
)

produces 'invalid module text. . unexpected `)`. Also, in <http://sourceforge.net/p/readable/wiki/Scheme-tutorial/>, at 'Unsweeten: Translating Sweet-expressions into S-expressions', there's a passage
Post by Alexander D. Knauth
Unsweeten also copies comments to the output file, but only in certain cases. Only a group of semicolon comments starting from either the file's very beginning, or after a blank line, are copied to the output. Such semicolon comments will have indentation (if any) removed. Block comments and comments inside a datum are never copied. Semicolon comments immediately after a datum aren't copied either (the reader has to consume them to see if it's reached the end of the datum - and once the data is consumed unsweeten can't copy the comment out).
Unsweeten also has some special substitutions. If a semicolon begins a line, the next character may cause it to do something special. If line begins with ";#: or ";!", the line is copied back without the leading semicolon. If a line begins with ";_", then the line is copied back without either of those first two characters.
I can broadly understand why this is happening, but this again feels like the half-way problem mentioned above. The infix.plt solution, piggybacking as it does on the at-exp reader, seems to evade this problem.

Best wishes,

Norman
--
Norman Gray : http://nxg.me.uk
SUPA School of Physics and Astronomy, University of Glasgow, UK


____________________
Racket Users list:
http://lists.racket-lang.org/users
Alexander D. Knauth
2015-03-07 16:34:34 UTC
Permalink
Post by Norman Gray
There's clearly _something_ going on with the parsing, though. For example
#lang sweet-exp racket/base
(define (f x)
{x * x}
;
)
produces 'invalid module text. . unexpected `)`.
Ok thanks for finding that, I just submitted a pull request to fix it:
https://github.com/takikawa/sweet-racket/pull/18
But that has nothing to do with the infix notation interacting with anything.
That was a bug with comments before closing parentheses.

____________________
Racket Users list:
http://lists.racket-lang.org/users
Norman Gray
2015-03-07 21:12:36 UTC
Permalink
Alexander, hello.
Post by Alexander D. Knauth
https://github.com/takikawa/sweet-racket/pull/18
But that has nothing to do with the infix notation interacting with anything.
That was a bug with comments before closing parentheses.
Ah, righto -- my mistake.

I'll play with both the sweet expressions and Jens Axel's infix, and see which feels more natural in use.

Best wishes,

Norman
--
Norman Gray : http://nxg.me.uk
SUPA School of Physics and Astronomy, University of Glasgow, UK


____________________
Racket Users list:
http://lists.racket-lang.org/users
Alexander D. Knauth
2015-03-07 13:05:04 UTC
Permalink
Post by Norman Gray
#lang sweet-exp racket/base
let
\\
a 1
*(a a)
(see <http://sourceforge.net/p/readable/wiki/Scheme-tutorial/>, at 'Grouping and Splitting'), I get 'let: bad syntax (not an identifier and expression for a binding) in: |\\|’.
For this, sweet-exp uses `group` instead of `\\`.

#lang sweet-exp racket
let
group
a 1
b 2
{a + b}



____________________
Racket Users list:
http://lists.racket-lang.org/users
Alexander D. Knauth
2015-03-07 13:19:25 UTC
Permalink
That just made me think of this:
https://github.com/AlexKnauth/sweet-exp-utils/blob/master/sweet-exp-utils/kw-let.rkt
Which lets you write:
kw-let #:a 1 #:b 2
{a + b}
Or:
kw-let
#:a 1
#:b 2
{a + b}
Instead of having let, group, and the first id-val pair all be on different lines.
Post by Alexander D. Knauth
Post by Norman Gray
#lang sweet-exp racket/base
let
\\
a 1
*(a a)
(see <http://sourceforge.net/p/readable/wiki/Scheme-tutorial/>, at 'Grouping and Splitting'), I get 'let: bad syntax (not an identifier and expression for a binding) in: |\\|’.
For this, sweet-exp uses `group` instead of `\\`.
#lang sweet-exp racket
let
group
a 1
b 2
{a + b}
____________________
http://lists.racket-lang.org/users
____________________
Racket Users list:
http://lists.racket-lang.org/users
Loading...