Quick Guide
This is a small guide to nearly all Nemerle features, specially for people coming from C#:
Variables
- mutable a = 5;: mutable variables can be changed later
- def b = 4;: normal variables cannot be changed
In all variables, type inference works
- def c : float = 4;: a type annotation
Lists
- def nil = [];: the empty list is []
- def numbers = [1, 2, 3];: generate a list with those values
- def more_numbers = 4 :: numbers; : :: adds a new item to the list
List comprehensions
- $[ (x, y) | x in list1, y in list2, x < y]: get all pairs on the lists for which the condition is true.
- $[1, 3 .. 8]: ranges, from 1 to 8 step 2 (3-1)
- $[1 .. 5]: range from 1 to 5 step 1
- $[ (x, y) | x in [1 .. 3], y in [2, 4 .. 10] ]: generate all pairs
more...
Useful methods on lists
- Length, Head, Tail, Last, Nth
- FirstN: return first N elements of the list
- ChopFirstN: return the list without the first N elements
- LastN: return the last N elements
- Reverse
- Remove: removes an element
- Contains
- Iter (f : 'a -> void): executes the function in all elements
- Map (f : 'a -> 'b): returns a new list['b], executing the function in all elements of the list['a]
- Group (f : 'a * 'a -> int): return a list of lists, grouping the elements whose function returns the same value
- FoldLeft, FoldRight: returns a value result of executing the function recursively on the list, with a first element, in normal or reverse order
- ForAll (f : 'a -> bool): returns true if all elements return true
- Exists (f : 'a -> bool): returns true if at least one application of the function in the elements returns true
- Find (pred : 'a -> bool): finds the first element whose predicate is true
- Filter (pred : 'a -> bool): returns a new list containing all elements whose predicate is true
- Sort (cmp : 'a * 'a -> bool): sorts the list based on the method. The reason underlying the fact that the function returns an int is that CompareTo functions in .NET return an int
- RemoveDuplicates
- ToArray
Arrays
- def a = array(3);: specifies the number of elements
- def b = array[1, 2, 3]: specifies the elements
Tuples
- def t = (1, "one");: a tuple is a set of values which no name to recognise them
- def fst = t[0];: use 0-based index to get the items
Nemerle.Utility.Pair
This class contains three methods that work with pairs (tuples of two elements):
- First and Second retrieve the first or second element of the tuple, respectively
- Swap exchanges both elements of the pair
Decisions
- when (condition) code: execute code if condition is true
- unless (condition) code: execute code if condition is false
- if (condition) code1 else code2: execute code1 if condition is true, code2 if it is false
Loops
- for (mutable i = 0; i < 10; i++) code: for loop as of in C
- for (i in $[0..9]) code like the above, using range
- for (i in $[9,8..0]) code reverse order
- while (condition) code: execute code while condition is true
- do code while (condition): the same as above, but checks the condition at the end of the code, so it is always run at least once
- foreach (x in list) code: execute the code for every member x of the enumerable collection list
- repeat (10) code: repeats the code the specified number of times
Exceptions
- throw ArgumentException();: throws a new exception of the desired type
- Syntax for try-catch-finally handler resembles the one from C#, although catch handlers use a pattern matching-like syntax:
try {
code
}
catch {
| e is ArgumentNullException => ...
| e is OverflowException => ...
| _ => ...
}
finally {
// Finally code is always executed
// no matter an exception where thrown or not
}
Variants
- Create a variant with empty options and options with extra information
variant Volume {
| Max
| Min
| Other { v : int }
}
- def v1 = Volume.Max ();: an empty constructor is used for empty options
- def v2 = Volume.Other (5);: the constructor for non-empty elements gets all fields as parameters, in the order they were written in code
Enums
As in C#, are just a good face for ints:
enum Seasons {
| Spring
| Autumn
| Winter
| Summer
}
Pattern Matching
Literal matching
match (value) {
| 1 => "one"
| 2 => "two"
| _ => "more"
}
match (value) {
| "one" => 1
| "two" => 2
| _ => 0
}
match (value) {
| Seasons.Spring
| Seasons.Summer => "hot"
| _ => "cold"
}
List matching
match (some_list) {
| [42, 42] => "two forty-two"
| [42, _] => "forty-two on first position of two-element list"
| [_, 42] => "forty-two on second position of two-element list"
| 42 :: _ => "forty-two on first position"
| _ :: 42 :: _ => "forty-two on second position"
| [] => "an empty list!"
| _ => "another list"
}
Variable pattern
Binds the variable names:
def display (l) {
match (l) {
| head :: tail =>
Write ($ "$head, ");
display (tail)
| [] =>
WriteLine ("end")
}
}
Tuple pattern
match (tuple) {
| ( 42, _ ) => "42 on first position"
| ( _, 42 ) => "42 on second position"
| ( x, y ) => $"( $x, $y )"
}
Type check
Checks if the value is of given type, binding the new value with the new type
def check (o : object) {
match (o) {
| i is int => $"An int: $i"
| s is string => $"A string: $(s.ToUpper())"
| _ => "Object of another type"
}
}
Record pattern
Binds on field or properties
def check_class (c) {
match (c) {
| MyClass where (foo = 0) => true
| _ => false
}
}
If the type is known to the compiler, the where clause is not needed
def check_class (c) {
match (c) {
| (foo = 0) => true
| _ => false
}
}
as pattern
Binds a value matched with an identifier
variant Foo {
| A { x : int; mutable y : string; }
| B
}
match (some_foo ()) {
| A (3, _) as a =>
a.y = "three";
| _ => {}
}
Type hint pattern
Used to explicitly declare types where the compiler cannot infer it
def foo (l) {
| (s : string) :: _ => s [0]
| [] => '?'
}
with clase
Used to specify a default value in cases where we need to match both a small and a big structure with the same code.
def foo (_) {
| [x] with y = 3
| [x, y] => x * y
| _ => 42
}
Regular Expressions match
regexp match (str) {
| "a+.*" => printf ("a\n");
| @"(?<num : int>\d+)-\w+" => printf ("%d\n", num + 3);
| "(?<name>(Ala|Kasia))? ma kota" =>
match (name) {
| Some (n) => printf ("%s\n", n)
| None => printf ("noname?\n")
}
| _ => printf ("default\n");
}
you must add a reference to Nemerle.Text to use this functionality
(using Nemerle.Text)
Yield
- Works as in C#, used for enumerating sequences:
Range (from : int, to : int) : IEnumerable[int] {
for (mutable i = from; i <= to; i++)
yield i;
}
Imperative programming and Blocks
To use return, break and continue we need to open the Nemerle.Imperative namespace:
- return x;: cuts the execution of the function, method or property, stablishing x as the return value
- continue;: on a loop, continues with the next iteration
- break;: on a loop, cuts the execution of the loop and continues with the following code
Blocks are a set of instructions, preceded with an identifier and a colon. The result of the block is the last value computed, except if the name of the block is used,along with the return value, to jump out the block.
def x =
foo: {
when (some_cond) foo (3); // if some_cond is true, the block will return
qux ();
42 // else it will return 42
}
more...
Functions
- Functions can be declared inside methods, and type inference works for them:
public Greet (people : list[string]) : void {
def say_hello (s) {
System.Console.WriteLine ($"Hello $s");
}
foreach (person in people)
say_hello (person);
}
- compute (f : int * int -> int, x : int, y : int) { ... }: functions can be passes as parameters, whose types are divided by * and its return type is told after ->
- compute ( fun (x, y) { x + y }, 3, 4): anonymous functions can be created inline, just preceding them with fun and its list of parameters
- def addFive = compute (fun (x, y) { x + y }, _, 5): partial application, substitutes one or more parameters, then yielding another function with a smaller set of parameters
- def addFive = _ + 5;: partial application substituting the parameter with _
- def name = _.Name;: you can also use this type of partial application to access members
- lambda x -> Console.WriteLine (x): a easier construct to create a function with just one parameter
String formatting
- def s = $"The number is $i";: insert the value of the variable i where $i is placed
- def s = $"$x + $y = $(x+y)";: $(...) can be used to make calculations or access members
print Functions
- print (value), sprint, fprint: substitutes variable names with $ notation in the string and returns it to Console, string or TextReader, respectively
- printf (value), sprintf, fprintf: as above, but with formatting
- scanf (format), sscanf, fscanf: returns a string extracted from console, string or TextReader that keeps the specified format
Type conversions
- def s = n :> int;: cast may fail with an InvalidCastException
- def s = n : int;: cast cannot fail, only for supertypes
Namespaces
- namespace NS { ... }: declares a new namespace
- using System;: open the namespace, that is, makes all members inside it not to requiere full qualifying. It also opens namespace inside it (different with C#)
- using System.Console;: open the type, making its methods visible
- using C = System.Console;: create an alias to refer the type or namespace
Classes and Modules
- class Example { ... }: creates a class Example
- module Example { ... }: creates a module Example, that is, a class with all members static
Interfaces
Defines a set of public methods an adhering class must implement
interface IExample {
Method() : void;
}
class Example : IExample {
public Method () : void { ... }
}
Accessibility
- public: everyone can access
- internal: only classes in the current assembly (DLL or EXE) can access
- private only current type can access
- protected: access is limited to current type and its derived types
- protected internal means protected or internal - access limited to derived types or types in the current assembly
Modifiers
- static: no instance is needed for accessing
- mutable: if not set for field, they are read-only
- volatile: only for fields, it means that the field has to be always read from the memory, and written instantly. Useful for multithreaded programs
- extern: used on methods, along with DllImport attributes to call out to native code
- partial: only on type definitions, it means that a given type definition is split across several files
Constructors
class Example {
mutable Name : string;
public this (name : string) {
Name = name;
}
}
- def n = Example ("serras");: no new keyword is used to create new objects
Static Constructors
Executed once per type. No parameters.
class Example {
static public this() { ... }
}
[Record] macro
Generates a constructor wich assigns a value to every field:
[Record] class Point {
public x : int; public y : int;
}
is the same as:
class Point {
public x : int; public y : int;
public this (x : int, y : int) {
this.x = x; this.y = y
}
}
Inheritance
- class Human : Mammal { ... }: class Human inherits from Mammal, or implements Mammal interface
Modifiers
- abstract: the method contains no actual implementation, that must be provided in child classes
- override: redefinition of a virtual or abstract method
- virtual: the most derived method will always be called
- new: allows name redefinition in nested or derived classes
- sealed: no derivation or redefinition is possible in derived classes
Parameters
- method (x : int, y : int, z : bool = false) { ... }: default parameters
- method (i : ref int) { ... }: passes the parameter by reference, that is, changing the actual value
- method (i : out int) { ... }: specifies an out parameter, used for returning values
- Values passed as ref or out parameters must be decorated with the ref or out keyword
- Write (method (3, z = true, y = 1));: parameter names can be used, after unnamed ones
Properties
public Property : string {
get { property }
set { property = value }
}
Property Accessors
- [Accessor (Sum)] mutable sum : int;: generate a public property with name Sum, getting the value from the field sum, with just a getter
- [Accessor (Sum, flags=Internal)] mutable sum : int;: change the accessibility
- [Accessor (Sum, flags=WantSetter)] mutable sum : int;: generate both getter and setter
- [Accessor] mutable sum_of_sam : int;: property name used, capitalized and underscores removed : SumOfSam
more...
Flag Accessors
For setting individual bits of enumerations fields, making boolean propeties:
[System.Flags] enum States {
| Working = 0x0001
| Married = 0x0002
| Graduate = 0x0004
}
[FlagAccessor (Working, Married, Graduate, flags=WantSetter)]
mutable state : States;
Indexers
class Table {
public Item [row : int, column : int] {
get { ... }
set { ... }
}
}
Operator Overloading
[Record]
class Vector {
[Accessor] x : double;
[Accessor] y : double;
[Accessor] z : double;
public static @+ (v1 : Vector, v2 : Vector) : Vector {
Vector (v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z)
}
}
Delegates and Events
- delegate Foo (_ : int, _ : string);: creates a new delegate type
- def f1 = Foo (method);: creates a delegate instance containing a reference to a method or function
- def f2 = Foo ( fun (i, s) { ... } );: creates a delegate containing an anonymous function
- event MyEvent : Foo;: creates an event field of delegate type Foo
- Foo += method;: adds a method to the delegate
- Foo -= method;: remove a method from the delegate
- Foo (2, "two");: invokes a delegate, that is, calls all the methods in it, in the order they were added, passing these parameters
Genericity
class Example[T] {
mutable item : T
}
- Generic functions, variants and methods use the same syntax
- def x = list.[int]();: for rare cases where generic parameter cannot be inferred
Constraints
- class Example['a] where 'a : IComparable['a] { ... }: 'a must implement or inherit the class or interface stated
Design by contract
All types needed are included in the Nemerle.Assertions namespace. By default, if contract is violated a Nemerle.AssertionException is thrown. You can change it by means of otherwise
getfoo (i : int) : int
requires i >= 0 && i < 5 otherwise throw
System.ArgumentOutOfRangeException ()
{ ... }
Preconditions
class String
{
public Substring (startIdx : int) : string
requires startIdx >= 0 && startIdx <= this.Length
{ ... }
}
ConnectTrees (requires (!tree1.Cyclic ()) tree1 : Graph,
requires (!tree2.Cyclic ()) tree2 : Graph,
e : Edge) : Graph
{ ... }
Postconditions
public Clear () : void
ensures this.IsEmpty
{ ... }
Class invariants
class Vector [T]
invariant position >= 0 && position <= arr.Length
{ ... }
- Use expose to change the invariants
expose (this) {
x += 3;
y += 3;
}
more...
Lazy evaluation
- def l = lazy (MethodWithBigCost ());: declares a variable whose value will be retrieved only when needed
- method ([Lazy] x : int, y : int) { ... }: the parameter will only be fecthed in rare cases
- The field Next will only be evaluated when requested, because or its LazyValue type:
class InfList {
public Val : int;
public Next : LazyValue [InfList];
public this (v : int) {
Val = v;
Next = lazy (InfList (v + 1));
}
}
more...
Type aliases
- type int = System.Int32;: establishes an alias for the System.Int32 type. int can be used anywhere in code with the exact same meaning as System.Int32.
Operators
- a = b;: assignment. In Nemerle, this operator doesn't return a value, so multiple assignments are not allowed
- Compound assignment is allowed: a += b;
- +: number addition, string concatenation
- -, *, /, %: number substraction, multiplication, division and modulo
- a <-> b;: swap, exchanges values of a and b
- ++, --: adds or substract 1 to the value
- +, -
Logical Operators
- ==, !=: equal, not equal
- >, <, >=, <=: greater than, less than, greater or equal to, less or equal to
- &&: short-circuiting and
- ||:short-circuiting or
- !:not
You can also use and, or, not if you open the Nemerle.English namespace
Bit Operators
- &, |, ^: bit-level and, or and xor operations
- %&&, %||, %^^: bit-level and, or and xor, returning true if the result is non-zero
- >>, <<: right and left bitwise shift
Checked and unchecked contexts
- unchecked { ... }: any number operation that goes beyond the limits of the type will silently go into an overflow
- checked { ... }: operations overflowing will throw a OverflowException
Some things inherited from C# =
- using (resource) { ... }: the resourc must implement the IDisposable interface. This block assures the resource is correctly disposed even though an exception is thrown
- lock (object) { ... }: for multithreated application. Assures that no other code executes this block if the block object is being used
Logging
All macros are inside the Nemerle.Logging namespace:
- [assembly: LogFunction (DoLog)]: specifies a logging function
- [assembly: LogFunction (DEBUG => log4net_category.Debug, TRACE => log4net_category.Info)]: specifies different logging functions for different compilation flags
- log (VERB, "example", 2): calls the logging function if the compilation flag is set, with those parameters
- whenlogging (VERB) { code }: executes the code only if the compilation flag is set
- [assembly: LogFlag (VERB, true)]: sets the compilation flag for VERB to true
more...
Assertions
- assert (condition, "message");: if condition is false, a AssertionException will be thrown, with the actual line and column number in the code file
SQL macros
- [ConfigureConnection (connectionString, name)]: applied to a class, tells the compiler about the connections used later in other SQL macros
- ExecuteNonQuery ("INSERT INTO employee VALUES ('John', 'Boo')", connection);: executes the query returning no results, via the specified connection
- def count = ExecuteScalar ("SELECT COUNT FROM employee WHERE firstname = $myparm", connection);: retrieves just one result, using the specified connection. See you can use the $ notation to substite variables
- Execute a code for every returned result, binding the column names to variables. Beware that the code is just another parameter, so you need to end parenthesis after them
ExecuteReaderLoop ("SELECT * FROM employee WHERE firstname = $myparm",
dbcon,
{
Nemerle.IO.printf ("Name: %s %s\n", firstname, lastname)
});
more...
Concurrency macros
All this macros are in Nemerle.Concurrency namespace
- async { ... }:You can execute any block of code asynchronously:
- Additionally, you can create a method that will always execute asynchronously: async Read (s : string) { ... }
Chords
Chords are sets of methods that only return a value when some exact amount of them are called in some order. This example states very well both the syntax and uses of chords:
class Buffer [T]
{
[ChordMember]
public Put (msg : T) : void;
public Get () : T
chord {
| Put => msg
}
}
More examples can be found at the SVN repository
Nemerle Standard Library
Collection classes
All in Nemerle.Collections namespace:
- ICollection['a]: extends .NET ICollection by adding contract for mapping, folding, itering...
- Hashtable['a, 'b]: extends System.Collections.Generic.Dictionary[K, V] by adding Fold, Map and Iter methods. Hastable saves items with an unique key
- Heap: saves a list of objects, allowing only to extract the first removing (ExtractFirst) or not removing (Top) it. Like usual, allows Map, Iter and Fold operations.
- LinkedList['a]: extends .NET generic LinkedList, adding some useful, list-like methods
- Queue['a]: like always, extends .NET Queue['a] by adding the useful list-like methods like Iter, Fold, Map... Queues are data structures which only allow to add or remove items at the end or the start of them
- Set['a]: an implementation of mathematical sets. It allows all normal operations on list plus:
- Sum: adds two sets yielding only one replica of each duplicated element
- Substract: returns all elements of the first set that are not in the second one
- Intersect: return the elements that appear on both sets
- Xor: return the elements that appear in one of the sets, but not in both
- Stack['a]: extends .NET Stack, a class which allows to add or remove items only on the top of them
- Tree contains an implentation of Red-Black trees, an useful structure
Array and String extensions
This methods live in Nemerle.Utility namespace, in NArray and NString classes, but can be used in arrays and string in code in a normal way. The methods adds functionality à la list for these two types.
Nemerle.IO
Contains helper functions for handling an input stream: ReadIntDigits, ReadRealDigits, ReadString, ReadChat, ConsumeWhiteSpace and CheckInput.
Option
The type option['a] allows to save values that can be null. option.None tells that it has no value. option.Some (value) saves a value.