A pixel art image of a mushroom

Nova

Nova is a programming language invented by (wryl).

You can see an exchange talking about this starting here.

It’s a very interesting language where you build facts, a bit like Prolog or a Knowledge Graph. Then you pattern match on those facts in order to advance the computation.

Under the language you have an unordered set of n-tuples, then you pattern match on those in order to advance the computation.

For example, let’s say you want to have a program that maintains a counter, you start with something like this:

Increment was clicked,
The counter is at $count:
  $new_count = $count + 1,
  The counter is at $new_count.

Decrement was clicked,
The counter is at $count:
  $new_count = $count - 1,
  The counter is at $new_count.

The counter is at 0.

I don’t have access to the implementation or any programs beyond some examples, so the following is pure speculation.

Underlying computation mechanism

The statements on the above language serve two different functions:

Increment was clicked,
The counter is at $count:
  $new_count = $count + 1,
  The counter is at $new_count.

This specifies that if at any time, the tuple (Increment, was, clicked) exists in the tuple database, and the tuple (The, counter, is, at, _) exists, then consume them and replace them with (The, counter, is, at, _) with a new value.

If a token that starts with $ is found in the precondition then that name becomes a variable that takes the value found in the tuple.

For example, if the tuple database contained

(Increment, was, clicked)
(The, counter, is, at, 4)

Then running that computation is something like:

delete (Increment, was, clicked)
delete (The, counter, is, at, _)
$count = 4
$new_count = 5 ($count + 1)
insert (The, counter, is, at, 5)

Given two operations delete and insert that operate on the tuple database.

This is very interesting and is a new way of specifying a computation for me. I want to explore this further. This could relate very well with the exploratory programming concept. It would offer very good introspection and iteration, which are fundamental for that.

Internal representation

Since tuples are always parsed left to right until end of line (I think). Probably the fastest easiest representation is to just have a tree of tuple values.

Since you know what tuples have been added it should be easy to check which rules may be affected by them and match on those.

Program as a database

At each point in time the program is a tuple database that can be queried. The tuple database is evolved atomically on each match.

Questions and Doubts

  • Is the order of matches specified? (Top to bottom of file?), since two rules may match at the same time and be contradicting.
  • What happens when the same rule is matched by several tuples? Is the rule applied for all of them?
  • What kind of tooling would work for debugging this?
    • A time traveller debugger should be very simple to implement.
  • Abstracting
    • Was wondering about a way to specify what incrementing a value is. So for example you say: Increment %val: %val = %val + 1, I’m using % to target the value itself (does this even make sense?). Then for the example above you could do Increment is clicked, The counter is at $count: Increment $count. This would leave the tuple intact and just modify the value. Without having to re-implement what incrementing is for everything that can be incremented in the program.
  • Is there a need/space for metaprogramming?

(wryl) in the thread says

If I wanted to store an array, for example, I can store it in the form..

arrayname@array-name @ index = $value

So..

foo @ 1 = 10,

foo @ 2 = 20,

foo @ 3 = 30.

I can now ask questions, via patterns, such as “what arrays contain the value 20, and at what indices?“.

I’m not sure how that would work? I guess the environment he has created allows for queries that do not modify the environment. Leveraging the same pattern matching as the match defintions but one that returns multiple values.

Something like this:

$table @ $idx = 20

Found 3 matches
($table=foo, $idx=2)
($table=bar, $idx=34)
($table=baz, $idx=1)