
The Earl Grey programming language - breuleux
http://breuleux.github.io/earl-grey/
======
mikejholly
Await, pattern matching and macros are great language features Node and
CoffeeScript both lack. Nice work!

~~~
thomasfoster96
Async/await is coming in ECMAScript 7, so Node will have it soon.

~~~
Dralletje
Define "soon" haha. With the speed of adopting ECMAScript 6 this "soon" could
become really long.

------
fenollp

        fact(match) =  
           0 or 1 -> 1  
           n -> n * fact(n - 1)  
    

why not simply

    
    
        fact(0 or 1) -> 1
        fact(n) -> n * fact(n - 1)

~~~
istvan__
I think the first one is a single function that has pattern matching for the
parameter while the second one is defining the function twice and relying on
the language to call the right one based on the parameter.

I think in Erlang the function identification is the name and the arity and
this is as close I know of what you would like to have.

~~~
TheDong
In haskell you can write exactly the following:

    
    
        fact 0 = 0
        fact 1 = 1
        fact n = n * fact (n-1)
    

It works as you would expect and really they aren't that dissimilar.

~~~
FreeFull
Small correction, fact 0 = 1

------
shakethemonkey
Hyphens in variable names. It's a bold strategy for a scripting language,
Cotton.

~~~
Shoop
I think a lot of lisps use hyphens in variable names

~~~
shakethemonkey
There's plenty of precedent. It's just rare for a reason. I'm not sure
allowing slightly easier access to CSS syntax justifies it.

~~~
agumonkey
I'd love to hear why people prefer underscores over hyphens. I think I grew
out of syntax fanboy-ism, but C and python __private__, _special_variable are
everything but readable to me. They break the visual line too much. Even
historically it was a weird symbol, originally a line break that made it into
non-space separator in PL/1, then almost everywhere. Before that it was pure
formatting, a typewriter glyph to be overtyped/composed on words to underline
them.

~~~
wvenable
> I'd love to hear why people prefer underscores over hyphens.

Because I like subtraction.

~~~
breuleux
Just wondering though, how often _do_ people write subtraction as "stuff-
thing" instead of "stuff - thing"? I find myself typing the latter almost
systemically, so hyphens never get in my way, but of course it's all too easy
to be blind to the habits of others.

~~~
jacobolus
If you have `stuff - thing` it’s no big deal, but once you start having
`(a0-b0)/(a1-b1) + (x0-y0)/(x1-y1)` or whatever, then being able to save all
the spaces starts to be kind of nice, especially if your math expressions get
to be 60 characters long. There are a few times where I’ve definitely ended up
with more readable code by using the presence or absence of a space as a way
to group expressions. Also, I generally prefer to write things like
`array[n+1]` or `array[n-1]` without the extra spaces.

This code example doesn’t actually have any examples of unspaced subtraction
in it, but there are a bunch of other binary operators with space removed. In
my opinion adding spaces around all the operators in this file would make the
code less readable, especially if trying to follow along from the formal
published spec describing the algorithm:
[https://github.com/jrus/chromatist/blob/master/src/ciecam.co...](https://github.com/jrus/chromatist/blob/master/src/ciecam.coffee#L164-L166)

~~~
breuleux
I think using spacing for this can be a little misleading since it can
obfuscate priority. To give an extreme example, 1e100 * 1e300/1e300 is
infinity, because the multiplication is done before the division, but the
formatting suggests it's the other way around. It's not too bad in that case
but if you were to accidentally group an addition instead the mistake would be
harder to spot. I would rather use parentheses all the time to be safe.

Still, you make a good point with the space savings. I guess I just find
hyphens nice enough that I don't mind the tradeoff :)

------
xxyyxx
I like it. It goes further than coffeescript and livescript can. Especially
with macros and better react support

------
evincarofautumn
One one hand, this is yet another syntactic reskin of ideas from modern
imperative-land. On the other hand, it looks like a good one, by a thoughtful
author who also cares about integration with existing platforms, and that’s
not nothing.

------
sssilver
Actually, the language looks and reads great. Keep up!

------
explorigin
High-level comparison with Haxe:

EG and Haxe share: \- compiles to Javascript \- Macros \- Pattern Matching \-
async/await (Haxe requires a 3rd party macro lib, but it integrates well)

EG has: \- cleaner syntax \- document-building DSL \- "One of EG's primary
goals is to be as compatible as possible with existing JavaScript libraries
and frameworks and the node/iojs ecosystem." (Haxe makes compromises here to
support other platforms)

Haxe has: \- static type-checking \- dead-code elimination \- support for more
platform targets (PHP, Python, C#, Java and more) \- years of experience

------
makmanalp
I really like how the tooling to create a full application is already there,
it isn't like "here's my new language, but there are no libraries, good
luck!".

> Global variables need to be declared to be accessible: > globals: >
> document, google, React

If I'm getting this correctly, what a brilliant idea! Contain the shittiness
by having one single location where all globals are declared. So very helpful.

------
andrezsanchez
Glad to see this addressed CoffeeScript's silly issue of variable scope by
just requiring a `var` statement like regular JS.

Also, love the name :)

------
ufo
The "fact(match)" is very strange. In Haskell you have "lambda-case" and in
Ocaml you have "fun" as syntaxes to define lambdas that pattern-match on the
argument.

That said, I really like the inclusion of async and a DSL for documents. These
two are things that benefit a lot from having language support.

~~~
breuleux
"fact(match)" is just making use of a generic feature: the "match" keyword in
a pattern dictates that the body defines a sequence of sub-patterns to match
at that position. An argument uses pattern syntax, so it works there, but it
works in other situations, for example this contrived example:

    
    
        f(x, y) =
           match x:
              {m, n} ->
                 match m:
                    <= 0 -> n + y
                    else -> m + n + y
              n -> n + y
    

Can be rewritten:

    
    
        f(match x, y) =
           {match m, n} ->
              <= 0 -> n + y
              else -> m + n + y
           n -> n + y
    

So you can match hierarchically like that (sorry if the example is strange,
it's not supposed to mean anything).

~~~
ufo
Is there any other language that does this? For me the second example doesn't
look better than the first one.

~~~
breuleux
I haven't seen the feature elsewhere. The second example looks better to me
(syntax highlighting helps) and reduces redundancy and indent, but I guess
views may vary on this. Good to know!

~~~
ufo
If your goal is to reduce redundancy than I think a "lambda-case" syntax might
be a better fit. As a bonus it also lets you use this feature on anonymous
functions!

[https://downloads.haskell.org/~ghc/latest/docs/html/users_gu...](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-
extns.html#lambda-case) [http://stackoverflow.com/questions/1604270/what-is-
the-diffe...](http://stackoverflow.com/questions/1604270/what-is-the-
different-between-fun-and-function-keywords)

~~~
breuleux
There already is a "lambda-case" syntax. "fact(match) = ..." is sugar for
"fact = match -> ...". If one works, then so does the other.

Personally I much prefer the way I do it, because it is more powerful, works
in more places, and requires no new syntactic forms.

------
davenportw15
Does 'each' serve as both forEach and map? It appears that way from the fib
example.

~~~
breuleux
Yes. The compiler detects whether the return value is used or not to determine
whether to accumulate the results in an array or not. Also, unlike forEach and
map you can use continue or break.

------
mbroshi
Looks interesting, but odd that the very first code snippet is an infinite
loop.

~~~
breuleux
God damn it how did I miss that. The condition was wrong, too. Fixed, thanks
:)

~~~
Dewie3
Why not have a "Show HN" if you're the one who made it (assuming from the
URL)?

~~~
breuleux
I... actually did, a while ago. I got no feedback at all, so I thought I'd do
things differently this time around. Might just be a matter of luck.

------
htilford
What was the inspiration to create yet another compile to JS language?

~~~
breuleux
I guess I wanted macros and pattern matching without Lisp syntax, and I wanted
to retain and use the JS/node ecosystem.

There's also a few language features I couldn't find anywhere else that I
wanted to try out (my % operator, ad hoc exception classes, some pattern
matching features like coercion and "match" inside a pattern to define sub-
patterns, the each operator, some features of the macro system that I have yet
to document, etc.)

It's kind of fun, really.

~~~
visarga
What does the % operator formally do? All I could find in the documentation
was :

> Earl Grey's % operator can be used to easily build HTML, DOM, virtual DOM,
> and other things:

~~~
breuleux
There are examples below that statement for common usage, but if you want a
deeper understanding:

    
    
        tag.xyz %
           property = value
           child1
           child2
    

Will produce the data structure:

    
    
        {tags = {"tag", ".xyz"}
         props = {property = value}
         children = {child1, child2}}
    

as an instance of the ENode class. Then, transformer functions can process the
data structure to generate HTML or other things, e.g.

    
    
        require: /html
        html(thing)
        ==> <tag class="xyz" property="value">child1child2</tag>

------
visarga
I love the name but it will get mixed up a lot on Google searches. Just like
it was with the TV series "24" that matched every 24 that was to be found
online.

~~~
loopbit
I typed 'earl grey language' and the first three results refer to this, the HN
article is in fifth position.

The same as typing '24 tv series' will mostly return relevant results.

------
dwg
As someone who currently uses LiveScript professionally, I look forward to
trying out Earl Grey. At first glance it looks very promising.

I'm aware there are many people who don't see the value in creating "yet
another compiles to JS language," or those who view them as simply "syntax
sugar," but I for one very much appreciate the work done by yourself and
others on similar projects.

------
baldfat
Am I the only one childish enough to ask for the language to be called Earl
Grey Hot in honor of Star Trek?

~~~
webjprgm
This is also what I thought. I was disappointed to see no TNG references on
the page.

~~~
breuleux
I like Earl Grey tea, but I don't watch Star Trek, so it didn't even occur to
me. Sorry about that :(

On the other hand I have to admit I like the idea of calling utilities Picard
or Engage, they have a nice ring to them. Hmm.

~~~
baldfat
If you do add those references the people will love you!

------
petegrif
This language has it down to a tea.

~~~
karmakaze
Hope it fares better than Ceylon.

------
hderms
This is just extremely exciting. I love the language design and it looks
usable as all hell. First compile-to-js language I've ever seen that got me
excited, let alone the first one that i'd actually use outside of the browser.
Congrats.

------
danneu
Great README.

Gives me a good sip of the entirety: the syntax, macros, patmatching,
integrating with React, and even how to gulp it and write tests with it. Yet
succinct enough to scroll in one swipe.

------
Grue3
Looks like another Coffeescript. Braces/parens are not bad, they structure the
code and make it easier for the eyes. Lack of punctuation is as bad as too
much punctuation.

------
M8
What level of automated refactoring and IDE integration does it offer?

~~~
myhf
The maximum possible level: a self-hosting compiler.

------
moomin
Now add an absolutely vital library called Milk and watch tea lovers
everywhere shudder.

~~~
spacemanmatt
Made correctly, earl grey (really any black tea) needs some milk fat to
neutralize the tannic acid or it could turn your stomach.

~~~
CocaKoala
I had actually noticed that I didn't feel great after drinking earl grey
without milk, but never realized why. Thanks for mentioning this!

~~~
spacemanmatt
True story: One day I was out of milk, but figured it wouldn't be too bad to
go without and have my tea anyway. Dropped the kids off at school, lost my
stomach in the parking lot. 8:00am, lookin' classy at the private school.

------
trafnar
"Oh god, do we need another language that compiles to javascript?!"

—Everyone, probably

~~~
bbrennan
JS is the new JVM. Write once, run anywhere is still the dream, I'm glad new
programming languages are taking advantage of JavaScript's versatility.

~~~
toyg
_> Write once, run anywhere is still the dream_

More like "write once, run in the browser". I don't think most compile-to-js
languages care too much about "anywhere", they are just trying to get nicer
alternatives in what is basically a platform (the browser) closed to anything
except JS.

~~~
woah
JavaScript will run anywhere

~~~
saraid216
Javascript will run anywhere you have something to run it on, same as Java, or
any other language.

------
childintime
is it just me, tiring quickly of this syntax?

~~~
webjprgm
I'm not a fan of using -> like CoffeeScript does. It doesn't seem to mean
function-body / algorithm-to-do-the-thing to me. That operator makes sense for
pointers or for function return value type expressions.

~~~
breuleux
I think that's just because you are used to see it used that way. And it's not
like CoffeeScript invented this.

Haskell does it:

    
    
        \x -> x + 1
    

OCaml does it:

    
    
        fun (x : int) -> x + 1
    

It is very common in functional languages to use -> both for function bodies
and return types.

~~~
webjprgm
I suppose. Kinda like => for "maps to" in some math / theory classes.

