# The Luan language
Luan is a scripting language implemented in Java, built on Ousterhout's idea of pairing a scripting language with a system language: Luan for applications, Java for libraries. It started as a Lua clone and was then changed according to the principles in [principles.md](principles.md).
References in the luan repository: `website/src/diff.html.luan` ("How Luan differs from Lua"), `website/src/manual.html.luan` (the reference manual, which is unfinished and leaves out many library functions), and `website/src/tutorial.html.luan` (a short tutorial). The source in `src/luan/` is the final word, especially for the library.
## Differences from Lua
- Simpler, mostly by removing things: no globals unless `_ENV` is defined (so an undefined name is a compile error), and no coroutines, `goto`, numeric `for`, `pcall`/`xpcall`, `:` method calls, call metamethod, proper tail calls, bitwise operators, or string-to-number coercion. Only tables have metatables.
- Stricter: conditions in `if`, `while` and `repeat`, and the operand of `not`, must be booleans. Passing extra non-nil arguments to a function is an error. The end of a line ends a statement; a backslash at the end of a line continues it.
- Additions: `try`/`catch`/`finally`, `continue`, optional block terminators (`end_do`, `end_for`, `end_function`, `end_if`, `end_try`, `end_while`), `or`/`and` expressions as statements, template statements, backticks, and a binary type.
- `..` converts every operand to a string, so `"x="..nil` is `"x=nil"`.
- In a table constructor, the end of a line separates fields.
- `for` takes one expression, not a list: `for k, v in pairs(t) do`, `for i in range(1,10) do`.
- Errors are tables. `Luan.error(message)` throws one; in `catch e`, `e.message` is the message.
## Values
Values are Java objects. `nil` is Java `null`; booleans, numbers and strings are Java `Boolean`, `Number` and `String`; the binary type is `byte[]`. A number may be any Java `Number`, such as `Integer`, `Long` or `Double`, which matters when storing numbers in Lucene (see [dynamic-sites.md](dynamic-sites.md)). A `java` value is any other Java object.
Strings can't hold binary data; that's what the binary type is for.
`{nil}` is an empty list and `{}` an empty map. They behave the same except in `Parsers.json_string`, which writes `[]` for the first and `{}` for the second. Write `{nil}` for a table meant as a list, to show the intent.
## Statements that trip people up
- One statement per line. Two statements on one line need `;` between them; without it, `Io.print("a") Io.print("b")` is "Invalid input".
- Line ends: a statement split over lines needs `\` at the end of every line but the last. This includes a multi-line `or` chain:
```lua
return starts_with(referer,"http://"..host.."/") \
or starts_with(referer,"https://"..host.."/")
```
- Logical statements: `x==5 or error "x should be 5"` is a statement. The last operand must itself be a statement, a function call or another logical expression ending in one, so `x==5 or "msg"` doesn't compile. The compiler reports this misleadingly, as "'end' expected" at that line.
- Templates: `%>` starts literal text and `<%` ends it; `<%= expr %>` writes a value. The text goes to `Io.stdout`. A template can be any statement, so it can sit inside a loop or a function:
```lua
for _, post in ipairs(posts) do
%>
<h2><%= html_encode(post.subject) %></h2>
<%
end
```
- Backticks: `` `stats` `` runs the statements and returns everything they wrote to `Io.stdout`, including `Io.print`, as a string. Backticks aren't statements.
## Modules
- A chunk starts with only one local, `require`. Everything else is imported, at the top of the file:
```lua
local Luan = require "luan:Luan.luan"
local error = Luan.error
local ipairs = Luan.ipairs or error()
local String = require "luan:String.luan"
local starts_with = String.starts_with or error()
```
- `require` takes a URI: `luan:X.luan` (the standard library, `src/luan/modules/X.luan`), `site:/X` (the site's `src/` directory), `file:`, `classpath:` and others. `Package.load(uri)` is the same but returns `false` for a missing module instead of throwing.
- A module returns a table of functions, built up and returned at the end:
```lua
local Utils = {}
function Utils.check_referer()
...
end
return Utils
```
- Modules in a site's `lib/` that use each other require each other inside the functions that use them, not at the top of the file, so that adding a circular dependency later never forces a change:
```lua
function post.get_chat()
local Chat = require "site:/lib/Chat.luan"
return Chat.get_by_id(post.chat_id)
end
```
## Objects
There are no classes. An object is a table, and a constructor adds closures to it:
```lua
function Post.new(post)
function post.save()
...
end
function post.delete()
...
end
return post
end
```
Callers write `post.save()`, not `post:save()`.
## Threads
Luan has real threads instead of coroutines. Each interpreter (`src/luan/Luan.java`) lives in one thread, and an object becomes immutable as soon as two interpreters can reach it. So application code never synchronizes.
For values that must differ per thread, libraries keep per-interpreter values: `Luan.get_local_cloned`/`set_local_cloned` keep a value that is copied into interpreters cloned from this one, and `get_local_only`/`set_local_only` keep one that isn't (as for `Http.request` and `Http.response`). Prefer local cloned unless local only is clearly needed. Application code rarely needs either.
## Compilation
Luan compiles each chunk to Java source, then to class files, which it loads. That's why it needs a JDK, not just a JRE.
## Calling Java
Any Java method can be called from Luan with no glue code. This is how Luan's own library is built, and how a Luan application uses a Java library.
- `require "java"` turns on Java in the chunk, if the chunk has permission. Hosted sites don't have permission, so on hosting only the standard library uses Java on a site's behalf.
- `require "java:pkg.Class"` returns the class. Static methods, static fields and nested classes are its fields, and `.new(...)` calls a constructor.
- Methods of a Java object are bound to it, so they can be stored and called as plain functions: `local append = sb.append`.
- Arguments are converted to the parameter types. A boxed type like `Integer` accepts `nil`, which is how a Java method takes an optional argument. A first parameter `Luan luan` is supplied automatically.
- A Java array comes back as multiple return values.
- There is no getter or setter mapping: call `obj.getName()`.
- Java keywords get a trailing underscore: `StringLuan.char_` is exported as `String.char`.
- Overloaded methods are resolved at call time, but a library is clearer with one unambiguous Java method written for Luan to call.
### How the standard library is built
A module `src/luan/modules/X.luan` builds its table by assigning functions from a Java class, usually `XLuan.java` next to it: `String.find = StringLuan.find`. To find out what a function does, go from the `.luan` file to the Java method. Java objects are usually wrapped in tables that expose selected bound methods, plus a `java` field holding the object. Lists are returned as Luan tables.
## Fail fast
In a dynamic language, robustness comes from finding mistakes as close to their cause as possible. Use `or error()` freely:
- On every import: `local f = Module.f or error()`.
- On required values: `local id = Http.request.parameters.id or error()`.
- On lookups that must succeed: `local post = Post.get_by_id(id) or error "post not found"`.
- On conditions: `x > 0 or error "x must be positive"`.