The Excellent Schemer
code-magazine.com
code-magazine.com
Microsoft has always been as brazen as it is effective at this sort of thing.
The current standard for Scheme is referred to as R6RS
R7RS small has been out since 2013. But yeah... "it's complicated".We did an experiment a few months ago with compiling Gambit to JS and then serving it as an Office extension, using our JS FFI to interface with the Office JS library. Worked out of the box, but definitely some performance cost. Curious about performance on .NET.
BTW if Bob reads this, happy to hear you talk about this at the upcoming Scheme Workshop :) I guess this isn't available on Excel on the web?
https://icfp22.sigplan.org/home/scheme-2022 for those interested.
1. Does this mean we don't need static type-checking?
2. Instead of
(lambda (x y)
(let ((xs (* x x))
(ys (* y y)))
(sqrt (+ xs ys))))
why don't they (the article) format it like: (lambda (x y)
(let ( (xs (* x x))
(ys (* y y))
)
(sqrt (+ xs ys))
)
)
The rule could be: Never have more than
TWO consecutive closing ')' on the same line.If you're trying to prove the benefits of a syntax, the reader should not need to spend energy on trying to understand which closing ')' correspond to which opening '('.
In the predominant style, nobody worries about which specific closing parenthesis goes with which opening one. The indentation reveals the subordination structure, and the editor takes care of that.
Speaking of indentation, you have it wrong: the sqrt should be indented inside the let.
(lambda (x y)
(let ((xs (* x x))
(ys (* y y)))
(sqrt (+ xs ys))))
^^^^
At the ^^^^ spot, all that matters is that we have four closing parentheses. They are all the same otherwise. Which specific one closes the let is not informative.There are too many parentheses to be focused on them; you have to learn mostly not to see them, except within a line of code where there is no indentation. Someone who has been working with the language for a while just "sees" this:
lambda (x y)
let (xs (* x x))
(ys (* y y))
sqrt (+ xs ys)
Or maybe even this: lambda (x y)
let xs (* x x)
ys (* y y)
sqrt (+ xs ys)
(The question of "why not make that the syntax" has been thoroughly explored; it exists out there in some forms, along with other proposals for alternative Lisp syntaxes. https://srfi.schemers.org/srfi-110/srfi-110.html )That just tells me I got the indentation wrong because it did not clearly indicate the syntactic components of the expression.
> Someone who has been working with the language for a while just "sees" this: ...
I take your word for that. I have been working with Lisp for years but not recently, and I had trouble figuring out the meaning of the example code. I even got it wrong you say. It's clear for Lisp experts I'm sure but not everybody is a Lisp expert.
I rely on indentation; if the indentation is bungled, there is a good chance I will misunderstand the code. I'm not going to count parentheses to see that something was falsely de-indented to look like it doesn't belong to the preceding block.
https://docs.racket-lang.org/r6rs/r6rs-std/r6rs-Z-H-4.html#n...
> Scheme has latent as opposed to manifest types. Types are associated with objects (also called values) rather than with variables. (Some authors refer to languages with latent types as untyped, weakly typed or dynamically typed languages.) Other languages with latent types are Python, Ruby, Smalltalk, and other dialects of Lisp. Languages with manifest types (sometimes referred to as strongly typed or statically typed languages) include Algol 60, C, C#, Java, Haskell, and ML.
The Scheme standards are very concise and readable.
2. Sometimes we Schemers will leave an orphan paren, like if we want to leave a place temporarily for new code. The primary benefit of all on the same line, IMO, is it is more compact vertically and most Lisp programmers rely on paren matching anyway. If you program in Scheme long enough, you can just "see" the level of nesting by the apparent contour of parenthesis. (If you don't understand this, that's probably a good thing.)
LAMBDA = lambda (args) body
LET = let (bindings) body
binding = (var [value]) | var
actually the syntax is quite a bit more complex, since args have a lot of options and both LET & LAMBDA allow type declarations.
Each of the symbols also determine a certain indentation style and code shape. There are built-in operators, macro operators and function calls. Especially macros provide an unbound amount of syntactic possibilities.
Trying to figure out expressions by looking at parentheses and finding pairs by parenthesis alignment is mostly not used. It's a too complex visual operation.
The only reason I can see to put multiple closing parenthesis on the same line is to save vertical space. But if you pack too much code in a few lines, readability suffers.
To get the semantics of your statements right you do need to know where syntactic units start and end.
Wowza.
Edit:
Check out iron scheme here: https://github.com/IronScheme/IronScheme
I use Common Lisp a lot in my work and my own research programming, and language interop is always a nuisance. With IronScheme, it looks like interop with all .Net languages is easy.
https://github.com/lisp-mirror/airship-scheme
https://news.ycombinator.com/item?id=13868549
As for using it:
> This section is currently incomplete because the programming language is not functional at the moment.
Scheme is Only the Beginning! ... and it will also offer Clojure as an
alternative
It did take me awhile to understand this is a paid offering on top of office 365 though.