Show HN: G-Fu – a pragmatic Lisp embedded in Go
github.com
github.com
It's still a young language and naive implementation focused on correctness, but I'm very happy with how its turning out.
I'm especially fond of first class environments and qualified identifiers [0]; which allow composing, overriding and delegating data and behavior in a convenient yet remarkably flexible way. It's clearly a more fundamental mechanism than the usual suspects.
Note that this is the opposite of what Python is doing with __dict__ and Lua with tables. Rather than basing the implementation on a general purpose data structure, g-fu exposes the the implementation and allows hooking into it.
It reminds me of pcostanza's work on Context Oriented Programming and ContextL [1], but integrated rather than bolted on.
[0] https://github.com/codr7/g-fu/tree/master/v1#environments
I made a toy Forth in Go recently [1] but didn’t really know what I was doing. I’m going to check G-Fu out to understand how I should have implemented mine.
I've written my share of Forths, but none in Go. Lisp is definitely more involved, especially expanding macros and juggling environments.
You're welcome :) Note that I'm still in the process of simplifying and refactoring quite heavily. Feel free to get in touch if you run into anything weird, and I'll do my best to help make sense of it.
I have yet to try plugins myself, but I've implemented the same mechanism using dlopen in C.
I'm almost hoping that big G is forced by greed to include Windows. Otherwise some kind of shim on top of DLL-loading might be an option.
Which are notorious for being unoptimizably slow
> It reminds me of pcostanza's work on Context Oriented Programming and ContextL
I'm not reminded at all. Can you expound?
Well, context oriented programming is all about separating the system into layers of behavior that may be flexibly and conveniently composed to get the right mix of functionality. Which is exactly what g-fu is doing with first class environments.
The Clojure-code I've written, while terse; always feels too far off from what I want to say. I have the same issues with Haskell, too much hoop jumping to take part in someone else's quest for purity.
There's plenty I like in there and Rich is a very disciplined thinker. The languages have much in common. g-fu's way of using environments looks a lot like Clojures use of maps if you squint.
Transducers are brilliant, it's difficult for me to believe it took this long. Which is why g-fu uses [0] them as the foundation for all sequence transformations.
[0] https://github.com/codr7/g-fu/blob/master/v1/lib/iter.gf
The main idea behind G-Fu is to complement Go by providing a more expressive experience while delegating the heavy-lifting. Which means that performance is far from the top priority.
Here's a project doing that: https://news.ycombinator.com/item?id=19508616
This is a theory around this approach: https://en.wikipedia.org/wiki/Partial_evaluation#Futamura_pr...
It's a nice compromise. The emit-logic can be kept fairly uniform and low-maintenance since its more or less identical to the regular interpreter.
I got around 10% increased performance on a Forth in C for whatever that's worth.
One thing to keep in mind is to use functions in the emitted code rather than simply dumping everything in a pile. Most compilers don't deal well with code piles from my experience , which makes the code both compile and run slower than it could.
It's very shallow though, more demo toy than practical tool like most Lisps.
And the posted link seems to be one of those.
Just wanted to note that its not really comparable to what g-fu is doing.
Though full disclosure, I clicked for the jokes about Greenspun's tenth rule, and I'm vaguely disappointed I didn't find any.
But providing Gophers with a slightly more polished alternative that still composes well with Go-code might help avoid the worst nightmares.
[0] https://github.com/codr7/g-fu/blob/master/v1/src/gfu/abc.go