-
Notifications
You must be signed in to change notification settings - Fork 89
New features
We list new language features for each release.
Full changelog in the blog post.
This version brings only one new feature: indentation-based syntax.
Full changelog in the blog post.
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] ();
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
| _ => ...
}
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, _)
fun (x, y) { some_fun (e1, x, e2, y) }
f (x, _)
.
It also works for member access:
_.foo
fun (x) { x.foo }
_.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, [])
#pragma warning disable 10003
some_unused_function () : void {}
#pragma warning restore 10003
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.
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.
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
public DoFoo (x : SomeClass = null) : void
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.
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)
.
- 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");
mutable
can now define more than one variable:
mutable (x, y) = (42, "kopytko");
x++; y = "ble";
mutable x = 3, y = "kopytko"; // the same
for (here;;)
.
- 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.
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 => ... }
foreach (op in ops) { match (op) { | Op.A => ... | Op.B => ... } }
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.
'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.
- 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.
Yet incomplete support for new(), class() and struct() generic constraints.
The parser and the typer which constitute more then half of the compiler) have been replaced by entirely new implementations.
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) => ...
| _ => ...
}
[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.
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.
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 => ...
| _ => ...
}
The catch handler syntax has been changed to reflect change in matching:
try {
...
} catch {
| foo is SomeException => ...
| bar is Exception => ...
// or | bar => ...
// or | _ => ...
}
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)
- 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)
- 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