
Lily Programming Language - alg0rith
https://github.com/jesserayadkins/lily
======
chriswarbo
Looks very nice! The templating and server support makes Lily look like a nice
"next step" for PHP developers/shops/projects. PHP's "installed everywhere"
feature is pretty hard to beat, especially for host-it-yourself projects like
Wordpress. I could see such a language catching on for custom, in-house
development though; for example to implement microservices.

It's nice to see that there's a trend for such small, (relatively) simple
languages to include nice features like first-class functions, convenient
lambda notation, sum types, type inference, etc. A few years ago it seemed
most new languages were just nitpicking over syntax, without bringing much to
the table. I'm glad to see we're leaving the local minimum of "class-based OO
with slight different static method mechanism"!

------
alkonaut
Love it. It's like someone used C# a lot and got fed up with how much cermony
goes into making a simple sum type and exhaustive handling of the variants.

A pet peeve of mine is the sloppyness by which .NET allocates things like
iterators etc. I'd very much like to see zero-cost abstractions in a new
language, so that there is no surprise differences between various ways of
iterating over collections. I read it only quickly but couldn't find anything
related to how enumeration/iteration works under the hood.

~~~
jesserayadkins2
Actually, no, I've never used C# except for a few minutes and only one time. I
have more experience with the syntax of Scala and Rust. Between the two, I
found Rust's more appealing. I like that enums serve a single purpose and
can't be inherited.

Currently, the best you can get for iteration of Lists and Hashes is to do
each-ing the way you'd go about it in Ruby, except that the language currently
lacks iterators.

That's not to say I don't want iterators. But I've spent a huge amount of time
of this release in making sure that all of the built-in classes get dynaloaded
so that memory usage stays low. Now that everything's getting dynaloaded
properly, I've less of a problem with doing iterators.

~~~
stevedonovan
Very cool - haven't come across a fun new language for a while. When thinking
about iterators, think about coroutines a la Lua. Otherwise you're going to
get yield-with-serious-restrictions.

~~~
DanWaterworth
When I was adding for each style loops to my language, plastic [1], I just
opted for 'you can iterate over any expression that produces a coroutine'. It
shouldn't cause any problems a tracing jit can't fix and it's super
convenient.

[1]
[https://github.com/DanielWaterworth/plastic](https://github.com/DanielWaterworth/plastic)

------
a_c
Hello jesse, it is one hell of an inspiring work!

I read from your blog that you are self-taught programmer. Would you mind
sharing something about yourself? In particular, I'm interested in area like
what do you do for your day job? Is it programming related? What resources did
you come across that you find particularly useful in making lily? Anything
would be appreciated!

~~~
jesserayadkins2
Thank you!

As for me, I'm not so sure what to share. I'm not all that exciting. Most of
the time I have I spend on Lily. Once in a while I take a break. But I don't
get out that often. Lily's nice in that it's a place for me to do something
and feel like I make a difference.

My day job? For most of the time that I worked on Lily, I was working part-
time at [redacted] as a Maintenance Assistant. My favorite memory was talking
shop with a guy there who had some computer knowledge. He asked what I had
done and I told him that I had just written a garbage collector and that it
was so awesome because it took just a week and it went well.

He answered me saying something to the effect of "Well of course you wrote a
good garbage collector, you're Maintenance! That's what you do!" We both had a
good laugh at it.

I've never had a job doing software development. I recently left [redacted] to
pursue a job in software, but haven't had much luck with it. I'm still holding
out hope though.

So, no, my job isn't programming related.

Resources? My strategy is that when I get up to something new, I do all of the
research that I can both in the topic itself, as well as how other languages
do it. One example would be Exceptions. I didn't know how to do that, so I
started researching how Python did it, how Java did them, Ruby, etc. I started
thinking of what I wanted, and also what the goal of having them in my
language was. I also made sure to search through Haskell, Scala, Rust, and
OCaml since they don't use exceptions as much. The point being that I wanted
to know what languages do when they tend to not use exceptions.

Rather than starting off as "This is a good idea", I instead approach it as,
"I think I would like X. How does that typically get done?"

For resources, the most helpful thing I've read has been ESR's guide on struct
packing:

[http://www.catb.org/esr/structure-
packing/](http://www.catb.org/esr/structure-packing/)

I'm afraid not much else comes to mind though.

~~~
a_c
Thank you for getting back!

Coding itself is fun, yet it is always interesting to know the guy behind
software. It is a tough road in making a new language and you have invested 5
years on it! That determination is something I hope could achieve :)

------
ebbv
I like some of the things they're doing here but I have a big problem with the
language design choice of having multiple valid syntax doing the same thing
(e.g. declaring a new class as Cat('Spike'), Cat.new('Spike') or 'Spike' |>
Cat.)

I tend to subscribe to the philosophy that language designers should be as
strict as possible; choose the "best" syntax for doing something and only
allow that unless there's really compelling reasons for alternatives.

~~~
adrianratnapala
As stevedonovan says, the 'Spike' |> Cat is probably contrived. The feature
probably exists for the sake of things like

    
    
       cats.map{|c| c.name} |> print
    

Which is more readable to me than

    
    
       print(cats.map{|c| c.name})
    

It's a little jaring that it has both Cat(arg) and Cat.new(arg) syntax. But I
wouldn't want to judge that without learning about the semantics that it
emerges out of.

~~~
jesserayadkins2
They're the same thing. The first (Cat(arg)) is the same thing as the second
(Cat.new(arg)). The reason for the distinction is...umm...I'm still not sure
if I want to eventually include classes as values the way that other things
are values.

If you're grabbing the constructor as a function, for example, then it's a bit
more sensible to use Cat instead of Cat.new. I don't know...it seemed at the
time neat to allow a shorthand way of constructing something, but it's kinda
wonky.

~~~
taftster
Hey, I just wanted to shout out and say that your reply here is refreshing. I
appreciate that you admit that the feature is "kinda wonky" and that you're
still looking at and intellectually rationalizing about such things. There's
no harm in trying out the various constructor approaches, and then see how it
feels in the real world.

This is refreshing from other newish ( _cough_ golang) languages which pick
the "wonky" path, but go on to defend it tirelessly. Keep up the good work.

------
mhd
The language itself might be quite different, but a few of the design
parameters remind me of Wren[1], another language that's on my "try to embed
it somewhere" list...

[1]: [https://github.com/munificent/wren](https://github.com/munificent/wren)

------
Profan
I wish we had more actually decent statically typed interpreted languages
(ones that are easily embeddable, to be precise), this looks very interesting.

And no, AngelScript REALLY does not count as anything interesting. (unless you
really really like C++)

~~~
groovy2shoes
I started working on an embeddable, byte-compiled dialect of Standard ML after
coming to the realization that Lua with types (as I conceive of it) is
_extremely_ similar to ML, but I've had to put it on the backburner for now.
But, I agree: a typed language that can be used as an embeddable
extension/scripting language would be cool.

------
idank
This is an impressive volume of work, especially for one person. How do you
stay motivated?

~~~
jesserayadkins2
First of all, thank you! As for what motivates me, it's a few different
things:

* The challenge of it. Lily's one of the few things that I've done where I feel really challenged, and where I can actually make a true difference in it. It gives me something to do, something that I can always be refining and thinking about.

* I -strongly- believe there is a market for this. I want to see this used in game development, used in server development, and used standalone. It's really, really fast scripting language with static typing that brings a unique blend of features that allow for terse code. I want to eventually port this to Arduino, just to say that I did it (Lily boots in 6K with 64-bit pointers, so I think it's possible).

* It's something that I can put at the top of my resume.

* I balance what I do. You might see me spend a week doing plumbing work in lexer, and the next I jump around and patch different places in emitter. I try to not stick in any one area too long. If I do a feature that's difficult and takes a long time, I balance that out with what I term "candy". Candy, in this case, being something that's more immediately visible. I added the constructor shorthand syntax shortly after doing type erasure. Type erasure took a month, and I was a little burned after that. So I balanced it out with a feature that was easier, and had a more visible effect on the language.

* Once a week, I'll go over what I've done, and sort of pat myself on the back, and also think of "Alright, X is done..." and it always goes to "So what's next week?" There's never been a "I'm done". Honestly? The first two years were the hardest, because I didn't have a product that I cared much for. These last three have been easier, because I'm excited about what I'm doing, and there's a more broad spectrum of what I can do.

* You all. No, seriously, I'm finding myself more often talking to different communities about what I've done. I talked to 4chan's /g/ last night. Sometimes I talk to different boards on Reddit, sometimes I try to talk here. I tried Slashdot once, but they didn't bother to even approve the article. Some people give crummy comments, but seeing the new stars, seeing people say they're willing to try the language, that means a lot to me. I really enjoy engaging people when it's over text about what I've done, since I'm comfortable when talking over text and I don't get RL opportunities to talk about what I do hardly ever since I don't know anyone personally RL who does coding for a living, and I'm a pretty stay-to-myself person.

~~~
goldenkey
Shoot me an email (its in my profile.)

~~~
jesserayadkins2
I can't seem to find it. Am I missing something?

~~~
goldenkey
My bad I thought the email field shows publicly. Try viewing again. Should be
there now.

------
rufusroflpunch
I really dig the syntax of this language, I must say. Great job. I'm
interested in the embeddability of this language. There doesn't seem to be any
documentation on the API features, short of looking through the source code. I
would be greatly interested in this. Specifically, how to add calls that the
Lily code can call, or how to call Lily code from within the interpreter.

~~~
jesserayadkins2
This is a big problem in the language now. There's no solid apis for working
with the frontend (invoking the parser and getting a result). The backend apis
are acceptable, except that it's difficult to move values around.

I'm a couple of weeks away from the end of a three month release window, so
I've (for the moment) given up on trying to finish the apis. But I'm not far
from having them done. A month, maybe?

But after that, I'll write a guide on how to embed Lily, and how to extend it.

For the moment, your best bet if you're creating a standalone package like
postgres is to refer to how postgres structures the dynaload table. If you're
looking to embed the interpreter, it's awkward and hard.

Once this release cycle ends (July 10, Lily's true 5 year anniversary), it's
the first thing on my list. I want to give people a solid api so that other
people can start building stuff and not have to worry about me breaking it.

First the api, then the tooling, then documentation. You've got my word on
that (and HN won't let me delete this, on top of that).

------
percept
Is Lily a cat?

Anyway, somebody hire this guy. I'm sure someone that can do this is qualified
to make web CRUD for lots of money (should he so desire).

~~~
jesserayadkins2
No, I'm just terrible at making up examples so cats! Cats everywhere!

------
akavel
• Have you considered allowing returning multiple values, like in Lua and Go,
and also returning errors through them? esp. instead of exceptions? (Though I
suspect this could be problematic to match with the sweet |> pipe operator)

• Have you considered supporting Lisp/Scheme-like or Rust-like macros? or
Rebol-like DSLs? (though I suppose the latter are probably strongly tied to
Rebol's minimalistic syntax)

~~~
jesserayadkins2
Multiple return values I'm not very interested in. Lily has first-class
tuples, and you can return a tuple which I might later add in desugaring for.
But multiple return values themselves cause a lot of problems with the
internals being pretty set on 0 or 1 return.

Macros are a hard no. DSLs, maybe. For the latter, I could see allowing a
pluggable import handler through Lily's options. But I'm reluctant to commit
to a yes or no on that at the moment, since I'd rather get over the hump of
api not being fully fleshed out.

~~~
technomancy
Really glad to hear that about multiple return values. In my mind multiple
return values are a solution for the problem of "oh, we haven't invented
pattern matching yet", and matching against tuples is soooo much cleaner and
more consistent.

------
rmsaksida
I love that there's a focus on low memory usage.

~~~
jesserayadkins2
I owe ESR a lot for writing about struct packing, because that's a large part
of how Lily uses so little memory:

[http://www.catb.org/esr/structure-
packing/](http://www.catb.org/esr/structure-packing/)

------
wired_devil
I don't like this syntax: "if: {". Using ":" for a one line statement is ok,
but in most cases you have to use multiple lines and end up with two
identifiers that represent the same thing. Maybe you can make the "{" for
multiple lines and ":" for one line. I like to have an indentifier for one
line statements, unlike the C approach.

~~~
childintime
I don't like the colon too. Not in Python, not in Nim. It seems jarring to me,
something someone fearful of programming might want!

Also, as Larry Wall said: everybody wants the colon, so it is an extremely
useful symbol elsewhere! A shame to waste it.

That being said, this is by a long shot the most tasteful little language seen
in a long time.

------
0x54MUR41
Earlier submission:
[https://news.ycombinator.com/item?id=11934295](https://news.ycombinator.com/item?id=11934295)

------
PeCaN
I registered #lily on Freenode if you want it.

Impressive work! I think this is the first relatively conventional language
that I've gotten really excited about in a while. It's a really nice blend of
features and a quality implementation. Definitely going to use it next time I
embed a language.

------
S4M
Does it support operator overloading? I tried it quickly (`define
+(...){...}`) but it didn't work. Maybe there is a notation for it but I
couldn't find it in the tutorial.

~~~
jesserayadkins2
There's no operator overloading. I'm pretty reluctant to add it too, because
I've seen it be abused far, far too many times. It has uses, yes, but I'm not
very interested in it at the moment.

I won't say absolutely no to it, but if it were to be added, it wouldn't be
right now. There's too much api that needs doing right now.

~~~
hawski
I always dreamed of language without operator overloading, but with builtin
vectors and matrices. Maybe they could be easily mapped to SIMD instructions.
They can have a bit different operator (like in one PEP [1]).

I know that there are intrinsics for C, but they are non portable. Maybe
except NaCl [2].

Also is concatenation of strings only done through usage of $"^(variable)"
syntax?

[1]
[https://www.python.org/dev/peps/pep-0465/](https://www.python.org/dev/peps/pep-0465/)

[2] [https://developer.chrome.com/native-
client/reference/pnacl-c...](https://developer.chrome.com/native-
client/reference/pnacl-c-cpp-language-support#portable-simd-vectors)

~~~
jesserayadkins2
It's probably possible, especially with today's compilers being smarter about
using those instructions. You're right, in that concat is currently only
available through interpolation.

At the moment, I'm not interested in adding vectors or SIMD. It's something I
might try further down the line, but not now.

------
codezero
This looks pretty cool.

When ever I discover a new language, I try to find out why it was created.

Why did you make Lily? Are you aiming to solve any specific problems, or is it
a fun project you wanted to do?

~~~
jesserayadkins2
Thanks!

I started Lily to be an alternative to PHP. The first commit was adding
templating support, and it was a while before the language could be
standalone.

I had two requirements when creating and designing Lily:

One, that the language had to be interpreted. I didn't want to offer people an
alternative to PHP but then tell them that they would need to repeatedly run
compile passes over it. Facebook has HipHop, and it transforms PHP into C++. I
wanted a language that could be used like PHP, but having a faster interpreter
wasn't enough.

The other requirement was to have a statically-typed language. I believed that
a statically-typed language would lend itself to better transformation into a
lower-level language. In theory, an llvm frontend might also be writable that
took Lily as input.

I wanted Lily to outperform PHP both when interpreted, and when compiled. Over
time, the focus broadened once I realized Lily's low memory usage, and how
fast the turnaround of the parser is.

~~~
codezero
Awesome, thanks for sharing this!

------
malcium
Why did you name it Lily? That's my daughter's name so I'm genuinely curious.

~~~
jesserayadkins2
I couldn't think of a good name. I had ideas of something like Meteor or
Hurricane or Tornado. The first was taken, and I -very- quickly had second
thoughts about the other two.

My mom, from time to time, mentioned that she really liked the name Lily.
After giving it a lot of thought, I said, "You know, why not go with that?"

I've grown to like it.

~~~
feiss
I think it's a great choice, it's catchy, short, simple and kind. A perfect
fit for a programming language, I love it.

------
arranf
What can I go out and immediately build in Lily as a "useful" hello world
program?

~~~
jesserayadkins2
That's a good question, and unfortunately one that I'm at a loss as to how to
answer right now. I've been focused more on building it, and less on using it.
However, I've been looking to change that lately now that the core is becoming
more stable and usable.

~~~
arranf
Awesome I would _love_ to get to grips with this and start building.

------
spriggan3
What about polymorphism ?

How does one deal with low coupling? For instance, in PHP I would have used
interfaces to decouple collaborators.

~~~
jesserayadkins2
No traits yet. A few other things need to be done first. Generics need to be
name-able, System F, and core api is a more pressing need right now.

My plan is to tackle traits in a few months, so long as everything goes well.
But I want the above stuff done first, so that when I do traits I can start
thinking about higher kinded types, trait inference, and the like.

------
hyperpape
Is the speed of startup entirely based on the dynaloading, or are there other
choices that make it faster than Lua?

------
malcium
Why did you name it Lily?

~~~
feiss
Already answered :)
[https://news.ycombinator.com/item?id=12017668](https://news.ycombinator.com/item?id=12017668)

------
tomp

        print($"My name is ^(@name).")
    

I don't understand why anyone would still require special notation for
interpolated strings, when we have the awesome and unambiguous string
interpolation syntax introduced by Swift (granted, this project was started in
2011, before Swift).

> Reference counting has the benefit of giving consistent, and more easily
> measured performance. There's no fear of the garbage collector suddenly
> leaping into action right at the worst time, or having to tune the collector
> to minimize pauses.

LoL. Refcounting can lead to just as long pauses as GC, if your reference is
the last reference to a huge object graph.

~~~
berdario
Swift string interpolation syntax is not more awesome or any less ambiguous
than other syntaxes used in other languages

In fact, it's the first time that I've seen interpolation with round
parentheses, rather than curly braces (which are used in javascript with $
(es2015 template literals), python, bash with $, ruby with #, groovy with $,
etc... )

> LoL. Refcounting can lead to just as long pauses as GC

He didn't say more performant, he said _consistent_

~~~
vorg
> I don't understand why anyone would still require special notation for
> interpolated strings, when we have the awesome and unambiguous string
> interpolation syntax introduced by Swift

You're both wrong. String interpolation is just a very thin syntactic layer.
It's easy enough to write

    
    
      printf("Half of %f is: %f5.2", someVal, someVal * 0.5)
    

instead of

    
    
      print("Half of $someVal is: ${someVal * 0.5}")
    

and a lot easier for a programming language to parse, without needing to feed
the parser into the lexer. And you also get easy formatting of the decimal
(e.g. %f5.2), whereas string interpolation (in Swift, Apache Groovy, etc)
requires a separate call, e.g.

    
    
      print("Half of $someVal is: ${format(someVal * 0.5, "%f5.2")}")

~~~
drjeats
C#'s new interpolation syntax is a counterexample to your point about easy
formatting:

[https://msdn.microsoft.com/en-
us/library/dn961160.aspx#Ancho...](https://msdn.microsoft.com/en-
us/library/dn961160.aspx#Anchor_1)

    
    
        $"Name = {name}, hours = {hours:hh}"
        var s = $"hello, {name}"
        System.IFormattable s = $"Hello, {name}"
        System.FormattableString s = $"Hello, {name}"
        $"{person.Name, 20} is {person.Age:D3} year {(p.Age == 1 ? "" : "s")} old."

