I finally got round to trying @soegaard 's racket-cas and on the whole it seems OK but I'm not sure I've installed it correctly, there are some minor issues and the docs seem unclear.
I downloaded the zip from github and ran drracket from its directory.
Is it supposed to be installed as a package under raco? I didn't do that, maybe I was supposed to.
To get it to run I then had to modify main.rkt a bit, and then loaded that up into my DrRacket IDE. Here's the file:
When I run this, the greeting appears OK, and the basic commands see to work fine, eg
> (tex (expand '(expt (+ a b) 2)))
"$a^{2}+b^{2}+2\\cdot {a\\cdot b}$"
Typing plain xy or z also correctly reads them as 'x'y or 'z
What does not happen is automatic simplification, which the docs say should happen. However if I explicitly request simplification, it seems OK.
> `(+ 3 a 2 x (* 4 x))
'(+ 3 a 2 x (* 4 x))
> (simplify `(+ 3 a 2 x (* 4 x)))
'(+ 5 a (* 5 x))
Any suggestions?
(Especially if this should be installed as a package? The suggestion to use the form (require racket-cas/repl)
instead of how I did it makes me think so.)
Note however, that automatic simplification and simplify is two different things. The automatic simplifier only does "small stuff" (adds numbers, collect equal terms, sort the terms etc.).
The functions in racket-cas usually expect their inputs to be normalized.
If the inputs are normalized, the outputs are also normalized.
Therefore the automatic simplifier (aka normalize) must be used on inputs
before calling many of the functions.
In the repl it is more convenient to use quasiquote than it is to writenormalize` all the time.
But, back to the macro problem. The "make quasiquote do automatic simplification" macro is defined in [1].
The question is why it works when used in "repl.rkt" but not when required from the repl?
(module+ start
(provide quote quasiquote)
(require (submod ".."))
(require (prefix-in old: (only-in racket/base quote quasiquote)))
; In the REPL it can be convenient to change the meaning of '
; to automatic normalization:
(define-syntax (quote stx)
(syntax-case stx () [(_ . datum) #'(normalize (old:quote . datum))]))
(define-syntax (quasiquote stx)
(syntax-case stx () [(_ . datum) #'(normalize (old:quasiquote . datum))])))
; (let () (define f '(* x x)) `(* x ,f))
; This macro doesn't work as expected ... why?
(define-syntax (repl stx)
(syntax-case stx ()
[_ (with-syntax ([req (datum->syntax stx 'require)])
(syntax/loc stx (req (submod "." start))))]))
Thanks for all that, Axel!
Yes, indeed, opening repl.rkt instead of main.rkt fixes the normalization/auto-simplification issue
(@AlexKnauth , no, just adding all-from-out does not fix it, but it doesn't matter, since you can just launch off the repl.rkt file)
Looking forward to testing it and seeing how it's been implemented!
There is one more little thing I found, I think it may be due to an update in Racket since it was written, I'm guessing it was a keyword parameter change
> (render (expand '(expt (+ a b) 2)))
. . racket-cas.rkt:2065:23: application: required keyword argument not supplied
procedure: latex->pict
required keyword: #:preamble
arguments...:
Any ideas? - it would be nice to have a renderer that can be shown off...
I think, the problem that render used to be defined in racket-cas but was removed.
Now it calls a render from latex-pict, which is broken.
[I'll fix that.]
In the mean time, you can paste this definition into the repl to get a render.
> (begin (require latex-pict pict)
(define (render u)
(define (strip$ x) (substring x 1 (- (string-length x) 1)))
(pict->bitmap (scale (tex-math (strip$ (tex u))) 2))))
> (render (normalize '(+ x 2 a 3 (* 4 x))))
exec failed (No such file or directory; errno=2)
. . ../../usr/share/racket/collects/racket/private/kw.rkt:1386:57: open-input-file: cannot open input file
path: /var/tmp/latex2pdf-6d322b6d01941cdd976b954807b0591c.log
system error: No such file or directory; errno=2
You can see it flash momentarily as it tries to open a rendering window, but then it reports the above error about not being able to find some log file, no idea what that is, I'm afraid. Permissions?
Anyway it really is not a high priority for me, I'm more than happy to wait till it's fixed, but it certainly would be nice to have, once everything's going. Just thought I'd let you know.
The package latex-pict uses pdflatex and a couple of latex libraries.
Maybe something is configured differently on your computer?
If you are using a complete, newish TeXLive, I'd expect everything to work.
Marc had to install some extra packages to get everything to work though.
Which editor are you using in your screenshot? Mine doesn't really look like that in DrRacket or Emacs, and I'm wondering if there's another editor you're using that I haven't tried.
Yeah, especially the subst functionality, which allows me to combine it with normal Racket functional code is a boon.
I'm sure I'll be plaguing you with some questions in the future, and once I've got my head around it a bit, I'll be happy to look through the source, see if there's anywhere I can help!
Have a great Festive Season...
As I said, I've been getting along with racket-cas faster than I thought I would.
The idea is to make a generalised math package, gjs-stylee, perhaps ultimately a bit like scmutils. For this, I need to be able to move transparently between numeric and symbolic code. Also I need functions to evaluate "normally" when dealing with inexact values, but symbolically when dealing with exact or symbolic ones. Like my 80s TI-Voyage on its puny m68k, is that too much to ask?
Anyway, the racket-cas library seems really easy to interact with , I've managed to encapsulate it acceptably so far. See, the racket-cas notation is "hidden", expressions are generated by regular functions.
; sorry, not done expt yet
(define (power expr i) (expand ((repeat-apply (curry * expr) i) 1)))
> (power (+ 'x 1) 6)
(+ 1 (* 6 x) (* 15 (expt x 2)) (* 20 (expt x 3)) (* 15 (expt x 4)) (* 6 (expt x 5)) (expt x 6))
@soegaard Really nice to have those expand and distribute functionalities so easily available but (if I may ask) did you deliberately not incorporate them into simplification routines? Just out of curiosity.
Also how can I get the docs into html or pdf or whatever? I tried running
scribble --html racket-cas.scrbl
but to no avail. I also tried to pass it that info file, but I must be doing something basically wrong.
Really nice to have those expand and distribute functionalities so easily available but (if I may ask) did you deliberately not incorporate them into simplification routines? Just out of curiosity.
Yes. Consider (x+y)^100000. This is a small expression whose expansion is large. This choice matches Mathematica, NSpire and other.
I'll need to check that's the issue with the docs.
Btw - since you mention that you also need numerical calculations.
The compile function exported by racket-cas can be used to convert S-expressions into normal, callable functions.
Example from the README.
We can use standard plot library to draw a few graphs of the Taylor polynomials.
The plot library expects standard Racket functions from number to number.
The function compile will turn a symbolic expression into a normal Racket function.
> (require plot)
> (plot (list (function (compile (taylor '(sin x) x 0 5)) #:color "green")
(function sin #:color "red" -3.14 3.14)))
<nice graphs appear in DrRacket>