Differences to Lua

Since np is based off the Lua runtime, there are more than a couple of similarities. Despite the syntactical differences, np is clearly a Lua dialect. However, there are some significant differences:

Optional Semicolons and Commas

Statements in np do not need to be separated by semicolons. Commas are also optional in function parameter lists, as well as list literals. However, commas are still needed to return and receive multiple parameters.

Deleted Stuff

np does not support the goto statement or code labels. String literals can have line breaks in them. Language keywords are allowed when using the dot notation to address list keys (like = 1). The unary object length operator has been removed, as has the repeat...until statement.

Metatables and Metamethods

The entirety of an object's behavior is stored in its metatable - which I have renamed to "event lists" to make the distinction clearer. In conjunction with that, the self operator : is used in np to invoke functions from the event list, operating on the data object. The types number, string, and list are automatically instantiated with the corresponding library functions as their event list, so for instance myList:copy() will invoke the copy() function from the list library to work on the myList object. Lua-style system metamethods, such as for example __index, have been renamed to omit the leading underscores and be generally more legible.

Standard Libraries

The standard Lua libraries have been extended with a lot of additional functionality.

Mutable Operations

np sports compound assignments like a+=1. To better support that functionality, many library functions now also support both mutable and immutable operations.

Loading Modules

With the __file__ and the __dir__ keywords, source code files are now aware of their own filename and path, and can use this to make better decisions about loading other code from the filesystem.

Local by Default

All variables are local and have to be declared before use with the new keyword which replaces Lua's local statement. The current module's root context can be accessed and modified by addressing the root container object only.


There is only one syntax for declaring functions now: new f = { a | => a*2 }. This means function declarations are essentially normal variable assignments using function literals. To help with recursion, the this keyword was intrduced, which always refers to the current function.


Lua-style iterators are deprecated and may be removed in the future. In their place, people should use the functional iterator pattern as exemplified in the new standard libraries. The np iterator pattern is simpler to code and easier to read, and it requires no syntactical sugar. For an example, refer to the items() iterator function of the list library.

Block Statements

In Lua, you often have to use block statements such as do..end or then..end even if the block contains only a single statement. In np, code blocks are optional in these cases.

Safe nils

The nil type in Lua signifies a value that does not exist. However, Lua programs tend to error out dramatically whenever program authors forget to check for nil and attempt to use those values. The resulting statements are often clunky and verbose.

In np, you may invoke any event function on a nil object, which then returns another nil object. This allows you to chain event calls together without having to check for nil in between, for example: myList:filter():doSomething():endThenDoThis().

You can also omit nil checks when addressing member fields of list with the dot and bracket notations: will return nil if any of the constituent parts are nil.