|
We'll try here to answer some of controversial thoughts you might have after looking on Nemerle feature set.
Q: Why use CLI/.NET?
A: Mainly for interop reasons. There are number of CLI libraries and bindings out there already. There is going to be more and more.
Surely we'll loose WRT to compiled OCaml in terms of performance, at least until JIT's are made perfect, but it is easily possible to write a Gtk, GNOME, Windows GUI or even KDE application, we can embed Nemerle into ASP.NET web pages and there are more and more applications and libraries supporting .NET now. It is also possible to write libraries for other .NET languages, like C# or VB.NET.
We have also avoided significant development costs, because of this decision (no need for low-level compiler, JIT, the runtime library).
Q: Why use Nemerle and not C#?
A: Nemerle is probably going to be used in some applications, where C# would be otherwise chosen. Why one would use Nemerle and not established, well described C#?
In Nemerle you can do mostly everything you would have done in C#. ,,mostly'' refers to unsafe code and maybe some C-interfacing tricks. But of course you can do more:
Foo.Bar_long_name<Baz.Qux> x = new Foo.Bar_long_name<Baz.Qux> (10) |
def x = Foo.Bar_long_name (10) |
Q: Why use Nemerle and not F# or SML.NET?
A: F# is a .NET port of subset of OCaml. SML.NET is Standard ML '97 implementation for the .NET. Both are languages from the ML family.
We believe Nemerle is far easier to grasp for programmer who has not been exposed to ML-like languages before (due to more bracy syntax and a few other design choices). At the same time the functional capabilities provided by the three languages are mostly the same.
Nemerle is a new language. We had CLS interop in mind since the very beginning. OTOH both SML.NET and F# are ports of existing languages, with a retrofitted CLS layer. In our opinion this does not play that well together.
Q: Why dynamic types? Don't they impact performance?
A:
<sidenote>
By dynamic types we understand the fact that all values carry
runtime types. These types can be queried during runtime, and
dynamic casts can be performed, raising exceptions in case
of type mismatch.
</sidenote>
Probably yes. But dynamic types are inherent part of CLI so there is no performance reason to ban them (we would have to pay performance cost anyway). Additionally, dynamic types are useful in some contexts, like dynamic loading of classes (or rather dynamic construction of objects).
For example what static type would you give to polymorphic de-serialization function? In OCaml it has type in_channel -> 'a which is obviously wrong.
Of course there are several religious issues about dynamic typing. Our answer is very simple: you don't need dynamic types -- don't use them.
Q: What syntax extensions are good for? Programmers are writing in languages not writing languages.
A: That's not true :-) Everyone programming in had an idea how to change this funny little annoying thing in .
Of course not everybody is going to do it, but we intend to provide a library of useful language extensions along with Nemerle. For interesting examples see this page.
Macros gives you powerful tool for research in programming languages design and implementation of new ideas like Join Calculus. You need not to create entire compiler from scratch, but simple write a function transforming code and include using My.NewLanguageFeature; directive in final program.
It is possible to define functions that we're unable to encode in our type-system. Ordinary example is C-like, but type-safe printf function.
We also allow extending language syntax to some degree. However, it is quite difficult to do this The Right Way. Currently extending syntax in Nemerle is quite limited, but it gives great possibilities by ability to invoke an arbitrary macro.
This section will try to answer a few questions about the Nemerle syntax, and sometimes semantics behind it.
Q: Why does function call require ()? f x looks much better than f(x), and in ML you can use both forms.
A: Function call requires (). It looks like this:
f (x, y, z); f (x); f (); |
Form without () (i.e. f x) is not allowed.
There are some good reasons for that. The main one is that it allows for better overloading resolution (simply when looking at f (x, y) you know you need a function with 2 parameters, and it's not a partial application). Overloading is likely to occur quite frequently in CLI. Another reason is that following code will give you a parse error, not a weird typing error:
f (x) /* forgot ';' here */ g (x) |
Using this syntax it is not possible to do partial application, but see below.
Q: There is a special 'a option type in ML, which can be Some x or None and is used where a pointer, that can be null, would have been used in C-like languages. So what is null value good for? You can have option type in Nemerle too.
A: Of course you can, you even have it in standard library. It's the suggested way of handling this matter.
But think about external functions that can return references. By CLI standards they can also return null. Thus it would require to have all functions returning foo in CLI to return option (foo) in Nemerle, and you would end up using val_of function over and over again, resulting in None_value (or something) exceptions instead of Null_pointer_exception.
This is why we have null in the language. In fact it is quite common in Nemerle to have a feature just for interop reasons.
Q: Why a sequence needs to be enclosed in {}? Wouldn't it be possible to assign some priority to the ; operator and treat this as an expression?
A: It would be possible, but it's quite error-prone and misleading. In simple examples it's OK:
let x = 3 in g x; h x /* Caml */ { def x = 3; g (x); h (x) } /* Nemerle */ |
But consider the following snippet of Caml:
/* Correct */ if x > y then let x = 3 in f x; g x else h () /* Parse error */ if x > y then f 3; g 3 else h () |
Thanks to ; being used only in clear context it is not possible in Nemerle.
This issue is resolved in similar manner in OCaml Revised Syntax.
Q: Why does if require else? In OCaml one doesn't need to write else ().
A: To avoid confusing grammar ambiguities. Besides, this is a functional language, what is if expression without else?
You can also use when and unless macros for if without else or else without if.
A few explanations about how to do various things in Nemerle.
Q: How to make a partial function application?
A: You simply need to use the so called eta-long form:
def f (x, y) { ... }; def g (x) { fun (y) { f (x, y) } }; def plus5 (x) { fun (x) { 5 + x } }; |
This prevents partial application bugs, which would be common in presence of overloading.