Comments
by Jesse Ray Adkins
Interpreted language with a focus on expressiveness and type safety.

Lily is an interpreted language with low memory overhead, static typing, and type inference.

Safety through types

Every variable has to have a starting value. Every expression has a known type. Everything has a type, even if it's not explicitly stated. Lily's type system exists to aid the programmer, not get in the way.

To further this notion, Lily provides Option for values that may be None.

Type inference

Strong static typing goes hand-in-hand with good inference. Lily knows that [1, 2, 3] is a List[Integer].

Lily requires that functions explicitly specify their input and output types. But, aside from that, most explicit typing is optional.

Isolated

The interpreter does not write any global data. This allows multiple interpreters to exist at the same time without worrying about them colliding into each other.

Built-in templating

Lily can be run from a server and used as a templating language. When used as a templating language, code is between <?lily ... ?>, and everything else is text.

Code that is imported is expected to always be in code mode. No more importing something that accidentally sends headers. import is also namespaced, among many other things.

Low memory use

Most interpreted languages have to dynamically allocate a lot of memory just to get started. A few hundred KB, or even 2 MB isn't unheard of.

Allocating memory takes time. One way that Lily cuts down on memory (and startup time) is to not dynamically allocate memory for functions and (some) functions that you aren't going to use.

Lily can do this, because it's statically typed, and knows for sure what will and won't be used. This technique, termed dynaloading, allows Lily to print 'Hello world' in less than 10 KB of memory.

print("Hello from Lily!")

class Cat(name: String)
{
    # The body of a class is the constructor.
    # Properties start with @<name>
    var @name = name
    print($"My name is ^(@name).")
}

# Types can almost always be inferred. This is List[Cat].
var cats = [
    Cat("Muffin"),
    Cat.new("Fuzzy"),
    "Snowball" |> Cat]

# a |> b is the same as b(a)
cats.map{|c| c.name} |> print

# Option is either Some(A), or None.
var maybe_cat: Option[Cat] = None

match maybe_cat: {
    case Some(s): print("Cat.")
    case None:    print("None")
}
Information updated 01/02/17
View Comments