SICM, scmutils, MIT-Scheme, CAS systems, etc, etc...

778 views
Skip to first unread message

Alex Gian

unread,
Jun 10, 2018, 5:52:51 AM6/10/18
to Racket Users
Due to the interest displayed in various questions on the subjects above, I'd like start this thread as a central point for a discussion relating to porting some of the central ideas in the scmutils/mechanics environment into Racket, especially, if possible, into a nice useful pedagogic environment, with good graphic support, teachpack modules for books like SICM and FDG, etc -- in fact a nice interactive CAS system, with an elegant functional foundation.  Thanks to Daniel Prager for the idea.

As quite a few people have already said, a straight port from MIT-Scheme would probably be  a bit of a schlepp, with an added horror element.

I think most people would favour the approach of "re-creating" all the various modules used in scmutils, but in a nice modern edition, preferably in idiomatic Racket, to exploit the environment!  In my estimation, the central module for the system is the Calculus and the Automatic Differentiation, which seems to be based on the ideas of Spivak, i.e. the school of "modern" functional calculus notation.  No surprises there.  Of course, to get there, you need certain elements in place, certainly generic arithmetic, including over functions and literals, sane handling of expressions and a good simplifier -- a "functional" CAS, in other words.  Another innovation of the scmutils system is the up/down tuple arithmetic, which in my limited understanding is an extension of the Einstein notation, useful for many things, including, later, the approach to functional DG.

Porting various modules piece-by-piece into the project would allow them to be tested and verified (and used) independently, and if the whole thing is kept nice and modular, a plug-and-play approach to components might be achieved!  A nice target might be to implement the sytem as an architecture - rather than just a program - so it could also be done in other languages, if there was an interest.  Haskell spriings to mind.  In fact the Clojure port came about in this way, and I'm sure there could be a lot of cross-fertilisation of ideas.  Inncidentally, the Clojure port was named SICMutils, not too far from the original name.  I would favour the use of this name, regardless of implementation platform.  IOW, SICMutils for Clojure, for Racket and so on. "scmutils" doesn't really convey much, almost a misnomer, really, "mechanics" (the other name used for the library) is too general and gets lost.  SICMutils is close enough to the original, but gives a nod of credit to SICM.

Lots more to say, in due course. For instance, I wonder if the rudimentary rewrite-rule used in scm utils could be beefed up, perhaps using kanren or racklog, so that simplification rules can be an ongoing project.  I am sure there is quite a lot of expertise on this already.  For now I will concentrate on the structures and matrices, after which I hope to start on the generics.  GJS' "Adventures in Advanced Symbolic Programming" will be the general guide to this.  Also Jens Axel Søgaard has done some good work based on J. Cohen's Books, perhaps it can find its way into the handling of expressions.  Other libraries, e.g. electrical engineering, numerical integrations and ODEs, seem to be widely available and if possible should be used.  No need to re-invent the wheel based on an obsolete, square design  ;)

I started on this as a really long-term project, and a way to learn Racket well, but I have been pleasantly surprised by the level of interest and support!  Already, I am well on the way to achieving a working "structures" module, in a tenth of the time that it would have taken me without the support here.  Many thanks!  If there is enough interest, perhaps a GitHub (or similar) repository might be in order.  I need to figure out how to set up a good TDD environment for Racket first.

Finally, I think that specific implementation details might overwhelm this thread, I'll try to keep it for discussion of design ideas mainly, as specific are probably better served in their own threads.  This has already worked well for me, thanks again!

Alex Gian

unread,
Jun 10, 2018, 6:31:14 AM6/10/18
to Racket Users
To kick off (from the applicable structure thread),  Jens Axel mentioned that MIT-Scheme's named-lambda already exists for Racket.
In MIT-Scheme, lambda itself is implemented as a named-lambda, but with a dummy "non-existent" name.

Opinions, please, especially if you're familiar with MIT-Scheme.  Do you think it would be worth preserving this in a Racket implementation?  Functions need a way to display themselves, this being a CAS, but is it idiomatic Racket?  Could-something better be used

I'm not getting on to expressions until structures and generics are done, but it is a design consideration worth thinking about.


On Sunday, June 10, 2018 at 10:03:33 AM UTC+1, Jens Axel Søgaard wrote:

It is now clear me that Racket is more than rich enough to make for an elegant representation and the handling of functions will be key to this.
I don't know if you've studied MIT-Scheme at all, but there they have a form called the named-lambda, which implements lambda.  That idea may be of some use.  Or something like it.  Or something not at all like it.  Who knows?

Here is named-lambda for Racket. 

#lang racket/base

(require (for-syntax racket/base syntax/parse syntax/parse/lib/function-header))

(define-syntax (named-lambda stx)
  (syntax-parse stx
    [(_named-lambda (f:id . args:formals) b ...)
     (syntax/loc stx
       (procedure-rename (λ args b ...) 'f))]))

 (named-lambda (foo x [y 2]) (list x y))
((named-lambda (foo x [y 2]) (list x y)) 1)
((named-lambda (foo x [y 2]) (list x y)) 1 3)

The output is:

    #<procedure:foo>
    '(1 2)
    '(1 3)


The function  object-name  is used by the printer to extract the name from the procedure.
You can also attach object names to structure values - use the property  prop:object-name.

/Jens Axel


Daniel Prager

unread,
Jun 10, 2018, 8:23:20 AM6/10/18
to Alex Gian, Racket Users

Alex wrote:
> I need to figure out how to set up a good TDD environment for Racket first.

Alex Gian

unread,
Jun 10, 2018, 12:58:03 PM6/10/18
to Racket Users
On Sunday, June 10, 2018 at 10:03:33 AM UTC+1, Jens Axel Søgaard wrote:
 
Here is named-lambda for Racket. 
 

Looks cool, but for some reason it doesn't work for me.
Is there something I should have installed?

#lang racket

(require math
         racket/struct
         racket/base
         ;; syntax stuff
         for-syntax
         syntax/parse
         syntax/parse/lib/function-header)

;; for function name experimantation

(define-syntax (named-lambda stx)
  (syntax-parse stx
    [(_named-lambda (f:id . args:formals) b ...)
     (syntax/loc stx
       (procedure-rename (λ args b ...) 'f))]))

; ================================================

gives back

Welcome to DrRacket, version 6.3 [3m].
Language: racket; memory limit: 512 MB.
. standard-module-name-resolver: collection not found
  for module path: for-syntax
  collection: "for-syntax"
  in collection directories:
   /home/alex/.racket/6.3/collects
   /usr/share/racket/collects
   ... [163 additional linked and package directories] in: for-syntax
  no packages suggestions are available .

I also clicked on the [update catalog] link that appeared next to the above message, but it didn't help.

 

Ben Greenman

unread,
Jun 10, 2018, 1:00:25 PM6/10/18
to Alex Gian, Racket Users

Philip McGrath

unread,
Jun 10, 2018, 1:03:40 PM6/10/18
to Alex Gian, Racket Users
You're missing a pair of parentheses:

(require math
         racket/struct
         racket/base
         ;; syntax stuff
         (for-syntax
           syntax/parse
           syntax/parse/lib/function-header))

Also, though, `procedure-rename` is a runtime operation. You might prefer to look at Inferred Value Names and perhaps the static-rename module.

-Philip

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jens Axel Søgaard

unread,
Jun 10, 2018, 1:06:20 PM6/10/18
to Alex Gian, Racket Users
2018-06-10 18:58 GMT+02:00 Alex Gian <alex...@gmail.com>:

Welcome to DrRacket, version 6.3 [3m].

Upgrade.

/Jens Axel
 

Daniel Prager

unread,
Jun 11, 2018, 7:49:28 AM6/11/18
to Jens Axel Søgaard, Alex Gian, Racket Users
Hi Alex

I reckon a community-driven test-driven / specification by example approach could be very fruitful, or at least an interesting experiment.

1. Post a goal and a few corresponding tests up front.
2. People can solve independently and/or collaborate to make the tests pass.
3. Discuss and refactor to evolve a mainstream design (or maybe designs).
4. Rinse and repeat.

Dan

Alex Gian

unread,
Jun 11, 2018, 9:35:20 AM6/11/18
to Racket Users
Yes, indeed.

I'm OK to work via this list and a few Gists while proofing the concept, i.e, structures and maybe generic arithmetic over functions, literals, etc, but if it gets any further, then a TDD based repository, as can be set up on GitHub, would be indispensable.  I've used that kind of thing before, where every pull-request gets tested automatically against the existing code, before it is even submitted, and yes, it does make life easy and sane.

I don't know how much effort it would be to do this for a Racket project,  any input always welcome, it's not happening straightaway, but good to think ahead.
GitHub?  Or will they be closed by next week?  LOL

My current projection on the order of doing stuff is
  1. structured objects (tuples, matrices)
  2. generics and literals
  3. GIT-based TDD repository
  4. simplifier [blackboard with GCD cancellation & rule-rewriting system] 
  5. power series and other math details
  6. Operators
  7. Calculus and AutoDiff
  8. Graphs/Plots
  9. Numerical support routines (Integration and ODEs)
  10. Mechanics stuff, Lagrangians, et al (SICM)
  11. Some teachpacks?
  12. Much later... advanced mathstuff vector calculus, abstract algebra etc...
  13. FDG
Some other non-scmutils stuff perhaps, along the way, I want to pinch some ideas I've seen and liked, but always
  • completely faithful to scmutils/mechanics - everything at the REPL must work the same as the book and manual.
  • fully embedded in Racket/Scheme - everything pre-existing must work like before.  The system should ultimately be a library for the user.

Hendrik Boom

unread,
Jun 11, 2018, 10:34:01 AM6/11/18
to Racket Users
On Mon, Jun 11, 2018 at 06:35:20AM -0700, Alex Gian wrote:
> GitHub? Or will they be closed by next week? LOL

I doubt github will be closed next week, but it might be prudent to make
sure of alternative arragements. Perhaps a second authoritative server
somewhere? Or at least someone to have a backup of all Racket-related
repositories.

-- hendrik

Hendrik Boom

unread,
Jun 11, 2018, 10:44:26 AM6/11/18
to Racket Users
On Mon, Jun 11, 2018 at 06:35:20AM -0700, Alex Gian wrote:

> My current projection on the order of doing stuff is
>
> 1. structured objects (tuples, matrices)
> 2. generics and literals
> 3. GIT-based TDD repository
> 4. simplifier [blackboard with GCD cancellation & rule-rewriting system]
> 5. power series and other math details
> 6. Operators
> 7. Calculus and AutoDiff
> 8. Graphs/Plots
> 9. Numerical support routines (Integration and ODEs)
> 10. Mechanics stuff, Lagrangians, et al (SICM)
> 11. Some teachpacks?
> 12. Much later... advanced mathstuff vector calculus, abstract algebra
> etc...
> 13. FDG

Looks like you're starting out right.

>
> Some other non-scmutils stuff perhaps, along the way, I want to pinch some
> ideas I've seen and liked, but always
>
> - completely faithful to scmutils/mechanics - everything at the REPL
> must work the same as the book and manual.
> - fully embedded in Racket/Scheme - everything pre-existing must work
> like before. The system should ultimately be a library for the user.

Now check this list of subprojects and desitderata into your code
repository. Embellish it with details and potatial strategies as you
progress. Keep it up to date as you write the code. Keep it up to
date as your plans change. Invite contributions from others.
Accept issue reports about the plans and inspirations as well as about
the actual code.

That way others can contribute, knowing your intentions. And other can
take over if they want if you tire of the project. It's ambitious
enough that you miight tire of it.

-- hendrik

Alex Gian

unread,
Jun 14, 2018, 8:06:12 AM6/14/18
to Racket Users
While on the Subject of Computer Algebra, I took a slight detour via Aubrey Jaffer's JACAL, and I am impressed with what a wealth of resource is to be found there.
In particular the polynomial routines seem even better done than in scmutils (though the same central idea).  Why are polynomials not a first-class citizen in the worlds of Lisp, that's what I want to know! (j/k)
so scmutils will give you

> (let ((pol1 (lambda(x) (+ (* x x) (* -2 x) 1)))
        (pol2 (lambda(x) (- (* x x) 1))))
          ((/ pol1 pol2) 'x))
#|
(/ (+ -1 x) (+ 1 x))
|#

 JACAL is not embedded in Scheme, but a separate, infix language, called by it.

scheme@(guile-user)> (math)
type qed; to return to scheme, type help; for help.
e2 : (x^2 - 2*x + 1) / (x^2 -1);    

    -1 + x
e2: ------
    1 + x

e3 : qed;
$13 = scheme
scheme@(guile-user) >   

This is not really a problem as the foreign syntax wrapper could easily be ditched.  It's just Scheme under the hood.
It's a bit of task getting SLIB to work, no chance with mzscheme, even though there was an ancient module available, in the end I went with Guile-2.0, but even that needed a patch, apparently SCM is the system currently supported.  

Seems a shame that all these little gems get lost in the archaeology.  Sometimes one feels like Schliemann.

There are issues with the level at which such algebraic simplifications are performed in scmutils, but, if possible, I'd like to see arithmetic genericised over polynomials, not tacked on later.


Laurent

unread,
Jun 14, 2018, 8:18:40 AM6/14/18
to alex...@gmail.com, racket-users@googlegroups.com List
Just in case that can be helpful as a starting point, I recently ported the dharmatech/mpl CAS to Racket:

There's also Jens Axel's CAS for Racket:

--
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...@googlegroups.com.

Stephen De Gabrielle

unread,
Jun 14, 2018, 10:22:51 AM6/14/18
to Laurent, alex...@gmail.com, racket-users@googlegroups.com List
https://github.com/soegaard/bracket
may also be useful.
--
Kind regards,
Stephen
--
Ealing (London), UK

Laurent

unread,
Jun 14, 2018, 10:29:48 AM6/14/18
to Stephen De Gabrielle, alex...@gmail.com, racket-users@googlegroups.com List
The difference between soegaard's bracket and racket-cas is explained here:
Excerpt:
"""
In short: The goal of the bracket project was to write a CAS with a nice
graphical frontend, but the frontend was never finished.

The racket-cas project was an experiment: How can the core be written in a
readable way?
If you study the code, you will see that the source is more readable than
the bracket one.
"""

Alex Gian

unread,
Jun 26, 2018, 5:48:19 PM6/26/18
to Racket Users
Slight change of tack:

After running and poring over the code of Dan Gildea's Guile port of scmutils, I think it may be possible to get it working on Racket (with a fair old amount of 'arts and crafts') and I am working on this now, rather than building bottom-up by realising each module incrementally.  Then, when a basic skeleton is working, each separate module can be addressed as needed.  If nothing else, it will give me a chance to get familiar with Racket modules!

I hope to have something up soon, probably on GitHub.

====

BTW, the Guile environment provides two forms lambda* and define*, which are documented here.  basically they are just lambda and define, allowing for a whole lot more arguments.  Does the Racket world have something like this already, or will I have to write the syntaxes for them?


Daniel Prager

unread,
Jun 26, 2018, 6:24:43 PM6/26/18
to Alex Gian, Racket Users
On Wed, Jun 27, 2018 at 7:48 AM, Alex Gian <alex...@gmail.com> wrote:
BTW, the Guile environment provides two forms lambda* and define*, which are documented here.  basically they are just lambda and define, allowing for a whole lot more arguments.  Does the Racket world have something like this already, or will I have to write the syntaxes for them?

Racket is more explicit when it comes to optional and keyword parameters. Translating one of the Guile examples ...

#lang racket

(define (sir-yes-sir #:action [action #f] #:how-high [how-high #f])
  (list action how-high))

> (sir-yes-sir #:action 'jump)
'(jump #f)
> (sir-yes-sir #:how-high 13)
'(#f 13)
> (sir-yes-sir #:action 'lay-down #:how-high 0)
'(lay-down 0)
> (sir-yes-sir)
'(#f #f)



Dan

Alex Gian

unread,
Jul 3, 2018, 8:35:56 AM7/3/18
to Racket Users
Project is coming on well, almost working.

One interesting point was the use of MIT-Scheme's apply-hooks.  I thought they only served for implementing applicable structures, but they are also used in the generic interface.  I'm sure eventually they'll be superseded, but for now I need them.  I was surprised how little effort it took for me to implement them using structs!  Remarkable.  Well, done Racket!

One place where I am bumping my head a bit is mutual dependency cycles between, you know a-requires-b, b-requires-c, c-requires-a.  I have neatened everything up as much as possible, hierarchized properly and tried to limit what's passed around by using only-in, etc.  However I cannot escape from the inevitable.

e.g   generic.rkt requires 'make-generic-operator' from ghelper.rkt.  
  ghelper.rkt requires 'type-tags' from types.rkt and 
  types.rkt requires 'g:type' from generic.rkt.          Ooops.

Is there some sort of canonical way to allow mutual references between modules like this?





Laurent

unread,
Jul 3, 2018, 8:59:56 AM7/3/18
to Alex Gian, racket-users@googlegroups.com List
I can't vouch for a canonical way, but the way I've resolved this in the past is by either
- putting what's needed in the same module, or
- exporting the name only, bound to #f, along with a setter procedure (because variables can't be mutated from outside the module), and call the setter in a different module where everything is available,
- using units, which, IIUC, generalizes the previous point to all bindings.

If your cycle is due to only a few elements, the second solution is likely the simplest.



Matthias Felleisen

unread,
Jul 3, 2018, 9:00:15 AM7/3/18
to Alex Gian, Racket Users

Use #lang racket/unit

Alex Gian

unread,
Jul 3, 2018, 9:21:01 AM7/3/18
to Racket Users
Thanks.  Sounds like a cool suggestion.  I'll look into it.
Unfortunately, I can't use it at the moment, because all the MIT-Scheme / Guile / GJS routines I'm porting at the moment have to be in #lang scheme.
I'm only writing the new stuff in Racket and what a treat it is being able to mix the two.  Just made life SOOO much easier!

Once everything is working at a "proof-of-concept" level and can start being refactored, then I'm sure all the little idiosyncracies will be reined in more canonically!

Alex Gian

unread,
Jul 3, 2018, 10:19:52 AM7/3/18
to Racket Users
I used your first solution in the end, was the simplest for the few lines involved.  Put all the offending code in one file and moved it a level up.  Thanks

Alex Gian

unread,
Jul 5, 2018, 8:50:45 AM7/5/18
to Racket Users
For anyone that may be following this, there is still an awful lot of tidying to be done, but we do have a working generic core.

Welcome to DrRacket, version 6.12 [3m].
Language: racket, with debugging; memory limit: 256 MB.

> (define unity (g:+ (g:square sin)(g:square cos)))
> (unity 42)
1.0
The rest shouldn't be as much of a headache... 

Alex Gian

unread,
Jul 12, 2018, 2:02:12 PM7/12/18
to Racket Users
On Thursday, July 5, 2018 at 1:50:45 PM UTC+1, Alex Gian wrote:

The rest shouldn't be as much of a headache... 

Said he, optimistically!
Been a bit of a labyrinth of spaghetti code dependencies, but I think I've managed to refactor it into a shape I wouldn't mind anyone else looking at.
dot (graphviz) graphs are great.  Every project should be forced to have one!  :p

In fact it would be great if there was a dot/graphviz-like utility for Racket.  
The user could then parse a large file collection and get the dependencies, and build the graph automatically, instead of sweating over it manually.
Still, for someone of my limited experience level it's been fun.

Daniel Feltey

unread,
Jul 12, 2018, 2:59:51 PM7/12/18
to Alex Gian, Racket Users
I think DrRacket has this built in if I understand correctly. See the documentation on the Module Browser[1] which is available through the `View` and `Racket` menus in DrRacket.


Dan

--
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+unsubscribe@googlegroups.com.

Alex Gian

unread,
Jul 12, 2018, 3:10:39 PM7/12/18
to Racket Users
Ah, thanks Daniel, that's great to know, as I check progress, but my wish / pipe-dream was for something that could do that with any code, especially legacy R[4|5]RS hybrids.  j/k
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.

Alex Gian

unread,
Jul 13, 2018, 2:14:54 AM7/13/18
to Racket Users
Nice little utility, that Module Browser.
It certainly helped me confirm that my imagined hierarchy was not too far from reality!

Funny how in the standalone mode you can't select a file to open (not that I can see, anyway) although you can in the sub-window mode.

Alex Gian

unread,
Aug 4, 2018, 4:24:24 PM8/4/18
to Racket Users
I shouldn't have, really, it was in no state to be uploaded, but out of consideration to the many folks that have helped me so far, I've put it up here.

Actually, although it's quite the mess now, once I've sorted out what to do about the "environments" (modules) and cleaned up and added the generic dispatching, it will almost work as a proof of concept.  The generic dispatching already works fine, I haven't included it in the upload yet, I want to make some decisions about tuples and matrices first.  Polynomial-gcd (for simplification) seems to be working.  Logic rules for simplification should be OK but have snagged on scoping of eval and modules (hence the upload).  

Once all that is done, I can move to the interesting stuff, literals and literal-functions and calculus!

Unless you have a particularly strong interest in this project I recommend you don't look at anything yet!
For the rest, there are a couple of dots/pdfs of the program structure (a lot of refactoring) and a skeleton of the documentation.

Be gentle!

Reply all
Reply to author
Forward
0 new messages