Live data from Hacker News

Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

github.com

61–70 of 73 posts

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#61

Interesting: https://github.com/robpike/lisp/blob/master/lisp1_5/parse.go... // Expr represents an arbitrary expression. type Expr struct { // An Expr is either an atom, with atom set, or a list, with car and cdr set. // Car and cdr can be nil (empty) even if atom is nil. car *Expr atom *token cdr *Expr } Instead of using interface types for expressions, there is a simple expression structure type with fields that ma…

I wrote a toy lisp 1.5 interpreter in Go a few years ago, and part of the joy was making the core of the interpreter mimic McCarthy's typography. This is my apply function:

  func apply(fn, x, a Addr) Addr {
          if atom(fn) == T {
                  switch fn {
                  case CAR:
                          return caar(x)
                  case CDR:
                          return cdar(x)
                  case CONS:
                          return cons(car(x), cadr(x))
                  case ATOM:
                          return atom(car(x))
                  case EQ:
                          return eq(car(x), cadr(x))
                  default:
                          return apply(eval(fn, a), x, a)
                  }
          }
          switch car(fn) {
          case LAMBDA:
                  return eval(caddr(fn), pairlis(cadr(fn), x, a))
          case LABEL:
                  return apply(caddr(fn), x, cons(cons(cadr(fn), caddr(fn)), a))
          }
          panic(errint("bad node: " + car(fn).String()))
  }

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#62
post #49

Earlier quoted context omitted.

Yes, he might be a famous programmer like kazinator instead of the co-author of The Practice of Programming and one of the fathers of Go.

don't forget those insignificant little 'Unix' and 'Plan9'/'Inferno' things...

Whilst Pike contributed to Unix it was Thompson's and Ritchie's invention - at least originally

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#64

Interesting: https://github.com/robpike/lisp/blob/master/lisp1_5/parse.go... // Expr represents an arbitrary expression. type Expr struct { // An Expr is either an atom, with atom set, or a list, with car and cdr set. // Car and cdr can be nil (empty) even if atom is nil. car *Expr atom *token cdr *Expr } Instead of using interface types for expressions, there is a simple expression structure type with fields that ma…

I find this a fascinating topic, so forgive me for this reply which has turned in to a mini blog post of sorts... Go embraces the common insight that you can encode a sum as a dependent product. That is, here, you have a discriminated union of atoms and cons cells, but the discriminant is not a specific tag value, as it would be in Haskell or ML or similar, but rather the nil/non-nil state of these fields. Of course,…

Stepping further from Go, this same principle is at play in Clojure, which favors open maps for information.

Curious, know little Clojure but isn't "open objects" a Javascript thing too? What is special about Clojure here?

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#65

Earlier quoted context omitted.

Well-timed for you, but Pike could have benefited from doing this experimentation forty years earlier. Who knows where he would be now?

Yes, he might be a famous programmer like kazinator instead of the co-author of The Practice of Programming and one of the fathers of Go.

He also co-invented an obscure encoding called "utf-8" that nobody uses.

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#66
post #64

Earlier quoted context omitted.

I find this a fascinating topic, so forgive me for this reply which has turned in to a mini blog post of sorts... Go embraces the common insight that you can encode a sum as a dependent product. That is, here, you have a discriminated union of atoms and cons cells, but the discriminant is not a specific tag value, as it would be in Haskell or ML or similar, but rather the nil/non-nil state of these fields. Of course,…

Stepping further from Go, this same principle is at play in Clojure, which favors open maps for information. Curious, know little Clojure but isn't "open objects" a Javascript thing too? What is special about Clojure here?

In the context of that statement, nothing.

I called out Clojure specifically because of the culture around this specific issue and because of the dispatch design of the multimethods that are present in the standard library and widely favored. Nothing stops you from making dispatch tables or simply switching on a key in JavaScript.

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#67

Earlier quoted context omitted.

I find this a fascinating topic, so forgive me for this reply which has turned in to a mini blog post of sorts... Go embraces the common insight that you can encode a sum as a dependent product. That is, here, you have a discriminated union of atoms and cons cells, but the discriminant is not a specific tag value, as it would be in Haskell or ML or similar, but rather the nil/non-nil state of these fields. Of course,…

Objective-C zero-initializes ivars, and it's common to rely on this. The big problem is that you still need to test that code is doing the right thing when it encounters a nil state. If you define away the zero states completely with sum types, code flow is completely accounted for at compile time, and entire categories of "oops, that shouldn't be nil right now" bugs simply don't exist. On Apple platforms, this is a…

It depends on whether or not you view "oops, that shouldn't be nil right now" as a categorically different problem than "oops, this integer shouldn't be greater than 10 right now" problems. Or "oops, this array shouldn't have an odd number of elements right now" problems.

Yes, it's nice to have the type system catch problems. And yes, in the context of memory-unsafe languages null or wild pointers are a big problem. But I've found that you'd need a combinatoric explosion of data constructors and abstract interfaces to enforce the interesting invariants of my programs. A nil pointer (which panics at runtime with a good stack trace!) tends to be among the easiest problems I have to solve when my programs violate invariants.

I'm not arguing that sum-types are a bad idea. Only that dependent products (with or without enforcement, static or dynamic) are an under appreciated technique. Sum-types are really just one special case of dependent products.

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#68
post #55
post #31

Earlier quoted context omitted.

There is a GNU implementation of APL ( https://www.gnu.org/software/apl/ ). Not sure if it is used in commercial applications or not. I would imagine that if you are doing commercial work with APL you are going to be paying for Dyalog.

> you are going to be paying for Dyalog Not really. As I see APL is ISO standardized and there are many implementations.

There are many implementations but not as many that are active (here is a brief list https://en.wikipedia.org/wiki/APL_(programming_language)#Mod...). Dyalog provides more than just a interpreter/compiler but an entire development environment.

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#69
post #3

Earlier quoted context omitted.

Personally, I find that one much more interesting. Before I was familiar with array languages, I hoped that functional programming and lisp would become the new zeitgeist of software development. Now, I think that array languages have the most promise in revolutionizing the discipline. While it probably wont happen, I wouldn't complain if array languages became the defacto norm for most new applications.

I always get the feeling that a lot of languages would be well served by having an APL or prolog implementation added as a library or macro; this would let teams leverage these tools down in the core of their application without having to compromise on how they create APIs. Closest I’ve seen to this was core.logic in the Clojure community, but it appears to be dead.

Datalog is very much alive in Clojure, there are many implementations and you pick between in-memory and disk based ones.

Re: Robpike/Lisp: Toy Lisp 1.5 interpreter in Go

#70
post #45
post #41

Earlier quoted context omitted.

I spoke to Rob shortly after he wrote this code (a few weeks ago). He said he had been wanting to do some coding over the weekend and pulled his copy of the LISP 1.5 Programmer's Manual - which he bought long ago, in grad school I think he said - off his shelf, and this code was the result. He also talked about how reading that book back when he bought it was incredibly eye-opening at the time and had such a signific…

It's not worth responding to people like that, but it's funny now to point out that Wadler says in the Featherweight Go video that Go's type system has something that Haskell's type system may like to borrow, i.e. that interface types are open: https://www.youtube.com/watch?v=Dq0WFigax_c It's somewhere in the first 10-20 minutes (if someone wants to give a timestamp link) (Also, my experience is that such comments us…

https://youtu.be/Dq0WFigax_c?t=912

(on closed vs open and haskell)

Post reply on HN