Elektrine lite

← Feed

@kasdeya@cryptid.cafe

Post #2333247

2026-05-06 19:53 UTC

idk if y’all remember my idea for a #Lisp where all expressions are actually #Lua -style tables, instead of linked lists like a normal Lisp. (I’m calling these expressions T-expressions btw, since they’re not quite the same thing as S-expressions, and they make Tables) but lately I’ve been trying to figure out a way to add symmetry between defining a variable and adding a key to a table. like here’s a table literal: '([key value] [key2 value2]) and ideally I’d love to be able to reuse this concept as the way to define variables. because I want this language to have as little magic as possible and as few discrete concepts to learn as possible, and a special form like (define) would be a discrete concept that I want to get rid of. so I considered letting people do something like this: [variable 666] (print variable) ; -> 666 and it would work for any nested T-expressions too: [variable "foo"] (do [variable 666] (print variable)) ; -> 666) (print variable) ; -> foo (print [variable "bar"] variable) ; -> bar but the main problem is that in order to resolve this, the reader would have to work in phases with the interpreter: (do [variable 666] (print variable) ; ↑ the reader only goes this far, ; then this gets interpreted [variable "foo"] (print variable) ; ↑ now the reader stops here and ; lets the interpreter work again ) which intuitively seems to me like it would probably be a terrible idea. alternatively, it would be a syntax error to redefine the same {variable / table key} in the same scope, which might work well enough this would also mean that sending keyword arguments to a function would have to use less elegant semantics: ; if these are variables instead of ; kwargs: (func ['kwarg0 value0] ['kwarg1 value1]) ; then kwargs would have to just be ; this, like a normal Lisp. which ; isn't as elegant :/ (func :kwarg0 value0 :kwarg1 value1) ; alternatively, you could do ; something like this, which is IMO ; a bit better (func [:kwarg0 value0] [:kwarg1 value1]) but the biggest problem with this idea is that they would be absolutely terrible in any kind of deeply-nested data structure, since every single key-value declaration would also be clobbering a variable: [id 666] `([name "Earth Machine"] [element ""] [id 667] [submachine ([name "Earth Submachine"] [id ,id] ; <- oops! this is ; 667, but I wanted ; 666 )) I could fix this by saying that “by convention, all variables declared in a table should start with a $“ or, “by convention, all table keys that will be used as table keys (and not as variables) should be keywords”. and the latter does sound kind of reasonable actually, yeah. I really really like that last option. because then you can create variables with any arbitrary scope that you want, inside of literally any T-expression that you want, without increasing the level of indentation, and you can define them pretty much anywhere, and they won’t interfere with deeply-nested data structures at all, and they won’t mess with the reader -> interpreter pipeline either! that’s actually an amazing solution, unless I’m missing some reason why it won’t work

Replies (1)

  • @kasdeya@cryptid.cafe 2026-05-06 19:55

    this does mean that the semantics of foo.bar.baz would change from (. foo 'bar 'baz) to (. foo :bar :baz) but that’s really not that bad, I don’t think. bar and baz are already being quoted in the first example, so the implicit behavior of turning them into keywords (instead of symbol literals) is really not that big of a deal

    Open ##2352666