The syntax of your language is quite nice. I’d maybe change (for …) to (each …), (fun …) to (fn …), and (let …) to (def …) or (set …) depending on implementation details of variable assignment, but those are just aesthetic preferences :)
I love '{thing}' for string interpolation.
If you haven’t already, check out clojure, janet-lang, io-lang, and a library like lodash/fp for more syntax and naming inspiration.
Thanks, I think this language will probably keep my hacking for a while :). you're right about the keyword naming, i tried to be unique, maybe too much for functions, simply because i love them being named "fun". Let in the current implementation definitely is confusing due to it being used for defining and updating a variable and its contents - maybe ill change it to let and set or def and set, who knows. Thanks for the feedback :)
> The scope is clearly defined by the parentheses, though if you're not used to Lisp syntax that can be confusing at first.
The scope is clearly not defined by the parentheses, and I've been programming in Common Lisp for 25 years, so I'm pretty used to Lisp syntax.
A sibling comment suggests it comes from the JavaScript let (which did not exist when I learned JavaScript; it wasn't introduced until 1.7), which is scoped to the containing lexical block, rather than a block introduced by the let form itself.
Those lets in TFA seem more like Lisp’s setq rather than let. A let expression would bind values to names only within the scope of (let …) itself. The lets in TFA and in your examples have side effects. You reference the bound values outside of (let …).
In other lisps a let form has a body that the binding(s) range over and they are not available outside. As in `(let n 12 (+ n n))` here n wouldn't be accessible after. You have `(def name 5)` for making definitions that are readable outsude.
I’m not sure but I assume it works similarly to define in scheme or to let bindings in languages like rust or JavaScript where the binding lasts until the end of some kind of implicit scope.
You must be right. I actually didn't know JS had a "let" (which is different from "var" in that it is block scoped rather than function scoped). It's also quite different from the let in most Lisps, in that it does not establish a new lexical block.
Playing with it, the binding is scoped to the entire block, but the assignment happens in statement order so that e.g. the following will be an error, rather than logging either "1" or "2" both of which there could be arguments for:
Other way round. They're implementing a language of the LISP family, which tend to use let this way. LISP languages originated around 1960. The use of let then caught on in other languages, including OCaml and Haskell, and eventually JavaScript.
(It's possible some language other than LISP was the first to use let, but my suspicion is it was LISP.)
I'm specifically saying about `let` syntax in this particular language. LISP and related languages also have `let` with substantially different semantics, but it's evident that it wouldn't make much sense given current examples.
I love '{thing}' for string interpolation.
If you haven’t already, check out clojure, janet-lang, io-lang, and a library like lodash/fp for more syntax and naming inspiration.
Keep building!