New features - vilinski/nemerle GitHub Wiki

We list new language features for each release.

Table of Contents

Version 0.9.1, Nov 4 2005

Full changelog in the blog post.

This version brings only one new feature: indentation-based syntax.

Version 0.9.0, Sep 14 2005

Full changelog in the blog post.

Generic specifier

You can specify parameters of:

  • the generic type being created: Bar.[int] ();
  • the generic type some static member is accessed from: Bar[int].foo ();
  • the generic method: Bar.baz.[int] ();

With matching

Missing variables in matching branches can be now specified:

match (some_list) {
  // treat one element list as [x, x]
  | [x] with y = x
  | [x, y] => use x and y
  // can also set several things at once:
  | [] with (x = 7, y = 12)
  // and mix with 'when'
  | [x, _, z] when x == z with y = 17
  | [x, y, _] => use x and y
  | _ => ...
}

Partial application on steroids

In ML you could apply two argument function to a single argument and get another single argument function. We now support a similar, yet more powerful, feature:

some_fun (e1, _, e2, _)
is transformed to
fun (x, y) { some_fun (e1, x, e2, y) }
Partial application can be therefore written as f (x, _). It also works for member access:
_.foo
will be rewritten to:
fun (x) { x.foo }
The two rewrite rules can be combined:
_.foo (3, _)
``` 
will result in two argument function. Note that <code>foo (3 + _)</code>
will probably not do what's expected (it will pass a functional value
to <code>foo</code>). Use plain lambda expression for such cases.

=== Default parameters for local functions ===

This is mostly useful for accumulators, for example:
```nemerle
def rev (l, acc = []) {
  match (l) {
    | x :: xs => rev (xs, x :: acc)
    | [] => acc
  }
}
rev (l) // instead of rev (l, [])
as you can see the initial accumulator value is placed in a more intuitive place. Any expression is valid as a default parameter value for a local function, but beware that it is evaluated each time the function is called without this parameter.

#pragma warning

#pragma warning disable 10003
some_unused_function () : void {}
#pragma warning restore 10003
You can also omit warning number to disable/enable all (numbered) warnings. You can also specify several warning numbers separating them by commas.

return, break and continue

Special implicit blocks are created around functions and loops. After using Nemerle.Imperative; it is possible to use break, continue and return. More details at the blocks page.

Version 0.3.2, Jun 1 2005

Omitting variant and enums names in matching

You can now omit prefixes of variants and enums in matching, for example:

variant Foo { | A | B }
match (some_foo) {
  | A => ...
  | B => ...
}
enum Bar { | A | B }
match (some_bar) {
  | A => ...
  | B => ...
}

The restriction is that the type of some_foo need to be statically known to be Foo. If type inference cannot guess it at this point, you will have to match over (some_foo : Foo) or specify Foo.A in the first branch. Same goes to Bar. This feature is similar to switches on enums in Java 5.0.

Default parameters

public DoFoo (s : string, flag1 : bool = true,
                          flag2 : bool = false) : void
{
}

For boolean, integer and string default value the type of parameter can be omitted:

public DoFoo (s : string, flag1 = true, flag2 = false) : void
Only other allowed default value is null:
public DoFoo (x : SomeClass = null) : void

Blocks

Blocks, it is possible to construct a block you can jump out of with a value. For example:

def has_negative =
  res: {
    foreach (x in collection)
      when (x < 0)
        res (true);

    false
  }

Please consult block wiki page for details.

Tuple indexing

Tuples can be now indexed with []. It is only supported with constant integer indexes. Indexing starts at 0, so pair[1] is Pair.Second (pair).

Top-level code

  • Code can be entered at the top level, without a class and the Main method. So the classic example becomes:
System.Console.Write ("Hello marry world!\n");
That is, it put alone in the file will just compile. You can define classes, issue using declarations before the actual code. You can also define local functions with def (which gives you type inference). Yeah, we know this is only useful in write-once-run-once-throw-away kind of programs and testing, but it is nice anyway :-)

Several mutable definitions

mutable can now define more than one variable:

mutable (x, y) = (42, "kopytko");
x++; y = "ble";
mutable x = 3, y = "kopytko"; // the same
The second version does not work inside for (here;;).

Other changes

  • Nemerle.English namespace now contains "and", "or" and "not" logical operators.
  • Macros can now define textual infix and prefix operators (just like "and" above).
  • Number literal can now contain _ for readability, for example def x = 1_000_000;
  • Lazy value macros
  • Automatic get/set accessor generation
  • Arrays are no longer covariant. They haven't been in 0.2 days, and we have found it to be causing problems with type inference (see #442).
  • Tuples and lists are now serializable. Variants are deserialized properly.

Version 0.3.1, May 2 2005

There is a single nice feature that sneaked into this release, it is now possible to match inside the foreach loop directly (#436), that is:

foreach (op in ops) { | Op.A => ... | Op.B => ... }
will now work as:
foreach (op in ops) { match (op) { | Op.A => ... | Op.B => ... } }

Version 0.3.0, Apr 29 2005

Implicit conversions

The most important addition in this release are implicit conversions of several kinds.

  • We now respect user-defined op_Implicit (like the ones for Decimal type)
  • Functional values are implicitly converted to delegates.
  • when (...) 3; now gives a warning instead of error (about using implicit object->void conversion).
  • Last but not least, conversions are provided for built-in numeric types like int and long. They work much like in C#. Here is a picture about that.
This also works in a kinda special way for literals. There might be some related bugs with constant folding though.

'is' vs 'matches'

'is' can be now used where 'matches' was. 'matches' shall be considered obsolete by now. It will give a warning in the next release.

There is one drawback with this change. If you have been using a polymorphic variant (like x is Some) on the right hand side of 'matches' it won't work anymore. You either need to supply the type argument (x is Some [int]), you can use wildcard type (x is Some [_]), or make it a valid non-identifier pattern (x is Some (_), x is None ()).

For the particular Some/None you can use freshly added IsSome/IsNone properties.

From the other cute new features department

  • It is now possible to use pattern matching on properties, in addition to previous possibility of matching on fields.
  • Another nice addition are the P/Invoke methods.

Version 0.2.10, Mar 31 2005

Yet incomplete support for new(), class() and struct() generic constraints.

Version 0.2.9, Mar 22 2005

The parser and the typer which constitute more then half of the compiler) have been replaced by entirely new implementations.

Nested variant options

Variant options are now nested inside enclosing variant, so their names need to be prefixed with variant name. For example:

variant Foo { | A | B { x : int; } }
...
def x = Foo.A ();
match (some_foo) {
  | Foo.B (3) => ...
  | _ => ...
}
You can mark variant with [ExternallyVisibleOptions] to import its options outside the variant or open variant name with 'using'. More details in this thread.

See also: omitting variant prefix in matching.

[] for generic types

Generic types use now [] instead of <>. That is there is 'list [int]' not 'list <int>'. This is the second (and hopefuly last ;-) time we change it. More details in this thread.

'is' in matching

The ':' operator in patterns should from now on be only used to statically enforce type. Runtime type checks should be performed with the 'is' operator which uses the same syntax:

match (some_list) {
  | (x : int) :: xs => OverloadedFunction (x); loop (xs)
  | [] => {}
}

match (some_expr) {
  | x is Foo => ...
  | x is Bar => ...
  | _ => ...
}
Trying to use ':' or 'is' in the other context will rise warning. It will be hard error for ':' used as 'is' in future release.

The catch handler syntax has been changed to reflect change in matching:

      try {
        ...
      } catch {
        | foo is SomeException => ...
        | bar is Exception => ...
        // or | bar => ...
        // or | _ => ...
      }

New type inference engine

The type inference engine has been replaced by a new one:

  • code like this compiles fine:
    def foo (x) { x.bar () }
    List.Map (some_list, foo)
when the type of 'some_list' is known.
  • overloading resolution now works when passing functional values:
 List.Sort (some_list, string.Compare)
  • variant option's constructors have now proper type, that is there is no longer need to 'SomeVariant.Option () :> SomeVariant.Option'
  • stuff like 'array [A]' should now work (if 'A' and 'B' have a common supertype)

Other additions

  • Added <<, >>, |, ^ and & operators. %|, %^ and %& remain there.
  • It is now possible to ignore values like this: _ = ignore_me (17);
  • It is now possible to assign stuff to tuples, like this:
mutable x = 7;
mutable y = "foo";
(x, y) = (42, "bar");
  • Function parameters can be now marked 'mutable'.
  • The 'partial' modifier on classes is now supported.
  • '{ def _ = foo; }' is now allowed without the additional '()' at the end.
  • New 'throw;' expression to rethrow the exception.
  • Add 'repeat (times) body' language construct
⚠️ **GitHub.com Fallback** ⚠️