Hacker News new | ask | show | jobs
by kovrik 3186 days ago
Can anyone explain why there are so many implementations of Scheme written in Scheme? What is the point of doing that (apart from learning purposes)?

I know, for example that people want Racket VM to be implemented in Chez Scheme because Chez is super fast. But what about all other implementations?

Also, as I'm currently writing R5RS/Clojure hybrid in Kotlin, can anyone please share any _simple_ standard algorithm of implementing r5rs macro system and macro expander?

The only thing I could find is https://www.cs.indiana.edu/chezscheme/syntax-case/

8 comments

I'm afraid I literally laughed out loud at your request for a simple standard algorithm for r5rs macro systems. However, it's a sympathetic laugh. Macro Hygiene is still very hard, principally because (I claim) there's not yet a clean and widely accepted model for it. Matthew Flatt's "sets of scopes" model is (IMNSHO) the current leader. Time will tell whether he or anyone else comes up with a simpler and more widely accepted model. But yes: as an implementor, it "feels" very heavy, and you keep thinking that there must be a simpler solution to this problem (aside from just throwing the problem out and giving up on hygiene and language composability).
Yeah, you are right. I've already implemented everything from r5rs, but macro system. And I don't know where to start, just can't wrap my head around it.

And people say that Scheme has a very minimalist design and is easy to implement...

You may find this paper helpful [1]. As noted there, syntax-rules consists really of two different parts: (1) the hygiene-preserving macro expander and (2) the pattern-matching facility. Once you wrap your head around the two pieces, it's actually pretty straightforward to implement them both. It's very common to write some "low-level" macro facility as a stepping-stone to syntax-rules (such as explicit-renaming macros or syntactic closures): the implementation of syntax-rules then becomes a composition of the pattern-matcher and the low-level facility. A tutorial implementation of an appropriate pattern-matcher can be found at [2],[3].

There's lots of good reading to be found at the ReadScheme Library [4]. Most if not all of the references in [1] can be found there.

Tangentially: yeah, syntax-rules kinda flies in the face of the oft-mentioned minimalism of Scheme, but there's a reason for it: at the time syntax-rules was standardized, there was no consensus on which (if any) low-level facility should be standardized (and, really, there still isn't any such consensus). The reason syntax-rules operates as a pattern-template rewriting system rather than as a procedural system is that such a system is able to guarantee that the macros it produces are hygienic in a (comparably) simple and intuitive way. The idea was to standardize on a high-level system so that Scheme could have a standard macro facility, whilst leaving the low-level systems open for further exploration and experimentation. The two main contenders are still, after all these years, syntax-case and syntactic closures: the latter being easier to implement and arguably easier to grok, the former being potentially more powerful (in that an implementation of syntactic closures within syntax-case is known, but not vice-versa (last I checked)).

--

[1]: http://mumble.net/~jar/pubs/scheme-of-things/easy-macros.pdf

[2]: http://blog.theincredibleholk.org/blog/2013/02/11/matching-p...

[3]: http://blog.theincredibleholk.org/blog/2013/02/12/patterns-w...

[4]: http://library.readscheme.org/

Hey, thank you so much for that! Haven't seen some of those papers. Looks promising. Cheers!
Scheme has a strong tradition in programming pedagogy---it is the language used in SICP and other classic books---and writing Scheme in Scheme is what many of these books build up to. So writing your own Scheme implementation is a natural thing for many Scheme programmers to do.

As for Racket, IIUC the plan is to migrate the current C VM to a Scheme one building on Chez Scheme. It won't be that Racket will be running on Chez. The Racket fork of Chez and Racket itself will be one and the same thing.

I think it's usually to provide extra features. For example, Gerbil has a more advanced macro and module system than most Scheme implementations. It's also very easy to do because you're bascially given an AST for your new Scheme that you transform into the base Scheme.

Gerbil's docs have an example of this: https://github.com/vyzo/gerbil/blob/master/doc/tutorial/lang...

Can these 'more advanced' features be implemented in, say, Racket/Guile/Chez?
I don't know why they couldn't be. I'm pretty sure Gerbil's macro/module systems are heavily inspired by Racket.
The well-known algorithm for macro expansion is mark-and-rename. Although the racket implementation was later changed to scope-sets(http://www.cs.utah.edu/plt/scope-sets/index.html).
The simplest way would probably be to implement explicit and implicit renaming macro transformers. They are found in many schemes and are quite a bit simpler than the syntax case you linked to. Then you can just glue parts of ashinn's match.scm on top of it for the pattern matching.

There is also a srfi for an improved hygiene low level macro facility that is rather elegant. Can't remember the number though. 70-something.

A single unifying scheme standard?

You must be new here..

r7rs is what you seek
HN uses * instead of Markdown's _ for emphasis.
Can someone explain these sort of questions?