Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: G-Fu – a pragmatic Lisp embedded in Go (github.com/codr7)
123 points by codr7 on May 25, 2019 | hide | past | favorite | 23 comments



Author here.

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

[1] https://github.com/pcostanza/contextl


Thanks for posting this!

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.

[1] https://github.com/AZHenley/goforth


Cool.

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.


If Go can't load code at runtime, how do you plan to add a "real" lisp REPL?


It can using plugins from what I've seen. I'm not aiming for a regular Lisp though, g-fu is designed to be embedded in and complement Go first hand.


FYI, plugins in Go only work on linux and macos. Windows has the option to load dlls dynamically, but it is a different mechanism. If I remember right the Go devs were not planning on making plugins work on other platforms because of having to make the PE format work(?)


Yeah, so I heard.

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.


> first class environments

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?


How so? I get that going the route of Python and Lua and using a general purpose data structure for the environment isn't optimal. But g-fu exposes the already existing environment as a separate type, the only thing it knows how to do is map symbols to values and access is restricted to a few special forms just like any regular Lisp enviroment.

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.



I find Clojure refreshing, but it has too many agendas for me and Java is just (a) no Go. I tried, I did. And launching the repl felt like watching grass grow on my latest/greatest macbook. And if I'm going to use a Lisp in Go, I definitely prefer one designed around Go to one imported from Java.

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


BTW, there's a Lisp that compiles to Go AST, and then derives Go code from that. (Won't find it right now, though.)


I've been considering compiling the interpreter as a shortcut to native executables, but to Go rather than its AST since that allows reusing the existing runtime.

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.


There's an approach to compilation where you take the input program, but instead of running it you output what the interpreter would do, as a new program. So you get meh performance but you have an executable.

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...


Yep yep, we're talking about the same thing. I like to call it an inline interpreter.

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.


Here it is, I think: https://github.com/jcla1/gisp


Thanks.

It's very shallow though, more demo toy than practical tool like most Lisps.


I'm not sure if you mean, "Like most Lisps, it's more demo toy than practical tool," or, "Unlike most Lisps, it's more demo toy than practical tool." Depending on whether by "most Lisps" you mean most established Lisps or the numerical majority of Lisp implementations, I could see either reading, and your punctuation doesn't make it clear. There are a lot of zero-user toy Lisps out there.


That was my point, most of them aren't even trying.

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.


This looks really cool :)

Though full disclosure, I clicked for the jokes about Greenspun's tenth rule, and I'm vaguely disappointed I didn't find any.


I'd guess an experimental Lisp interpreter embedded in Go is just too obvious :)

But providing Gophers with a slightly more polished alternative that still composes well with Go-code might help avoid the worst nightmares.


How do you call out to Go libraries with this?


You would have to wrap the call in a g-fu prim [0] for now. As for dynamically loading libraries, the plan is to implement g-fu libraries that call out as plugins. I have yet to dig into reflection to see how much effort an FFI would take.

[0] https://github.com/codr7/g-fu/blob/master/v1/src/gfu/abc.go




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: