Where your fantaZies come true Why create a new programming language?

If you want to know why Z is designed the way it is, go here. But if you want want to know why Z was built in the first place, keep reading. Transpile to JS is pretty popular these days. JS has become the de facto assembely of the web, because virtually no one codes in "Vanilla JS" these days. A plethora of languages (CoffeeScript, LiveScript, Elm, ClojureScript, TypeScript) have all emerged on the sole basis of compiling to JS. However, we can seperate the languages that transpile to JS into two categories: 1. Syntatic Sugar Languages that add new compile-time features to JavaScript, but no knew runtime features. These languages interop with JavaScript nearly seemlessly, but they fail to deliever certain features that require runtime additions, including operator overloading, pattern matching, better concatenation rules, etc. Examples: CoffeeScript

LiveScript

ESNext + Babel

TypeScript 2. JVM Languages (JavaScript Virtual Machine) These languages add new compile-time and run-time features to JS, and use JavaScript more like assembely code than a target language. While these languages can add any features they want, they often have limited and clunky interop with JS, and are all are limited to the frontend, whereas Syntatic Sugar languages can be used anywhere. Examples: Elm

Haxe

ClojureScript Z mixes these two sides of transpiled languages. It has it's own runtime, with custom operators, a standard library, goroutines, and other cool out-of-the-box features. However, it also can call any JavaScript method, uses the same APIs as JavaScript, and has a generally similar syntax, making it easy for JavaScript users to pick up. Z is also one of the only langauges that transpiles to JS, comes with a custom runtime, and functions on the backend!

So what are you waiting for? Are you ready to transform your backend experience with amazing features and a cool runtime and standard library? Jump in and learn some Z! Z mixes these two sides of transpiled languages. It has it's own runtime, with custom operators, a standard library, goroutines, and other cool out-of-the-box features. However, it also can call any JavaScript method, uses the same APIs as JavaScript, and has a generally similar syntax, making it easy for JavaScript users to pick up. Z is also one of the only langauges that transpiles to JS, comes with a custom runtime, and functions on the backend!So what are you waiting for? Are you ready to transform your backend experience with amazing features and a cool runtime and standard library? Jump in and learn some Z!

Getting Started To start, enter a terminal session. Every Z package on npm is namespaced under @zlanguage . Install the Z compiler as so: $ npm install -g @zlanguage/zcomp Now, in order for the compiler to function, you must also install globby : $ npm install -g globby Now, in order for the compiler to function, you must also install Or, with Yarn: $ yarn global add @zlanguage/zcomp globby That wasn't too hard! Now, to experiment with Z, let's launch a REPL. You can launch a Z REPL with: $ zcomp repl If all goes well, you should see the following: zrepl>

Basic Expressions and Math Let's start by creating a simple math expression: 3 + 2 The REPL will print back 5. Order of operations works: 3 + 2 * 7 The REPL gives you back 17, not 35. The following mathematical operators are supported at the following orders of precedence: ^ pow * / % + - Number Extensions Besides typical JavaScript number literals, Z supports the following extensions to them: A number can have: 1_000 Underscores

Underscores 0x100 Hexadecimal, Binary, and Octal prefixes!

Hexadecimal, Binary, and Octal prefixes! 10bytes Trailing characters

Trailing characters 1.somePropertyHere Trailing refinement

More Expressions To start, you may have noticed that inputting a raw number without any math is considered an error in the Z REPL. While this may seem peculiar, this is to avoid "useless expressions", like randomly putting a string or a number on some code. Single line Comments in Z are denoted with # : # I'm a single line comment! Block comments are denoted with /* and */ Strings in Z are easy enough to reason with: "Hello" ++ " World" # ===> "Hello World" Z performs coercion, but its coercion rules make more sense than JavaScript's: "9" + 2 # ==> 11 "9" ++ 2 # ==> "92" Booleans also make sense: true and false # ==> false false or true # ==> true Symbol literals are denoted with @, so @x is the same as Symbol.for("x") , and @@iterator is the same as Symbol.iterator . Regexps literals are like JavaScript, but they are denoted with ` rather than / . So `x`g is the same as /x/g Now that you have touched the surface of Z, it's time to take it up a notch and start writing files in Z.

Your First File Now that you've tested Z out, create a directory, call it ztest: $ mkdir ztest For each directory you create that will use Z, you must install the Z Standard Library: $ npm install @zlanguage/zstdlib --save That really wasn't that much setup. Now, create a new file, call it hello-world.zlang : $ touch hello-world.zlang Launch your favorite IDE, open helloworld.zlang, and type: log("Hello World") Execute the file with: $ zcomp run helloworld.zlang It should print out Hello World to the terminal. Files can hold more advanced expressions than the REPL, and have statements in them two. From now on, all examples assume that they are being typed in a file. Some examples will contain features that don't work in the REPL.

Variables Variables in Z can hold any value, they are not constrained to one type of value. Reassignable variables can be declared with let : Note that : is the assignment operator. let x: 5 # ==> x is now 5 x: "Hola Mundo" # ==> x has changed types let y: undefined # ==> You must assign a variable when you initialize it. y: Math.random() # ==> Put something in y Constant variables are declared with def . Constant variables cannot be reassigned, but their internal value can still change: def x: 5 # ==> This looks familiar. x: "Hola Mundo" # ==> Runtime error. Finally, hoisted variables (akin to variables declared with var in JavaScript) are declared with hoist : log(x) # I can see x from all the way up here! hoist x: 5 So to map Z's assignment statements to their equivalents in JS: let - let

- def - const

- hoist - var

Invocations, Arrays, and Objects You've already seen some invocations in Z (of log and Math.random ) As will all built-in data types in Z, Z functions map right to their JavaScript equivalents. Which means calling a function in Z with () transpiles to calling a function in JavaScript with () : log("Hola mundo!") # Log acts like console.log. console.log("Hola mundo!") # Does the same thing. Math.random() # Let's call another JS function Date.now() # They all work fine! Collections in Z Z supports numerous flexible collection literals to represent objects and arrays, the simplest being brackets: [1, 2, 3] # Arrays literals are just like JavaScript let x: 5 [ "hola": "mundo", # Objects are a bit different, object properties in Z are computed, so quotes are required. x # Expands to "x": 5 if there are other properties in the object ] [] # Empty Array [:] # Empty Object Parentheses can also be used to denote arrays, and brackets can denote arrays or objects. Arrays constructed from parentheses and objects constructed from brackets can be used in destructuring (which will be covered later): (1, 2, 3) # Array Literal {1, 2, 3} # Array Literal { "x": 3 } # Object Literal () # Empty Array Literal {} # Empty Array Literal Range literals correspond to arrays. They can be written in several different fashions: 1 to 5 # [1, 2, 3, 4, 5] 1...5 # [1, 2, 3, 4, 5] 1 til 5 # [1, 2, 3, 4] 1 to 5 by 2 # [1, 3, 5] 1 til 5 by 2 # [1, 3] When creating range literals, you can When invoking a function, you can emulate named parameters with an implicit object (like in ruby): Point(x: 3, y: 4) # Is like... Point([ "x": 3, "y": 4 ]) Property Access is akin to JavaScript: x.y # Alphanumeric property access x["y"] # Computed property access (any expression can go in the brackets) x..y # Conditional property access (only works if x isn't falsy, akin to x && x.y)

Control Flow Z supports very simple control flow. It may seem primitive, but for most imperative constructs, it's all you need. When coding Z procedurally (rather than functionally) these control flow statements will be your best friends. Z supports typical if , else if , and else statements: let x: 3 if x = 3 { # Check for equality log("Three times is the charm!") } else if x > 0 { # Check for positivity log("X is positive.") } else { log("X is feeling negative today.") } Z also has the ternary operator, though its syntax is more readable than most programming languages: # An easier way to write the above example let x: 3 log( if (x = 3) "Three times is the charm!" else if (x > 0) "X is positive." else "X is feeling negative today." ) You can simplify one line if statements by putting the if at the end of the line (Ruby-style): log("I'm feeling lucky!") if Math.random() > 0.5 In the looping department, Z supports loop , which is the equivalent of a while(true) loop. You exit a loop with break : let i: 0 loop { if i > 9 { break } log(i) i: i + 1 }

That's it. No fancy potpourri. Just one conditional structure and one type of loop. However, this section only covered Z's imperative control flow structures. You'll see more functional ones soon.

Intro to Functions Functions in Z are created with the func keyword. Z supports anonymous functions only, like CoffeeScript. You can name functions by binding a function to a constant variable. Otherwise, parameters and return statements are rather similar: def add: func (x, y) { return x + y } # Declare a simple function setTimeout(func () { log("Around one second has passed!") }, 1000) # Passing a function as a parameter def something: func () { # Return something awesome }() # IIFE def boundFunction: func () { }.bind(someThisValue) # Functions can have properties accessed on them because they are just objects will an internal [[Call]] property Default parameters are created with the : operator, and rest parameters are created with the ... operator. def add: func (x: 0, y: 0) { # Defaults return x + y } def sum: func (...xs) { return xs.reduce(func (t, v) { # We'll make this example more concise later. return t + v }) } If a function only consists of one return statement, the curly brackets and return may be omitted: def sum: func (...xs) xs.reduce(func (t, v) t + v) You can mark variables declared within a one-line function (a function with an implicit return statement) to be inferred, by ending them with an exclamation point: def sum: func (...xs) xs.reduce(func t! + v!) # We'll see how to make this even more concise later. You can pipe a value through multiple functions via |> : 3 |> +(1) |> *(2) |> log # Logs 8 You can use >> and << for function composition (as in Elm). You can partially apply functions with @ def square: Math.pow(@, 2) def logSquare: log >> square logSquare(10) # Logs 100 A standalone . creates an implied function for property access and method invocations. Currently, implied functions and partial application via @ cannot be mixed. For example: users.map(.name) # Get the name property of users [1, 2, 3, 4, 5].map(.toString(2)) # Get the binary representation of these numbers (in string form). That's pretty much all there is to know about basic functions in Z.

Exceptions The first thing Z clarifies is that Exceptions are not baseballs. For some reason, rather than "raising" an issue, you would "throw" it. That makes no sense at all. And then, to resolve the issue, someone would not "settle" it, but "catch" it. You can't play a friendly game of catch with exceptions. Z's choice of keywords is more intuitive than throw and catch : try { # Attempt to do something raise "Something contrived went wrong" # String coerced into an error object } on err { # When something bad happens settle err # Explicitly tell Z that the error has been settled/resolved. } At this point you are probably asking: why explicitly settle an error? The reason is, explicitly settling an error allows you to put time and thought into how to settle it, and what countermeasures to take. If you forget to settle an error, Z will raise a runtime error. This helps with making Plan Bs when something goes wrong. A try can only have one on clause. Handle type checking of the exception in the on clause.

Modules Z's module system is closely related to JavaScript's. A simple example will demonstrate this. Create a file called exporter.zlang in your test directory, and another file called importer.zlang in that same directory. Now, in exporter.zlang , type: export 3 In importer.zlang , type: import num: "./exporter" log(num) Now, to transpile exporter.zlang , and not immediately run it via the compiler, use the command: $ zcomp transpile exporter.zlang And: $ zcomp transpile importer.zlang To run the code: $ node importer.zlang You should see a 3 printed out. To further elaborate, each module in Z can export one thing, which is implicitly stoned (Z's version of Object.freeze ) when exported. Imports in Z are similar to JavaScript ones, except that from is replaced with : : import something: "./somewhere" import fs # This shorthand becomes: import fs: "fs" import ramda.src.identity # Becomes: import identity: "rambda/src/identity" In order to export multiple things, you can just export an object: export [ "something": cool, "very": cool, cool, "some": other.thing ] As you can see, Z modules are (pretty) easy to work with. We'll see a cool way to import multiple things from a module that exports an object in the next section.

Pattern Matching Z comes with a default ternary operator: let happy = true let mood = if (happy) "good" else "bad" # if (cond) result2 else result2 let moodMessage = if (mood = "good") "My mood is good." else if (mood = "bad") "I'm not feeling good today." else "Unknown mood." # Chaining ternary operators. However, for advanced conditional checks, this fails to be sufficient. That's where Z's pattern matching comes into play. The match expression at its simplest can match simplest can match simple values: let moodMessage = match mood { "good" => "My mood is good", "bad" => "My mood is bad", _ => "Unknown mood" # _ is a catch-all } Patten matching is more powerful than this though. It's not limited to matching primitives. You can also match exact values that are arrays and objects: let whatItIs: match thing { [1, 2, 3] => "An array of [1, 2, 3]", ["x": 3] => "An object with an x value of 3", _ => "I don't know what thing is." } You can also match types with pattern matching: let contrived: match someExample { number! => "A number.", string! => "A string.", array! => "An array", _ => "Something else." } If you want to capture the value of a certain type, use ! like an infix operator: let times2: match thing { number!n => n * 2, string!s => s ++ s, _ => [_, _] } Now, to capture elements of arrays, use ( and ) : def arrResult: match arr { (number!) => "An array that starts with a number.", (string!s, string2!s2) => s ++ s2, (x, ...xs) => xs, # xs represents the rest of the array, which excludes the first element in the array _ => [] } Objects can be matched with the { and } characters: def objResult: match obj { { x: number!, y: number! } => "A point-like object.", # Match an objects with x and y properties { name: string!name, age: number!age, car: { cost: number!, brand: string!brand } } => "A person named " ++ name ++ " that is " ++ age ++ " years old. He/She owns a " ++ brand ++ " type of car.", _ => "Some other thing" } To match a number in between other numbers, use range literals: def typeOfSquare: match square { { size: 1...10 } => "A small square.", { size: 11...20 } => "A medium square.", { size: number! } => "A big square.", _ => "Something else." } The object and array delimiters in pattern matching work as destructuring too: def (x, y): [3, 4] # x is 3, y is 4 def {x, y}: [ "x": 3, "y": 4 ] # x is 3, y is 4 You can define blocks to be associated with different patterns, for example: match num { 1 => { log("Num is 1.") log ("I love the number 1.") # You can put multiple lines in a "block" return "YAY!" # Blocks are wrapped into functions, so you can return from them. }, _ => "Not 1 :(" } You can define your own custom pattern matching conditions with predicates . To start, define some functions that return a booleans: def even: func x! % 2 = 0 def odd: func x! % 2 = 1 Then, use the ? at the end of the function name inside a match body to use the predicate: match num { even? => "An even number.", odd? => "An odd number.", number! => "Some other number.", _ => "Something else." } The most advanced form of custom pattern matching is the extractor . It allows you to not only perform a conditional check on data, but to perform custom matching on it. Let's start by defining a simple email function: def Email: func user! ++ "@" ++ domain! Then, we can defined a extract method on email . This extract method should return an array if there is a pattern to be matched, or undefined , if there is no match: Email.extract: func (str) if (str.includes("@")) str.split("@") else undefined def myEmail: "programmer@cloud.com" match myEmail { Email(user, domain) => log(user, domain), # Logs programmer, cloud.com _ => log("Invalid email.") } As you can see extractors and predicates add greater flexibility and power to pattern matching.

Runtime Types Z supports numerous ways to create runtime type checks. Each object in Z can specify its "type" by having a function called type : [ "x": 5, "y": 5, "type": func "Point" ] You can find out something's type using the built-in typeOf function: typeOf(3) # ==> "number" typeOf([1, 2, 3]) # ==> "array" typeOf([ "x": 5, "y": 5, "type": func "Point" ]) # ==> "Point" You can check that a parameter passed to a function is of a certain type at runtime (checking is done behind the scenes with typeOf ): def add: func (x number!, y number!) { # Note that you can't mix type annotations with default values and rest/spread def res: x + y return res } ! isn't actually part of the type. It just denotes that a type is present. You can also add return type annotations: def add: func (x number!, y number!) number! { def res: x + y return res } You can also validate that the right-hand side of an assignment is of a certain type: def add: func (x number!, y number!) number! { def res number!: x + y return res } This works great for simple functions, however you may need to implement more complex ones. This is made possible by the enter and exit statements: def readPrefs: func (prefs string!) { enter { prefs.length < 25 } def fileHandler: file.getHandler(prefs) # Some imaginary file system. # Do some stuff return something exit { fileHandler.close() # Clean up the file handler, exit is like finally and must be the last statement in a function. } } enter is a block of code that contains comma-separated conditions, all of which must be true when the function starts: def readBytes(bytestream Bytestream!, amount number!) { # fictional type Bytestream enter { bytestream.size < amount, amount < 100, amount > 0, } # Do stuff... } exit pretty much the same as enter, except it is executed at the end of the function, to see if certain conditions have been met. exit must be the last statement in a function. A function may only have one enter statement and one exit statement.

loop Expressions loop expressions are directly inspired by Scala. They are based on Scala's for expressions, and they may resemble list comprehensions in some languages. To start, use the operator <- to map over a list: def xs: [1, 2, 3] def result: loop (x <- xs) x * 2 # Result is [2, 4, 6] You can add predicates using a form of if : def xs: [1, 2, 3] def result: loop (x <- xs, if x % 2 = 0) x * 2 # Result is [2, 6] You can iterate over multiple lists by inserting multiple <- s: # Range literals: 1...5 is [1, 2, 3, 4, 5] def result: loop (x <- 1...10, y <- 1...10) [x, y] # Matrix of numbers 1 to 10 Using all of this, you could define a flatMap function: def flatMap: func (f, xs) { return loop ( x <- xs, y <- f(x) ) y } Note that you cannot start a line with a loop expression, as it will be confused with the imperative loop statement. The final ability of the loop expression is that you can place assignments in it. For example: def strs: ["Hello", "World"] def res: loop (s <- strs, l: s.length) l * 2 # res is [10, 10]

Operators You've already seen use of plenty of operators in Z. You've seen addition, subtraction, comparison, equality, and more. But for complete reference, below is a list of operators that come with the Z runtime, and their precedence: The Left Overload is a method you can define on an object to overload the operator on the left-hand side: x + y becomes x.+(y) if x defines a + method. becomesifdefines amethod. The Right Overload is a method you can define on an object to overload the operator on the right-hand side: x + y becomes y.r+(x) if y defines a r+ method. Operator Associativity Precedence Function Left Overload Right Overload pow Right Infinity Performs exponentiation NA (overload * instead) NA (overload r* instead) til Left 555 Exclusive range prev & succ & < NA to Left 555 Inclusive range prev & succ & < NA by Left 444 Used to specify the step of ranges NA NA ^ Left 333 Performs exponentiation NA (overload * instead) NA (overload r* instead) % Left 222 Performs modulus % r% / Left 222 Performs division / r/ * Left 222 Performs multiplication * r* + Left 111 Performs addition + r+ - Left 111 Performs subtraction - r- ++ Left 111 Performs concatenation concat NA >> Left 1 Left-to-right composition NA NA << Left 1 Right-to-left composition NA NA |> Left 1 Pipe NA NA < Left -111 Less-than < r< <= Left -111 Less-than or Equal-to NA (Define < instead) NA (Define r< instead) > Left -111 Greater-than NA (Define < instead) NA (Define r< instead) >= Left -111 Greater-than or Equal-to NA (Define < instead) NA (Define r< instead) = Left -222 Compares Structural Equality = r= and Left -333 And boolean comparison NA NA or Left -333 Or boolean comparison NA NA becomesifdefines amethod. The negative precedence and non-consecutive precedence numbers will be explained soon. First Class Operators Z has first-class operators, meaning the operators aren't special. They can be created, stored in variables, and in fact, are just ordinary functions. + is just defined as an ordinary function! Functions (like + ) can then be called with infix syntax (Note that in Z 0.4.0+, operators MUST HAVE ALL SYMBOL NAMES): However, operators are left associative and can have custom precedence: def +': func x! + y! 3 +' 4 * 2 # ==> 11 +' has no precedence, defaults to 1, evaluates after multiplication You can define a custom precedence for your operators: # Continuing from the last example: operator +': 1000 # Give it a high Precedence 3 +' 4 * 2 # ==> 14 Now, all the large precedence numbers should make sense. Operators having large gaps in precedence allows for insertion of operators in between precedence levels. Since operators are functions, they can be curried. All the built-in operators actually are: 3 |> *(2) |> +(1) |> to(1) # [1, 2, 3, 4, 5, 6, 7] The following symbol characters are allowed in identifiers: + , - , * , / , ^ , ? , < , > , = , ! , \ , & , | , % , ' Since operators are just functions, you can use them like ordinary functions: # Add function from before: def add: + # Sum an array [1, 2, 3].reduce(+)

Macros Macros are compile-time "functions" that operate on AST nodes. Let's start by looking at a very simple macro: macro $hello () { return ~{ "Hello World" }~ } There's a lot going on here. First, we define a macro called $hello with the macro keyword. All macros in Z start with the $ symbol, because this makes them "pop out" - so you know what's a macro and what isn't. Then, we return a template, denoted by ~{ and }~ which contains some Z code. This template in this case just contains the string "Hello World" , meaning that any call to this macro is immediately replaced with "Hello World" at compile time. For example: log($hello) With the macro above, it will now print "Hello World". Now, macros can also take parameters. This simple $id macro takes one expression and returns it: macro $id (~x:expr) { return ~{ {{~x}} }~ } You can see what happens. The tilde denotes a macro parameter, which in this case is of type expr . You call this parameter x . Then, when you return a template, you use double braces and the tilde operator again, to "spread" the value of x into the template. For example: log($id [1, 2, 3]) It just logs what you passed to the macro. However, parameters passed to any macro are also available in AST form. For example: macro $addFour (~arr:expr) { arr.push(4) return ~{ {{~arr}} }~ } log($addFour [1, 2, 3]) It will log [1, 2, 3, 4] . However, because AST nodes are passed to macro by reference, you're not allowed to reassign them without loosing the reference. So arr: arr.concat(4) would make not change the value of the AST node. You can also pass blocks to macros - this makes for a natural looking syntax: macro $while (~cond:expr, ~body:block) { return ~{ loop { if not({{~cond}}) { break } {{~body}} } }~ } $while true { log("MACROS ARE AWESOME!!!!") } As one can see, blocks spread into their execution context, so the block passed to $while becomes part of the loop block. Let's say we wanted to make a for-loop macro. It would iterate over a collection, like JavaScript's for-of loop. The parameter list looks like this: macro $for (~l:expr, of, ~r:expr, ~body:block) { } The standalone of in the parameter list defines a conextual keyword. So of can act like a keyword in the context of a $for macro. Now, since we want to iterate over all iterators, we are going to use Z's loop expression (from the last section): <- . We are going to define a callback, and for each element of the iterator we're going to call the function for it. Since Z's macros are are non-hygenic, and since we don't want to corrupt the local environment, we are going to use psuedohygiene for a variable names. This means Z will randomly generate ids for a variable names that keep them readable while leaving only a one in one million chance of a name conflict with another generated identifier. You accomplish this by using double brackets without the tilde: macro $for (~l:expr, of, ~r:expr, ~body:block) { return ~{ def {{callback}}: func ({{~l}}) { {{~body}} } {} ++ loop ({{i}} <- {{~r}}) {{callback}}({{i}}) }~ } You can use it like this: $for x of [1, 2, 3] { log(x) } Now, macros can also take keywods as arguments via id parameters: macro $asgn(~type:id, ~lvalue:expr, =>, ~rvalue:expr) { return ~{ {{~type}} {{~lvalue}}: {{~rvalue}} }~ } $asgn def x => 3 $asgn let y => 3 Finally: marco varargs capture groups within a certain pattern. You can then use ...(){} to generate statements for each captured argument: macro $logEach (...(~toLog:expr)){ return ~{ ...(){ log({{~toLog}}) } }~ } $logEach (1 2 3 4 5) This logs each number. A trailing comma can be added to indicate comma seperated values: macro $logEach (...(~toLog:expr,)){ return ~{ ...(){ log({{~toLog}}) } }~ } $logEach (1, 2, 3, 4, 5) Using all of this, you can define a $switch macro: macro $switch (~val:expr, ...{case, ~test:expr, ~body:block}){ return ~{ ...(){ if {{~test}} = {{~val}} { {{~body}} } } }~ } Then you can use it like this: $switch 1 { case 1 { log("1") } case 2 { log("2") } case 3 { log("3") } } Since macros aren't runtime constructs, you can't export them. Instead, in an old-timey fashion, you include macros into your program. The include statement copies and pastes the contents of one Z file into another, during compilation, which allows macros to be "imported": include "./for.zlang" # A file with the $for macro we defined before $for x of [1, 2, 3] { log(x) } Macros can also be grabbed from the standard library via includestd : includestd "imperative" # Grabs all the macros from the imperative.zlang file stored in the standard library.

Enums A note: Enums are only available in Z 0.3.1+. A stable, non-buggy implementation of enums is only available in 0.3.5+. While Z doesn't support classical OOP, Z mixes OOP and FP in Rust-Style enums, which are akin to the algebraic data types of functional languages. We are going to create a classic cons-list. You may also know this as a linked list. The general idea of a cons-list is that each "node" of the list could either be Nil , the empty/end of a list, or a value, and the rest of the cons-list. For example, the cons-list equivalent of [1, 2, 3] would be: Cons(1, Cons(2, Cons(3, Nil()))) To implement this, let's look at enum s. Enums in Z aren't a special new kind of type, they're just a special way to define certain types of functions. To start, let's make a simple enum representing a color: enum Color { Red, Orange, Yellow, Green, Blue, Purple } We can construct new members of an enum simply by calling its possible states: Red() # Constructs the "Red" member of the color enum. Orange() # Constructs the "Orange" member of the color enum. You can also refer to the enum collectively via its name: # This is the same as the example above. Color.Red() Color.Orange() The = operator is automatically defined on each state of Color . For example: def col: Red() col = Red() # true col = Color.Red() # Also true col = Orange() # false Now that you've seen the basics of enums, let's start defining our cons-list enum. We'll call it List and give it two possible states: Cons and Nil : enum List { Cons, Nil } However, there's a problem. Cons needs to store two pieces of data: the first value and the rest of the list. In order to do this, we need fields. Let's look at a simple example of fields with a Point enum: enum Point { Point(x, y) } # This could also be written as the following: enum Point(x, y) # Because the Point enum has only one constructor with the same name as it Now, we can construct point objects using Point , or even Point.Point . They will have read-only x and y properties defined on them: def myPoint: Point(3, 4) log(myPoint.x) # 3 log(myPoint.y) # 4 def anotherPoint: Point(x: 3, y: 4) # Named fields can be used to increase readability. def thirdPoint: Point(y: 4, x: 3) # Named fields can be in any order. log(myPoint = anotherPoint) # This is true, fields are taken into account in equality too. We can also use pattern matching to extract fields: match something { Point(x, y) => x + y, # Only runs if object is constructed via Point. _ => "Not a point" } Using fields, we can create a working implementation of the cons-list: enum List { Cons(val, rest), Nil } Now, we can create cons-lists, and test if they are equal: def li1: Cons(1, Cons(2, Nil())) def li2: Cons(1, Cons(3, Cons(4, Nil()))) def li3: Cons(val: 1, rest: Cons(val: 2, rest: Nil())) li1 = li2 # False li1 = li3 # True Now, to easily iterate and apply transformations to cons-lists, let's define a consForEach function that takes a function and a cons-list as a parameter and will pass the function each value in the cons-list: def consForEach: func (f, list) { loop { if list = Nil() { break } f(list.val) list: list.rest } } However, shouldn't we be able to associate consForEach with List itself. Say hello to the where block. Add the following to your List definition: enum List { Cons(val, rest), Nil } where { forEach(f, list) { loop { if list = Nil() { break } f(list.val) list: list.rest } } } Now, you can use forEach like this: List.forEach(log, Cons(1, Cons(2, Cons(3, Nil())))) It will print out the elements of the cons-list, one by one. Now, how can we add types to the fields of Cons ? Let's start by observing types of fields in action: enum Point(x: number!, y: number!) Point(3, 4) # All good! Point("hola", 4) # Error! enum Line(start: Point!, end: Point!) # Enums can also be used as types Line(Point(3, 4), Point(3, 4)) # All good! Line(3, 4) # Error! Because of this, you'll probably try something like: enum List { Cons(val, rest: List!), Nil } However, you'll get an error. Currently, all of an enum constructors must be typed or all must be untyped. There's no in-between. To get around this, you can use the _! type, which is a work-around for enums: enum List { Cons(val: _!, rest: List!), Nil } Now, you'll receive an error (at runtime) when rest is not of type List , but val can be of any type. While the forEach functioned defined above is useful, what if we wanted to print out the cons-list as a whole? If you were programming in JavaScript, you might write a custom implementation of the toString method. However, enums can derive traits, and unlike in other languages traits/interfaces/protocols in Z are just normal functions given context via the derives keyword. Let's look at how this works. Start by importing the standard library's traits module traits : importstd traits Now, extract the Show trait from traits : def {Show}: traits Now, alert your definition of List to use the derives keyword: enum List { Cons(val: _!, rest: List!), Nil } derives (Show) where { forEach(f, list) { loop { if list = Nil() { break } f(list.val) list: list.rest } } } Now, you'll find that any cons-list constructed has a toString method: log(Cons(1, Cons(2, Cons(3, Nil()))).toString()) # Logs "Cons(val: 1, rest: Cons(val: 2, rest: Cons(val: 3, rest: Nil())))" Now let's look at another kind of way to implement a trait: statically. Traits implemented with the static keyword are automatically applied to each instance of an enum, but to the enum itself. To demonstrate, take the Curry trait from the trait module : def {Show, Curry}: traits Now, add static Curry to the derives expression in the definition of list: enum List { Cons(val: _!, rest: List!), Nil } derives (Show, static Curry) where { forEach(f, list) { loop { if list = Nil() { break } f(list.val) list: list.rest } } } Curry makes all of an objects methods curried, and sicne we derived Curry on List , we can do: def logger: List.forEach(log) logger(Cons(1, Cons(2, Cons(3, Nil())))) Below is a list of all the traits defined by the traits module: Show Defines a toString method on an instance of an enum, which provides a more meaningful string to work with than "[object Object]" . Read Defines a read method on an enum that attempts to parse a string and return an instance of that enum. However, parsing is limited and only numbers and built-in constants will be converted to their equivalents. Should be implemented with static . Ord Makes an enum comparable by overloading < . Starts by comparing constructor order: enum Color { Red, Orange, Yellow, Green, Blue, Purple } derives (Ord) Yellow() < Blue() # True Orange() > Red() # True Yellow() <= Orange() # False If both the left-hand operand and the right-hand operand have the same constructor, it will check to see if the left-hand operand's field is less than the right-hand operand's field: enum Maybe { Just(thing), None } derives (Ord) Just(3) < Just(5) # True It is not recommended to use Ord on enums that have constructors that have more than one field. Copy Copy defines a copy method on each instance of an enum: enum Point(x: number!, y: number!) derives (Show, Copy) log(Point(3, 4).copy(y: 2).toString()) # Logs Point(x: 3, y: 2) Enum Enum defines the methods prev , succ , and to on each instance of an enum to allow for creation of ranges and the like: enum Color { Red, Orange, Yellow, Green, Blue, Purple } derives (Show, Enum) log(Red().succ().succ().succ().prev().toString()) # "Yellow()" log(Red().to(Yellow()).toString()) # "Red(),Orange(),Yellow()" log(Yellow().to(Red()).toString()) # "Yellow(),Orange(),Red()" By deriving both Enum and Ord you can overload range literals (the to type, not the ... type): enum Color { Red, Orange, Yellow, Green, Blue, Purple } derives (Show, Ord, Enum) log((Red() to Yellow()).toString()) # Red(),Orange(),Yellow() log((Purple() til Red() by 2).toString()) # Purple(),Green(),Orange() PlusMinus PlusMinus overloads the + and - operators for every instance of an enum. If both operands have the same constructor, and returns a new instance of that constructor with all the fields added. Otherwise, it adds/subtracts the relative order of the constructors in the enum declaration, and returns an instance of the constructor at that index. Json Makes each instance of an enum JSON serializable. Curry Curries each method of a certain object. That means if it's implemented with static it curries the methods of an enum. If it's implemented without static , it will curry every method on every instance of the enum. All the traits above are great, but what if we wanted to build our own trait? We're going to be constructing a Sum trait that defines a sum method to add all of a traits fields together. The implementation of the trait is below: def Sum: func (obj) { obj.sum: func () { let sum: 0 obj.fields.forEach(func (field) { sum: sum + obj[field] }) return sum } return obj } First off, you may notice there's no new trait keyword. It's just a function. First, the function takes an object representing the newly constructed instance of an enum. It then adds a method to that object: sum. Every instance of an enum has a read-only fields property which holds an array containing the string names of every property defined by the enum constructor. By iterating over that array, we can pull out each field name, and then the value of each field. It adds them, and then returns the object, which now has a sum method. Now, to use this, let's revisit the Point enum from earlier, and derive Sum on it: enum Point(x: number!, y: number!) derives (Sum) Try using a sum method on a point instance: log(Point(3, 4).sum()) It should log 7. When you derive a trait statically, the object passed to the function is the enum itself, for example the Point object would be passed to the Read trait if it were derived statically. To add "reflection" to each enum instance, every instance contains the following metadata: instance.fields # Array of all fields the constructor defined on the instance instance.constructor # Reference to the constructor of the instance (which is just a function) instance.parent # Reference to the overarching enum that the point's constructor belongs to (which is just an object) parent.order # Array of the order in which the constructors for an enum were defined. Useful for creating traits like "Ord" and "Enum"

Advanced Compiler Commands There are three commands in the compiler that have not yet been covered: dirt , watch , and wdir : Directory Recursive Transpilation or DIRT: The dirt command will transpile an entire directory to an "out" directory, maintaining file structure. So if you have a directory called src , and you want to transpile everything in it to dist , use: $ zcomp dirt src dist That's it. Watching Files If you have a file, say iwillchange.z , use the watch command to monitor it for changes, and transpile the file when changed: $ zcomp watch iwillchange.z ../dist/iwillchange.js Directory Watching The wdir command will watch a directory for changes, and then use dirt to transpile it when changes occur. This is useful for production, where you have complex nested directories that you need to transpile all at once. For example: $ zcomp wdir src dist In 0.3.8+, the Z REPL has additional capabilities. First off, it will allow you to enter multiline statements when the first statement ends in { , ( or [ . When you close the block, invocation, or array/object literal, all that code will be evaluated via the repl. You can also load and gain access to the functions in a Z file using the :l command. If you have a file called add.zlang , which contains a function that adds two numbers, load it via: zrepl>:l add And then you can use it as if you had typed it into the REPL yourself.

Runtime Overview Below is a list of all the built-in non operator functions included in the Z runtime: isObject(val) Returns true if val is not a scalar primitive. Otherwise, returns false . typeOf(val) Returns the type of val according to the following algorithm: Is val undefined ? If so, return "undefined" . Is val null ? If so, return "null" . Does val have a function? Does that function return a string ? If so, return the result of calling val 's type function. Is val NaN ? If so, return "NaN" . Does Array.isArray return true for val ? If so, return "array" . Return the result of calling typeof on val . typeGeneric(val) Returns the type of val according to the following algorithm: Does val define typeGeneric function? Does that function return a string ? If so, return the result of calling that function. Is val an array ? If so, return a string in the format "array<types>" , where types is equal the result of joining a unique set of calling typeGeneric on all the elements in val with "|" stone(val) Returns the result of recursively calling Object.freeze on an object and its properties. Returns the object, which is now deeply immutable. copy(val) Returns a deep copy of val , except for functions, for which it will return val itself. log(...vals) Alias for console.log . not(val) Coerces val to a boolean , then returns the negation of that. both(val1, val2) Applies the JavaScript && to val1 and val2, coerces the result to a boolean , and then returns that. either(val1, val2) Applies the JavaScript || to val1 and val2, coerces the result to a boolean , and then returns that. m(...vals) Returns the result of calling vals.join("

") chan() Makes a channel. send(val, ch) Sends a value to a channel. curry(f) Curries a function (loosely). JS The following methods are defined on the global JS object: Method JS Equivalent JS.new(constructor, ...args) new (constructor)(...args) JS.typeof(val) typeof val JS.instanceof(val, class) val instanceof class /td> JS.+(x) +x JS.+(x, y) x + y JS.-(x) -x JS.-(x, y) x - y JS.*(x, y) x * y JS./(x, y) x / y JS.**(x, y) x ** y JS.%(x, y) x % y JS.==(x, y) x == y JS.===(x, y) x === y JS.!=(x, y) x != y JS.!==(x, y) x !== y JS.>(x, y) x > y JS.<(x, y) x < y JS.<=(x, y) x <= y JS.>=(x, y) x >= y JS.&&(x, y) x && y JS.||(x, y) x || y JS.!(x) !x JS.&(x, y) x & y JS.|(x, y) x | y JS.^(x, y) x ^ y JS["~"](x) ~x JS.<<(x, y) x << y JS.>>(x, y) x >> y JS.>>>(x, y) x >>> y

Standard Library Z's standard library is small, but growing. It contains 15 modules, detailed below. Each module (except the matcher and constructs modules) also has its own section, after this one. Modules in Z's Standard Library: Template - A module that performs string templating, complete with encoding functions and nested object templating.

- A module that performs string templating, complete with encoding functions and nested object templating. Tuple - An implementation of fixed-size immutable collections (i.e. Tuples) in Z.

- An implementation of fixed-size immutable collections (i.e. Tuples) in Z. constructs - A module containing multiple control flow structures implemented as functions.

- A module containing multiple control flow structures implemented as functions. matcher - The behind-the-scenes implementation of Z's pattern matching. Not for use. Use match expression instead

- The behind-the-scenes implementation of Z's pattern matching. Not for use. Use expression instead utf32 - An implementation of Unicode in Z, with proper character indexing, Unicode-aware slicing, and more.

- An implementation of Unicode in Z, with proper character indexing, Unicode-aware slicing, and more. actors - A (primitive) recreation of the Actor Model in Z.

- A (primitive) recreation of the Actor Model in Z. F - A functional utility module that is akin to Rambda.

- A functional utility module that is akin to Rambda. gr - Utility methods for goroutines.

- Utility methods for goroutines. traits - Traits to derive on enums.

- Traits to derive on enums. Decimal - A big decimal implementation for Z.

- A big decimal implementation for Z. Rational - A bigrational number implementation for Z.

- A bigrational number implementation for Z. Complex - A complex number implementation for Z.

- A complex number implementation for Z. taylor - Taylor series used to approximate irrational numbers.

- Taylor series used to approximate irrational numbers. mercen - A web scraper that asynchronously fetches a list of all discovered Mersenne primes.

- A web scraper that asynchronously fetches a list of all discovered Mersenne primes. scrapy - A web scraper designed to extract a webpage's text content, and then allow you to execute queries on it.

- A web scraper designed to extract a webpage's text content, and then allow you to execute queries on it. gen - Generators based of Douglas Crockford's generators in How JavaScript Works.

- Generators based of Douglas Crockford's generators in How JavaScript Works. objutils - Tools for managing object references. Z's standard library also defined the following macro files: imperative - Imperative constructs from languages like Java and Ruby

Template Template is Z's way to perform advanced string interpolation. To start, you use the Template constructor to make a Template . Then, you resolve the template by calling resolve with data: importstd Template def nameTemplate: Template("{{person.name:upper}} is a nice name.", [ "upper": func (str) { return str.toUpperCase() } ]) log(nameTemplate.resolve([ "person": [ "name": "Joe" ] ])) # ==> "JOE is a nice name."

Tuple Z's Tuple module allows you to create Tuples not exceeding 4 elements: importstd Tuple def red: Tuple(255, 0, 0) def green: Tuple(0, 255, 0) def yellow: ++(red, green) log(yellow._1, yellow._2, yellow._3) # ==> 255 255 0