Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Rhine – A typed Elixir-inspired language on LLVM (github.com/artagnon)
81 points by artagnon on March 20, 2016 | hide | past | favorite | 16 comments


Building any language is hard, so congrats!

That said... the big thing about Elixir is that it's got Erlang and OTP behind it.


> Building any language is hard, so congrats!

Absolutely. Having tried to write a dead-simple Lua-like language [1], I can attest that it requires the programmer have a very complex graph of semantic requirements in their head at all times while writing the language, in order to not mess anything up, involving the types, the GC, the compiler, the parser, the lexer, the calling conventions, everything. I have high respect for anyone who actually goes through with writing one to a point of it being usable.

[1]: it did not go well, so much so that I have absolutely nothing to show for it


I gave quick look at the example. First reactions coming from OO languages and Elixir:

I can imagine that this

    def addCandidate(A ~Int, B ~Int) do
means that addCandidate has two arguments of type Int, but what does the ~ mean? I'll have to read the docs.

However I have really no idea of the meaning of

    def bar(arithFn ~Function(Int -> Int -> Int)) do
It's a function bar taking arithFn as argument, which is a function with... what arguments?

From the demo program it looks like a function with two int arguments returning an int, but why the -> signs and why isn't addCandidate defined as (Int -> Int -> Int) too? Where is it's return type. Maybe inferred?

It's quite puzzling and there are no explanations about that in the README.

Is the ~ necessary? Could it be removed and save one character that's not even on some keyboards around the world?

Apart from that lack of explanations, it could a perfectly nice language and it's a great project for sure.


Function signatures like (Int -> Int -> Int) should be familiar to anyone familiar with functional languages (f#, ocaml and haskell come to mind as having similar notation). I would also assume the return type of addCandidate to indeed be inferred.

That said, maybe the README does lack a bit of introductory text, especially if their targeted audience is programmers in general.


> From the demo program it looks like a function with two int arguments returning an int, but why the -> signs?

This is standard syntax in functional languages. A->B is a function from A to B. A->B->C is a function from A that returns a function B->C. This is the standard curried function application, like used in OCaml, and it enables you to easily partially apply and compose functions.

addCandidate's type is indeed Int->Int->Int, it's simply not declared that way. In OCaml, the following two syntaxes are equivalent:

    let addCandidate = fun A:Int B:Int -> ...body...
    let addCandidate A:Int B:Int = ...body...
I imagine this language is similar.


Yes, I'd implemented the syntax with the intention of doing currying, but haven't gotten around to doing that yet. If you want to do any "partial application", you need to write a lambda, and explicitly pass its function pointer now. The next step is to automatically generate the lambda.


Thanks for the feedback. The ~ is a substitute for :, which is used in other languages for optional type annotations. You're right about removing ~ altogether, Go style. ~Function(Int -> Int -> Int) is a function which takes two integers, and returns one. I've mixed in some Haskell syntax there. And yes, return type is inferred.

There are two reasons for there not being explanations in the README:

1. I foolishly thought it would be obvious.

2. I wanted to focus on the implementation, not the language itself.

In any case, I've added them now, thanks.


Thanks to everybody for all these explanations! I understand the logic of the syntax now.

A nice thing with Elixir is that it lures OO developers like me into the realm of functional languages with a familiar syntax. Int -> Int is not familiar to me. I could guess what it is but then I also see an Int, Int and feel a little puzzled. If one of the goals of this language is to "convert" OO developers maybe you should consider a syntax they are fully familiar with. You could make long time functional developers feel not at home though. Maybe it's a trade-off that's impossible to avoid. It's your call.


I think the bigger point of feedback is that anonymous function signatures are drastically different from defined function signatures.


Why `~Function(Int -> Int -> Int)` instead of `~Int -> Int -> Int`?


Nice project.

As was already mentioned, the main benefit of Elixir seems to come from BEAM, (Erlang VM) and its associated cockroach-like properties. There's also Crystal (https://github.com/crystal-lang/crystal), if what you want is a Ruby-inspired language with static typing and compilation to native code.


I needed a title. I could have said Elixir-inspired or Crystal-inspired, but few people know about Crystal. Although it's only minimally inspired by Elixir, I decided to go with that title.

By the way, I've mentioned Crystal towards the end of the README.


> Effort put into rhine-ml: 2 months

> Effort put into rhine: 1 year, 1 month

Props for the effort put into this! I came across rhine-ml a while ago and thought it would have been a nice, native alternative to Clojure. Both of these projects look very well thought out.

Curious, is this a learning project? It seems that way considering you go into detail about the inner workings.


Thank you. I actually made a lot of design mistakes in both rhine-ml and rhine, which is why I shelved them as "learning projects". I do fully intend to write a solid compiler for a well-designed language in the future. I have to make my mistakes first.

So, for the curious, the big mistake in rhine-ml is making it untyped: it generates terrible LLVM IR that executes super-slowly. I could try and optimize it, or go the types route. I chose types, and I don't believe in the optional-typing escape hatch.

The big mistake in rhine is that I wrote it in C++. It'll be a decade before it can lift its own weight, and OCaml is a great language to build a compiler in.


Does it have tail call elimination?


Nope, sorry. And that was kind of the point I was making: in over a year, I've only been able to do the most foundational work in C++. It'll need another 2~3 years to feature optimizations like that.




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

Search: