
Kashmir: A statically typed Lispy language compiling to Go - owickstrom
https://owickstrom.github.io/kashmir/
======
gus_massa
I'd really like to see an snippet in the front page. There are some samples in
the tutorial, but I like to see an example to get some feeling of the
language. For example, a mix of

    
    
      (define (factorial n)
        (if (< n 2)
            1
            (* n (factorial (- n 1)))))
    

and

    
    
      ;; here the type of y is inferred
      (fn ([x : int] y) (+ x y))

~~~
owickstrom
Good idea, thanks! I'll try to come up with something representative.

~~~
cjslep
Do you know how much effort/time it would take to spin up a "play.kashmir",
similar to "play.golang"? If it is minimal, it could be one of those items
that really lowers the barrier to entry into the language.

~~~
nothrabannosir
Especially if you just do the compilation to Go and redirect the user to a
prefilled play.golang.org page with the resulting code.

And a comment withe original code and a link back to your site :)

~~~
smt88
Pre-filling a page on another domain isn't possible unless the creator of that
page explicitly creates a way to do it. That's an important security feature
of web browsers.

~~~
nothrabannosir
You can create and run the entire snippet and redirect the user to the
resulting page. "Prefilled" was a poor choice of words :(

------
jlarocco
I understand this project, along with most of the other "Lisp compiling to
..." projects are just for fun, but it's still annoying to see so many of them
announced. Half the time it's a stretch to even call them "a Lisp." It's a
little silly to call your language a Lisp if it's missing a lot of the stuff
that Lisp is associated with. Does this Lisp even support macros? Just say
it's a new language that uses s-expressions and compiles to Go or whatever.
Calling it a Lisp makes it look like a lame attempt to get more attention.

I'm mostly just annoyed because everyone releases all these incompatible Lisp
wannabes, when Common Lisp, Scheme, and even Clojure, are all perfectly good
languages. Common Lisp has a few really good compilers (sbcl, lispworks, etc.)
that produce code that's competitive with C in some situations. QuickLisp has
really modernized the CL library ecosystem, and while there aren't as many
libraries available as there are for Python, Ruby, and Java, the situation has
drastically improved recently, and is continuing to improve.

~~~
throwaway533634
Here here! It seems like every week someone posts their pet flavor of lisp.
This doesn't have an substance. How about coming up with something new!

~~~
kristianp
I hope I don't get downvoted for this, but the correct way to say this is
"hear hear". It's derived from "hear him" or "hear her".
[https://en.wikipedia.org/wiki/Hear,_hear](https://en.wikipedia.org/wiki/Hear,_hear)

------
jrapdx3
As a long-time user of Lisp-derived languages (Scheme, Tcl), Kashmir looks
like an interesting variation.

It's heartening to see a revival of Lisps. For reasons I can't explain, s-expr
syntax has a certain symmetry and beauty and is far more understandable to me
than the alternatives.

Not sure yet what Kashmir brings to the table besides the Go output, and what
advantages that provides. I'll have to study it further.

A half-formed thought floats across my brain that a Lisp/Scheme compiling to
Rust might have merit. Considering the idea that a Rust back end could
possibly minimize the necessity for GC, performance of the resulting
executable would be less encumbered.

Really don't know how far one could get in that direction, probably more
difficult to achieve than I could imagine.

~~~
javajosh
It's because you understand that programs, when you write them, are frozen at
time zero, that it's s-expr tentacles are ready to accept inputs, and when
they get an input, they contract in computation and, for long lived programs,
emit _new tentacles_ that no programmer ever wrote.

(If you can write reliable tentacles and dress them up so that people want to
touch them frequently, you can become very, very rich.)

------
readams
What is the advantage of targeting go for a new language project? Could you
explain about why this made sense for your project?

~~~
jondot
There are so many motivations for this (and so many lisp/go projects that are
abandoned). This looks _very_ promising and I hope it takes off.

A few of the motivations:

* A lisp with an amazing startup time

* A lisp that can tap into a big and vivid ecosystem, like Clojure is tapping into Java's and its own

* Cross compilation and self-contained binary (I've personally tried doing this with various lisps, and none of them _really_ support it)

* Go as a platform is improving version by version and is very performant already

Another way to think of it - if only Clojure compiled to binary directly, then
this would be pointless. Because chances of that happening are virtually zero,
is why this project made my day.

Go is the assembly language of cloud infrastructure, just as Javascript is
becoming yet another "assembly" language. I believe Go is perfect for this,
because it is also simple (as opposed to ES6, for example).

~~~
hyperpape
"Go is the assembly language of cloud infrastructure"

People say this about JavaScript because to run code in a browser, it has to
execute as JavaScript. As a result, there are lots of actual libraries or
webapps that are written in other languages and compiled to JavaScript.

In contrast, you can do cloud computing in Java, C++, or various other
languages. Go may have advantages, but compiling to Go would just be a choice.

In short, I really don't know what you meant or why you'd say it.

~~~
bipin_nag
Javascript would be the assembly language of web i.e. what runs on your
browser. Although that won't be true with the advent of Webassembly. Go is
language of choice on cloud.

If you ask me following is the checklist it passes:

1\. Low memory footprint/good GC

2\. Concurrency (goroutines) builtin

3\. Great dependency (package) management

4\. Compiled/closer to bare metal

5\. Fast compilation

If you check other languages against the list they lack at least one of the
above. If you feel any other language is better suited please tell.

~~~
thinkpad20
> Go is language of choice on cloud.

I don't think this makes any sense. Javascript is the assembly language of the
web because it's the _only_ choice for the web (or more specifically, the
browser). At best, any other legitimate choice will just compile to
JavaScript, which is why it's thusly named. Go has no such privileged
position; it's not even clear what it would mean to be the "language of choice
on the cloud." You can write cloud software in any language you want, provided
that the language has libraries for networking. All of the features you list
are great, but none of them are exclusive to Go, nor are they required for
cloud computing.

~~~
bipin_nag
I agree that that the statements cannot be analogues. But then I never implied
it. My answer was only to counter the statement that JavaScript is the
assembly language, in future WebAssembly will likely take that role. Then I
continued on my intended answer of why Go is the preferred language.

------
jaytaylor
Here are nice code samples:

[https://github.com/owickstrom/kashmir/tree/master/experiment...](https://github.com/owickstrom/kashmir/tree/master/experiments)

------
mtrn
Has anybody come across a list of languages that compile to Go?

~~~
eatonphil
There are a number of Lisp interpreters written in Go [0-3]. There is a Lua
interpreter [4]. The only compiled language I know is Gisp [5] by jcla1. I
also built on top of Gisp with Gsp [6] to provide wrappers to the Go stdlib
and support more standard lisp functionality.

However, Kashimir is the first statically typed language implemented in Go
that I have seen. The rest are dynamically typed.

[0] GLISP - [https://github.com/zhemao/glisp](https://github.com/zhemao/glisp)

[1] golisp -
[https://github.com/SteelSeries/golisp](https://github.com/SteelSeries/golisp)

[2] go-lisp - [https://github.com/janne/go-lisp](https://github.com/janne/go-
lisp)

[3] Kakapo -
[https://github.com/bytbox/kakapo](https://github.com/bytbox/kakapo)

[4] Golua -
[https://github.com/akavel/goluago](https://github.com/akavel/goluago)

[5] Gisp - [https://github.com/jcla1/gisp](https://github.com/jcla1/gisp)

[6] Gsp - [https://github.com/gsp-lang/gsp](https://github.com/gsp-lang/gsp)

~~~
mtrn
Wonderful, thanks.

------
owickstrom
Project renamed to Oden and moved to: [https://oden-
lang.github.io/oden/](https://oden-lang.github.io/oden/)

There were a bunch of reasons to change the name and I was going to create a
GitHub organization for it anyway. Kashmir was not a good choice for
Googleability and it turned out there's some city or region in the Kashmir
region called "Golang"... :S

Sorry about the confusion!

------
jerf
Despite the fact this post may appear critical, this is in the spirit of
feedback to a young language, not a mean spirit.

One of the things I'm not sure you're looking at, and that you really ought to
decide sooner rather than later, is how much interaction with Go itself you
want. You very much do not want to leave the Go FFI interactions until the
end.

In fact I daresay this is a critical decision that needs to be the next thing
you really spend a lot of time thinking about, because a Kashmir that has a
very poor Go FFI leaves me little reason to prefer it to Haskell, or Liskell
if you want to get closer to Lisp. (Truthfully, reading over your goals &
features, this sounds closer to Haskell than a Lisp, except in syntax, so I'm
going to use Haskell as my benchmark.)

However, many of those goals and things in the type system will be at odds
with having a simple Go FFI. If all functions in Kashmir are auto-curried,
then Go has a hard time calling in to them, with a clumsy syntax and probably
slow performance. If Kashmir's type system ends up complicated enough that the
Go type system can't express Kashmir function types _at all_ , then Go can't
call into Kashmir at all, or some complicated "generic instantiation" step
will be required. On the other side, you have to worry about data structure
compatibility, too; if Kashmir data structures don't have a nice mapping to Go
data structures then Kashmir is going to have a hard time calling into Go
code.

Also, I'd suggest before proceeding much farther that you are very, very sure
that you understand Hindley-Milner deeply, including what can break it. It
offers a lot of inferring power, but at the corresponding cost of laying a lot
of very specialized restrictions on your program. These carefully
mathematically-specified things often have a way of breaking down the instant
you put a toe outside their specified line. (The Haskell community has added
things to it that have good bang/buck, but it's always something they have to
be careful about.) Go's native type system, for instance, has one huge
difference with Haskell that would have me a bit nervous, which is the
difference between:

    
    
        (+) :: Num a => a -> a -> a
    
        type Num interface {
            Add(Num, Num) Num
        }
    

Haskell's type there guarantees all the a's are the _same_ Num type. The Num
typeclass does not promise that _all_ "Num"s can be added together, only that
a Num can be added to other same type things. Go's type system can not
guarantee this; that interface in Go is promising that either A: You can hand
it any two things that implement Num and it will return yet something else
that implements Num which may or may not have any particular relationship to
the original types or B: it will panic at runtime. (Or loop forever, I
suppose, but it seems strange to be seriously discussing "bottom" in Go at
all....)

Where in practice you can turn to a programmer and say "Hey, obviously, it
makes no sense to add a rational and a Peano integer together, and if you did,
you obviously wouldn't expect a BigInt back. So just don't do that.", your
type inferencer will not be able to make such assumptions, and if it does,
you're right back to the problem that that will raise all sorts of hell in
your FFI.

 _These are not necessarily unsolvable problems!_ For one thing, there's the
sort of degenerate solution of simply not permitting any FFI, and only
permitting Kashmir->Go in a very restricted, stereotypical manner that
requires a specialized binding step. You could also write off calling Kashmir
from Go, if that helps, which is not a bad decision, but is one you should be
deliberate about. But I would suggest it is deserving of being the very next
issue you tackle, and spend a lot of time thinking about. Go's type system is
really, _really_ weak for a static type system, in the sense of what
guarantees it is capable of expressing, and trying to cozy that up to a
Hindley-Milner system without giving up on a lot on one side or the other is
going to be a challenge.

~~~
owickstrom
Thank you for the feedback! I have deliberately not done any big work on the
Go FFI yet because, as you say, I have not thought all stuff through. This is
very valuable input, thanks again!

------
2pointsomone
Can you please give one reason to name the project "Kashmir"?

~~~
newsignup
Pure guess: its beautiful? (in case its about the place in India)

~~~
asadlionpk
Yes a beautiful place conflicted between India and Pakistan. Major cause of
wars and conflicts between the two nations.

------
mattetti
This is a fun project, I'm looking forward to seeing how far you can take it.
One thing to note is that Go doesn't have TCO so performance when using a lot
of recursion might be pretty bad or the compiler has to be smart and use loops
and states.

~~~
sesm
JVM also doesn't have TCO, so Clojure has a special form, which transforms
recursion into an ordinary loop:
[http://clojure.org/special_forms#Special%20Forms--%28recur%2...](http://clojure.org/special_forms#Special%20Forms--%28recur%20exprs*%29)

Author of Kashimir could use a similar solution.

------
AYBABTME
How do goroutines work out? And/Or channel and stuff like `select`?

~~~
owickstrom
Currently not at all. :) Haven't gotten that far yet, but I have it in mind.
There will probably be a 1:1 mapping to these concepts in Kashmir.

~~~
AYBABTME
Cool, looking forward!

------
nrioux
Is targeting Go source code like this really the best option for a Go-like
language? I've been curious about hooking into some stage of Go's compiler.
Looks like there is an intermediate Go assembly language, which PeachPy
([https://github.com/Maratyszcza/PeachPy](https://github.com/Maratyszcza/PeachPy))
can target. Not sure how well documented it is, though. Anyone know of other
projects that do this?

~~~
owickstrom
Probably not the best option in the long run, but I didn't want to focus too
much on that to begin with. Hooking into the Go compiler would be nice,
perhaps that's something to look at when the Kashmir compiler can be written
in Kashmir. :)

------
bsurmanski
Is this intended as a human-written language, or as a target for machine
generated Go?

In my mind, the second one is where this language can really find it's niche.

~~~
owickstrom
Human-written is the purpose, but as it builds on the LISP syntax, which is
just simple data structures, generating it would be simple. I guess one could
do a more Haskell-like syntax front-end for Kashmir and transform it.

------
S4M
I am sure Kashmir is a great idea - in fact, I was wondering why there
couldn't be a typed lisp compiling to C, but please put more coding example!

~~~
owickstrom
Cool! :) I'll add more examples as soon as possible. Actually there's not much
you can do with Kashmir at the moment, I've mostly focused on getting the
basic model up so there's no library functions available etc. I have an idea
about how to read the type signatures from compiled Go packages to be able to
do simple interop between Kashmir and Go - no extern declarations or anything
like that.

~~~
S4M
One thing I wonder: does _let_ take types? Something like:

    
    
        (let ((x :string "hello"))
             (fmt.Println (+ x "owickstrom")))
    

(Although in that case the type can probably be infered...)

~~~
owickstrom
It does!

    
    
      (let (([x : string] "hello"))
        (fmt.Println (+ x "owickstrom")))

------
deadprogram
I'm looking forward to trying this with Gobot
[http://gobot.io](http://gobot.io)

------
codygman
Just now seeing this, wondering if it will generate code readable enough to
contribute to Go projects.

------
kureikain
Amazing work. I always want to learn more about creating a language. Will look
more into this.

------
DHJSH
Then just use llgo and compile it to asm.js!

