
Show HN: A Lisp compiler and environment in Go - eatonphil
https://github.com/gsp-lang/gsp
======
jgalt212
Along these lines, do people here think porting Clojure to use the Go VM a
worthwhile endeavor?

Or, to the contrary, if one just wants to avoid the JVM, would it just be
better to write Clojurescript?

That being said, having one binary to distribute and install is a very strong
argument for Go VM languages.

~~~
wtetzner
I wasn't aware there was a Go VM.

~~~
tptacek
There isn't, of course, but if you mentally substitute "runtime" for "VM", the
question is perfectly valid.

~~~
anjanb
In this context, what's the difference between a "runtime" and a "VM" ? What
does a "VM" have in addition to a "runtime" ?

~~~
wolf550e
[https://en.wikipedia.org/wiki/Runtime_system](https://en.wikipedia.org/wiki/Runtime_system)

libc is a runtime, but not a VM.

~~~
tptacek
Also compiler calling conventions, the memory map, program initialization, the
GC subsystem...

------
howeyc
Interesting, looks almost like how you'd write Go using S-expressions. Seems
like you have access to the stdlib from the examples. I wonder if you could
use other Go libraries. I also wonder if you can use co-routines or channels.

This[1] allows you to write something resembling Scheme R5RS but with some Go
extras like channels/co-routines, but no access to Go's stdlib.

[1] [https://github.com/kedebug/LispEx](https://github.com/kedebug/LispEx)

~~~
eatonphil
You should be able to reach any Go library, in fact. Aside from the Prelude,
the Gsp Stdlib[0] is in fact just bindings to the Go stdlib that casts every
value from interface{} into the required type. You can make bindings to any
other library in this manner.

I do not know why Go-routines would not work, though I have not tried yet.

Another difference from the lisp you brought up (and the one I'm more familiar
with, glisp[1]) is that Gsp is compiled as opposed to interpreted. This would
ostensibly have speed features.

I am interested to test how this fares compared to these other Go Lisps and
Clojure.

[0] [https://github.com/gsp-lang/stdlib](https://github.com/gsp-lang/stdlib)

[1] [https://github.com/zhemao/glisp](https://github.com/zhemao/glisp)

------
current_call
Wouldn't it be easier to just work in the reverse direction?

[https://github.com/zkat/chanl](https://github.com/zkat/chanl)

~~~
steveklabnik
It might be easier, but showing both directions is still very cool.

------
e12e
It may be a naive quesiton, but what does "prelude" mean in this context? I
get that I can use this to emit go code from gisp, and compile that. But the
example under the heading "using the prelude" doesn't really tell me anything.
Looking at the code, it appears to define a lot of basic lisp stuff -- but
without all that, how does gsp work in the first place?

Is it simply the difference of wrapping things up so that they... work?:

    
    
        diff <(gsp hello.gsp) <(gisp hello.gsp)
        4,7c4,5
        <       "github.com/gsp-lang/stdlib/fmt"
        <       "github.com/gsp-lang/gsp/core"
        <       "github.com/gsp-lang/stdlib/prelude"
        <       "github.com/gsp-lang/stdlib/net/http"
        ---
        >       "/fmt"
        >       "/net/http"
        18,19d15
        < 
        < var _ = prelude.Len
    

As far as I can tell, gisp doesn't produce go code that can be compiled. But
what good is the go code gisp produces? Can/should it be saved to file and
imported into another go program?

~~~
eatonphil
I'm not sure what gisp you are running. The gsp program adds some imports by
default (including the prelude). On the other hand, jcla1's gisp definitely
does not include these files unless you do so manually in the .gsp file.

~~~
e12e
As far as I know, that's "regular gisp (rm $(command -v gisp); go get -u
github.com/jcla1/gisp), and the full hello.go it produces is:

cat hello.gsp (ns main "/fmt" "/net/http")

    
    
        (def hello (fn [w r]
          (fmt/fprintf w "hello")
          ()))
    
        (def main (fn []
          (http/handle-func "/" hello)
          (http/listen-and-serve ":8080" nil)))
    

gisp hello.gsp

    
    
        package main
    
        import (
                "/fmt"
                "/net/http"
        )
    
        func hello(w, r core.Any) core.Any {
                fmt.Fprintf(w, "hello")
                return nil
        }
        func main() {
                http.HandleFunc("/", hello)
                http.ListenAndServe(":8080", nil)
        }
    

(Which go won't compile due to errors with imports, missing core.Any etc).

I realize hn isn't the best place to discuss issues, but if anyone have played
with gisp, and could shed some light (eg: maybe gisp is go 1.4 only?) that'd
be great.

Incidentlially gsp/gspc seems to work as intended. Maybe I'm misunderstanding
the purpose of gisp?

~~~
eatonphil
I think you are just having path issues. Also, you are using a gsp example to
test gisp. There are a few shorthands that gsp supports that gisp does not -
such as imports starting with /. Gisp will not resolve these.

If you continue to have issues and want to get it working correctly, feel free
to email me.

~~~
e12e
Thank you four your reply. I had my suspicions that might be the issue (the
shorthand/differences between gsp/gisp in particular). I also played a bit
with the simple factorial example[f] from gisp -- which apparently doesn't
work with gps(c) (gisp apparently allows calling casts as functions [eg: (int
ImNotAnIntButAfloat)] -- looks like gsp chokes on that.

After some tweaking I couldn't get [f] to work with gsp (but it worked fine
with gisp + go build). Looks like both projects could use some more (esp.
motivating) examples, and maybe a little more introduction/documentation. At
least enough to encourage play :-)

[f]
[https://github.com/jcla1/gisp/blob/master/examples/factorial...](https://github.com/jcla1/gisp/blob/master/examples/factorial.gsp)

~~~
eatonphil
Good call with the casting issue. I'd been seeing that that wasn't working
correctly but I just now figured it out.

Gisp lacked the ability to have function arguments actually be functions
themselves. Gsp gets around this by casting __all__ (a lazy move, I know)
functions to interface{} then to func([arg core.Any]+) core.Any.

I do stop this behavior for a certain whitelist - I need to add
int/float64/bool/string to that list I think.

This was definitely just a first step. I think getting the Prelude to work is
by far the coolest part. It did actually take a lot of trial and error hacking
gisp -> gsp to get it working.

After this I will probably look into self-hosting documentation and maybe a
cookbook.

~~~
e12e
Good to hear :-)

Btw, I'm still not sure what "prelude" means in this context...

------
deadprogram
This looks very interesting...

