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))
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.
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.
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.
I realize that it is missing some of the defining features of a real Lisp, that's why I wrote "Lispy" in the HN title. However, there's surely some parts in the documentation that says it's a Lisp, and that might be a stretch right now.
Anyhow, I wanted to get some feedback on this project and perhaps involve people early on, so not having macros yet is nothing that I'm ashamed of. I hope to implement them soon.
And yes, there are a lot of good compilers out there. Kashmir is not a replacement for any of them or any of the established Lisps. :)
"Lisp" is easier on readers. If he said "s-expression language", I wouldn't immediately have a feel for the level of abstraction he was aiming for (webasm has an s-expression representation but is low level).
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
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.
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.)
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).
"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.
I don't think (s)he meant Assembly, but rather the language used to "assemble" an awful lot of the modern cloud infrastructure. If you use Docker or CloudFlare, which I would think covers a sizable portion of new projects, your code is passing through something written in Go.
Google did a pretty amazing job of walking back the "replacement for C" talk and positioning Go as the language for web/micro/cluster/distribution/cloud/interconnected services.
But maybe I misinterpreted and (s)he meant Assembly.
Go made choices that makes it a good language to be compiled to. Compilation-wise: it's incredibly fast and compiles to static machine binaries. Runtime-wise: it has great concurrency and communication primitives.
Interesting. What I've heard about Google Go is that the design choices make it very difficult to implement a repl in. So I would expect any other language that compiles to it to be subject to the same limitation, making it a rather poor fit for a Lisp... but maybe I'm missing something?
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.
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.
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.
Eh... Then why are people experimenting with vendoring?
> 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.
Ocaml checks all of them. So does Haskell (with stack package manager), with only the low memory requirement being challengeable since many aren't used to optimizing lazy evaluation.
Both languages you suggest require more learning (both have origins in academia) and are less popular compared to Go in usage.
Regarding the package management comment. If it is an experiment let results get in. Some people consider vendoring bad yet others find some use in it. If vendoring happens like it or not it wont make dependency management bad as a whole.
I don't know about 'easy', but it just calls GCC in the end, so anything that can be made to work with GCC can be made to work with Chicken. Apparently building Windows binaries on Linux can be done with MinGW, though I've never tried:
http://www.blogcompiler.com/2010/07/11/compile-for-windows-o...
That's said, the project states more flexibility as a goal - specifically supporting generics. Between code generation and the cross-language compiler, writing generics (but generating non-generic Go code) should be somewhat easy to reason about.
There are many reasons using sexp's can be better than just writing Go including but not limited to:
- structured editing of source code
- macros (dry, dsl's, etc)
- if your Go code uses interface{} everywhere you'll probably have more of an advantage using dynamic typing anyway.
Don't know about the project's motivations, but I've been hoping for compile-to-go languages because it has an amazing cross-compiler. My use case would be to develop small apps on linux and ship self-contained binaries for other platforms effortlessly.
It does actually make a fair amount of sense. Go already has:
* Fast compilation
* Very very easy cross-compilation
* A pretty good garbage collector
* A huge library of easy-to-use libraries (they don't suffer from StringCollectorBeanFactoryProxy-syndrome)
* Good concurrency support
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.
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
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.
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!
Well I think its not the best idea to confuse people's perceptions of very important ideas of our existence as humanity, just because it was a cool 2-syllable name found in interest of saving time on Google.
Kashmir resonates very strongly and has strong meaning for a significant % of the world's population. Think about coming up with a name like "Crimea" for a language if it has no connection whatsoever. If it does, that's great, may be the author can draw the connection to it on the website.
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.
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) can target. Not sure how well documented it is, though. Anyone know of other projects that do this?
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. :)
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.
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.