Nomsu Overview
In the style of Learn X in Y Minutes, this overview is entirely written in Nomsu code. If you want to learn Nomsu interactively, install Nomsu and run:
nomsu -t tutorial
This page just provides a quick reference for common usage patterns.
/usr/bin/env nomsu -V7.0.0
#!### How do I...
### Write a comment? Put a ### and go till the end of the line
### How do I import a libarary?
"consolecolor"
use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### How do I print stuff?
"Hello world!"
say
### How do I set a variable?
### Variables have "$" prefix:
$foobar = 1
$text = "Hello world"
### Expressions that are more than just literal values require parentheses:
$foobar = (2 + 3)
$one_two = 12
$one_two
say
### How do I modify a variable?
$foobar = ($foobar + 1)
### Or, as a shorthand, you can do this to increment a variable:
$foobar += 1
### How do I define a multi-line string?
### In Nomsu, the name "text" is used, rather than "string", and multi-line text looks like:
$multi_text = ("
Start with a quotation mark, then put indented lines below it. The indented
lines will not include the indentation, except when the lines are indented
more than 4 spaces relative to the original quote mark.
<- E.g. the 2 spaces here will be included as part of the text.
But this line will have no leading spaces.
The text will continue until a closing quotation at the end of the text's
indentation level.
")
### How do I put values inside text? (AKA string formatting, string interpolation)
("
say Text can contain a backslash followed by a variable, list, dict, or parenthesized
expression. This escaped value will be converted to readable text, like so:
The value of $foobar is \$foobar, isn't that nice?
These are some numbers: \[1, 2, 3]
The sum of 2 and 4 is \(2 + 4).
A backslash not followed by any of these, and not at the end of a line
like this: \\ will just be treated as a backslash.
Or, two backlashes will be treated as a single backslash, no matter what follows,
like this: \\$foobar <- won't insert any values
If you need to split a long line without inserting a newline, you can end a line with backslash \
..and start the next line with two periods, like that.
Similarly, you can put a long interpolated indented value like: \(
1000 + 2000 + 3000 + 4000 + 5000 + 6000 + 7000 + 8000 + 9000
between a backslash and two periods.
)")
"Single-line text can contain escape sequences like \", \\, \000, and \n"
say
### How do I define a list?
$my_list = ["first", "second", "third", 4]
### Really long lists can use [..] followed by a bunch of indented values delimited
### by commas and/or newlines
$my_really_long_list = [
10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000
120000, 130000, 140000, 150000, 160000, 170000
]
### How do I use a list?
### Lists are 1-indexed because they're implemented as Lua tables, so this prints "first"
$my_list.1
say
### List entries can be modified like this:
$my_list.1 = "ONE!!!"
### Or appended to/removed from:
$my_list, add "extra item"
$my_list, pop
### How do I define a dictionary/hash map?
### One-word text keys don't need quotes, otherwise the key is an expression.
### If the expression is more complex than a literal, it needs parentheses:
$my_dict = {.x = 101, .y = 2, ."my value" = 99, .653 = 292, .(5 + 6) = 11}
### How do I use a dict?
### Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists
$my_dict.x
say $my_dict."how many bottles"
say $my_dict.653
say $my_dict.x = 9999
### How do I do conditional branching?
1 < 10):
if ("1 is indeed < 10"
say
1 > 10):
if ("this won't print"
say ..else:
"this will print"
say
### There's no "elseif", so for longer conditionals, a "when" branch is the best option
when:3 > 3):
("this won't print"
say
3 > 6) (3 > 5) (3 > 4):
("this won't print because none of the conditions on the line above are true"
say
3 > 2):
("this will print"
say
else:"this is the default case"
say
### How do I do a switch statement?
1 + 2) is:
if (0 1:
"this won't print"
say
2 3:
"this will print"
say
else:"this won't print"
say
### How do I loop over a list (a foreach loop)?
$list = [1, 2, 3]
$x in $list:
for "For $x loop #\$x"
say
### How do I loop over a number range?
### This is inclusive, so it will loop over 1,2, and 3
$i in (1 to 3):
for "For $i in 1 to 3 loop #\$i"
say
### This will print 0,2, and 4
$even in (0 to 5 by 2):
for "Even #\$even"
say
$backwards in (3 to 1 by -1):
for "Backwards #\$backwards"
say
### How do I do a 'while' loop?
$x = 1
$x <= 3):
repeat while ("repeat while loop #\$x"
say $x += 1
$x = 1
$x > 3):
repeat until ("repeat until loop #\$x"
say $x += 1
### How do I do an infinite loop?
$x = 1
repeat:"repeat loop #\$x"
say $x += 1
$x > 3): stop
if (
### How do I do a 'goto'?
do:$x = 1
--- (my loop) ---
"GOTO loop #\$x"
say $x += 1
$x <= 3):
if (
go to (my loop)"finished going to"
say
### How do I define a function/method/procedure?
### In nomsu, they're called "action"s, and they can be declared like this:
$first and also $second) means:
(say both $first
say $second
say
### Actions can have parts of the action's name spread throughout.
### Everything that's not a literal value is treated as part of the action's name
"Hello" and also "world!"
say both
### Actions can use "return" to return a value early
$n) means:
(first fibonacci above $f1 = 0
$f2 = 1
repeat:$tmp = ($f1 + $f2)
$f1 = $f2
$f2 = $tmp
$f2 > $n):
if ($f2
return
10)
say (first fibonacci above
### Actions can have aliases, which may or may not have the arguments in different order
[$worse_things more than $better_things
I hate $worse_things are worse than $better_things
I think $better_things more than $worse_things
I like
] all mean:"\($better_things, capitalized) rule and \$worse_things drool!"
say "dogs" more than "cats"
I like "chihuahuas" are worse than "corgis"
I think
### Actions can even start with a parameter
$what_she_said is what she said) means:
($what_she_said
say "-- she said"
say "Howdy pardner" is what she said
### The language only reserves []{}().,:;$\ as special characters, so actions
### and variables can use symbols freely:
>> $(∐) @&' -->< $ @&_~-^ ⊗⊞√ $1 !) means:
($(∐)
say $
say $1
say
>> "wow" @&' -->< "so flexible!" @&_~-^ ⊗⊞√
.."even numbers can be variables!" !
### You can also use unicode in variable and action names:
$こんにちは = "こんにちは"
$ と言う) means "\($)世界"
($こんにちは と言う)
say (
### Math and logic operations are just treated the same as actions in the syntax
2 + 3)
say (
### So you can define your own operators, although they will need to be parenthesized to
### play nicely with other operators
$a ++ $b) means (2 * ($a + $b))
(1 ++ (2 * 3))
say (
### How do I do grouping?
### Expressions can be grouped by enclosing parentheses:
2 + 3)
say (
### Or by (..) followed by an indented region
2 + 3)
say (
### If you need to keep going after an indented region, you can start the next line with ".."
"Very very very very long first argument that needs its own line"
say both ..and also "short second arg"
21 + 2)
(my favorite number) means (
### This can be nested:
"foo"
say both (my favorite number) and also
### Object-oriented programming:
### How do I define a class?
$x, $y]:
(a Vec) is (a thing) with [$self, +$other) means (Vec ($x + $other.x) ($y + $other.y))
($self, length) means (sqrt ($x * $x + $y * $y))
($(a Vec).is_a_vec = (yes)
$x $y) means (a Vec {.x = $x, .y = $y})
(Vec $v1 = (Vec 1 2)
$v1 + $v1) == (Vec 2 4)
assume ($v1
say
### Macros:
### The "lua>" and "=lua" macros can be used to write raw lua code:
(say the time) means:> "io.write(\"The OS time is: \", os.time(), \"\\n\");"
lua
say the time"Math expression result is: \(=lua "(1 + 2*3 + 3*4)^2 % 5")"
say
### Variables can be accessed via \$var
$n) means (=lua "math.sqrt(\$n)")
(square root of "The square root of 2 is \(square root of 2)"
say
### Macros can be defined to transform one bit of nomsu code into another using "parse $ as $":
$condition is untrue $body) parses as (if (not $condition) $body)
(if
### Or to transform nomsu code into custom lua code using "compile $ to $"
$body) compiles to:
(debug only $DEBUG_ENABLED:
if
return("
Lua -- Debug code:
\($body as lua)
")
..else:
"-- (debug code removed for production)")
return (Lua
$DEBUG_ENABLED = (yes)
### Constants can be defined as macros
20
(TWENTY) parses as
### When they're invoked, they'll need parentheses just like a function call
21
(TWENTY ONE) parses as
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### If you need to use compile-time actions in the same file that they're defined in, you
### can add a line of tildes (3 or more), and the file will be split into chunks, and each
### chunk will run before the next one compiles. (note that each chunk has its own scope)
1 > (TWENTY)) is untrue:
if ("Nomsu parsing macros work!"
say "It looks like a keyword, but there's no magic here!"
say
debug only:"Lua compiling macros work!"
say
### How do I use an action as a value?
### Well... it's always *possible* to fall back to Lua behavior for something like this:
$items according to $key_fn) means:
(best of $best, $best_key] = [nil, nil]
[$item in $items:
for $key = ($key_fn $item)
$best == (nil)) or ($key > $best_key)):
if (($best, $best_key] = [$item, $key]
[
$best
return
### Function literals look like: $x -> ($x * $x)
2, -3, 4, -8] according to ($x -> ($x * $x)))
say (best of [
### Or, you can surround an action with $(...) to refer to it:
$x squared) means ($x * $x)
(2, -3, 4, -8] according to $($ squared))
say (best of [
### However, nomsu was designed with flexible alternatives that are often better
### than passing functions. For example, instead of calling a key function on
### every item, you could instead define a macro that will inline an expression
### to produce faster code:
$items where $item has score $key_expr) parses as
(best of
result of:$best, $best_key] = [nil, nil]
[$item in $items:
for $key = $key_expr
$best == (nil)) or ($key > $best_key)):
if (($best, $best_key] = [$item, $key]
[
$best
return
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2, -3, 4, -8] where $x has score ($x * $x))
say (best of [
### The line above expands to:
say
result of:$best, $best_key] = [nil, nil]
[$x in [2, -3, 4, -8]:
for $key = ($x * $x)
$best == (nil)) or ($key > $best_key)):
if (($best, $best_key] = [$x, $key]
[
$best return