Nemerle
This article needs additional citations for verification. (February 2011) |
Paradigm | multi-paradigm: metaprogramming, functional, object-oriented, imperative |
---|---|
Designed by | Kamil Skalski, Michał Moskal, Prof. Leszek Pacholski and Paweł Olszta at Wrocław University |
Stable release | Release Candidate build 9580
/ February 5, 2011 |
Typing discipline | static, strong, inferred, nominal subtyping |
Platform | CLI (.Net & Mono) |
Filename extensions | .n |
Website | http://nemerle.org |
Major implementations | |
Nemerle | |
Influenced by | |
C#, ML, Lisp |
Nemerle is a high-level statically typed programming language for the .NET (see also Mono) platform. It offers functional, object-oriented and imperative features. It has a simple C#-like syntax and a powerful metaprogramming system.
It has been named after the archmage Nemmerle from "A Wizard of Earthsea" by Ursula K. Le Guin (spelling with a single m is a design decision).
Features
Probably the most important feature of Nemerle is the ability to mix object oriented and functional programming styles. The top-level program structure is object oriented, while in the body of methods one can (but is not forced to) use functional style. This is very handy in some programming problems. The feature set includes functional values, variants and pattern matching.
Another very important feature is taking a high-level approach in all aspects of the language—trying to lift as much of the burden from the programmer as possible. Features like macros and type inference fit here.
Features that come from the functional land are variants (aka algebraic data types), pattern matching, type inference and parameter polymorphism (aka generics). The metaprogramming system allows great compiler extensibility, embedding domain specific languages, partial evaluation and aspect-oriented programming.
Last but not least, the usage of more mundane library functionality from .NET is as easy as in C#.
Type inference
def x = 1; // int
def myList = List(); // generic List[T], type T is deduced from the usage in the next line
myList.Add(x); // compiler deduces type of T as int making myList type of List[int]
Everything is an expression
def x =
{ // similar to x = 3
def y = 1;
def z = 2;
y + z // this last statement is a block return value
}
def x =
if (DateTime.Now.DayOfWeek == DayOfWeek.Monday) // if, using, try are also expressions
"Monday"
else
"other day";
def x = try
{
Int32.Parse(someString)
}
catch
{
| FormatException() => 0;
}
Tuples
def k = (1, "one"); // k : (int * string)
def (a, b) = k; // a = 1, b = "one"
Pattern matching
def result = match (number)
{
| 0 => "zero"
| 1 => "one"
| x when x < 0 => "negative"
| _ => "more than one"
}
Type matching with variable binding:
def check (o : object) {
match (o)
{
| i is int => $"An int: $i"
| s is string => $"A string: $(s.ToUpper())"
| _ => "Object of another type"
}
}
Tuple pattern matching:
match (tuple)
{
| ( 42, _ ) => "42 on first position"
| ( _, 42 ) => "42 on second position"
| ( x, y ) => $"( $x, $y )"
}
Regexp matching:
using Nemerle.Text;
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");
}
Functional types and local functions
def next(x) { x + 1 }; // the type of x argument and other function arguments can be deduced from usage
def mult(x, y) { x * y }
def fibbonacci(i)
{
| 0 => 0
| 1 => 1
| other => fibbonacci(i - 1) + fibbonacci(i - 2)
}
Console.WriteLine(next(9)); // 10
Console.WriteLine(mult(2, 2)); // 4
Console.WriteLine(fibbonacci(10)); // 55
Metaprogramming
Nemerle allows to create, analyze and modify code of a program during a compilation process using a powerfull macro system. Macros can be used in a form of a method call or even a new language construction. Most of the Nemerle language constructions are macros (if, for, foreach, while, using etc.).
"if" macro example:
macro @if (cond, e1, e2)
syntax ("if", "(", cond, ")", e1, Optional (";"), "else", e2)
{
/*
<[ ]> defines an area of quasi-quotation, the Nemerle compiler transforms a code in a such block
to an AST tree, such transformations are somewhat similar to an Expression compiling in C#
*/
<[
match ($cond : bool)
{
| true => $e1
| _ => $e2
}
]>
}
// using this macro in code:
def max = if (a > b) a else b;
// during a compile time the upper line will be transformed to the following:
def max = match (a > b)
{
| true => a
| _ => b
}
IDE
Nemerle can be integrated into Visual Studio 2008. Also it has a completely free IDE based on Visual Studio 2008 Shell[1] (like Visual Studio Express Editions) and SharpDevelop (link to plugin source code).
Examples
Hello, World!
The traditional "Hello World!" can be implemented in a more C#-like fashion:
class Hello {
static Main () : void {
System.Console.WriteLine ("Hello, world!");
}
}
or more simply:
System.Console.WriteLine("Hello, world!");
Examples of macros
Macros allow to have boilerplate code generated with additional static checks performed by the compiler. They reduce amount of hand writing, make code generation more safe and give the ability to programatically generate code while having compiler checks and keeping source code relatively small and readable.
String formatting
String formatting macro simplifies variable to string manipulations using $ notation:
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
Declarative code generation
StructuralEquality, Memoize, json and with are macros which generate code in compile time. Although some of them (StructuralEquality, Memoize) can look like C# attributes, during compile time they will be examined by the compiler and transformed to appropriate code using logic predefined by their macros.
[StructuralEquality] // Implement IEquatable[Sample] .Net interface using by element comparsion equality.
class Sample
{
[Memoize] // remember first evaluation result
public static SomeLongEvaluations() : int
{
MathLib.CalculateNthPrime(10000000)
}
[DependencyProperty] // WPF dependency property
public DependencyPropertySample { get; set; }
public static Main() : void
{
/* syntax macro "json" generates code:
JObject.Object([("a", JValue.Number(SomeLongEvaluations())), ("b", JValue.Number(SomeLongEvaluations() + 1))])
*/
def jObject = json { a: SomeLongEvaluations(); b: (SomeLongEvaluations() + 1)}
// object initalization macro "with" is development of C# curly brackets object initialization
def k = Diagnostics.Process() with
{
StartInfo with // can init inner obects properties without ctor call
{
FileName = "calc.exe";
UseShellExecute = true;
}
Exited += () => WriteLine("Calc done"); // events and delegates
}
ReadLine();
}
}
Database accessibility
For example, using Nemerle macros for SQL you can write:
ExecuteReaderLoop("SELECT firstname, lastname FROM employee WHERE firstname = $myparm", dbcon,
{
WriteLine ($"Name: $firstname $lastname")
});
instead of
string sql = "SELECT firstname, lastname FROM employee WHERE firstname = :a";
using (NpgsqlCommand dbcmd = new NpgsqlCommand (sql, dbcon, dbtran))
{
dbcmd.Parameters.Add("a", myparm);
using (NpgsqlReader reader = dbcmd.ExecuteReader())
{
while(reader.Read())
{
var firstname = reader.GetString (0);
var lastname = reader.GetString (1);
Console.WriteLine ("Name: {0} {1}", firstname, lastname)
}
}
}
and this is not just hiding some operations in a library, but additional work performed by the compiler to understand the query string, the variables used there, and the columns returned from the database. The ExecuteReaderLoop macro will generate code roughly equivalent to what you would have to type manually. Moreover, it connects to the database at compilation time to check that your SQL query really makes sense.
New language constructs
With Nemerle macros you can also introduce some new syntax into the language:
macro ReverseFor (i, begin, body) syntax ("ford", "(", i, ";", begin, ")", body) { <[ for ($i = $begin; $i >= 0; $i--) $body ]> }
defines a macro introducing the ford (EXPR ; EXPR) EXPR syntax and can be used like
ford (i ; n) print (i);
Nemerle with ASP.NET
Nemerle can be either embedded directly into ASP.NET:
<%@ Page Language="Nemerle" %>
<script runat="server">
Page_Load(_ : object, _ : EventArgs) : void {
Message.Text = $"You last accessed this page at: $(DateTime.Now)";
}
EnterBtn_Click(_ : object, _ : EventArgs) : void {
Message.Text = $"Hi $(Name.Text), welcome to ASP.NET!";
}
</script>
<html>
<body>
<form runat="server">
Please enter your name: <asp:TextBox ID="Name" runat="server" />
<asp:Button OnClick="EnterBtn_Click" Text="Enter" runat="server" />
<p><asp:Label ID="Message" runat="server" /></p>
</form>
</body>
</html>
...Or stored in a separate file and entered with a single line:
<%@ Page Language="Nemerle" Src="test.n" Inherits="Test" %>
PInvoke
Nemerle can take advantage of native platform libraries. The syntax is very similar to C#'s and other .NET languages. Here is the simplest example:
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public extern static puts(c : string) : int;
[DllImport("msvcrt.dll")]
internal extern static _flushall() : int;
public static Main() : void
{
_ = puts("Test");
_ = _flushall();
}
}
External links
- Publications about Nemerle in RSDN Magazine, Russian official science magazine
- Type Inference with Deferral, Michał Moskal
- Nemerle presentation on Microsoft Research SSCLI RFP II Capstone 2005 workshop
- Language Homepage
- Project Hosting on Google Code
- Installation Guide
- The official documentation
- Nemerle Forum
- Nemerle at 99 Bottles of Beer
- Interesting entries about Nemerle from akiramei's diary (in Japanese)
- Nemerle online REPL
Books about Nemerle
- Timpledon, Lambert M.; Markeseken, Miriam T.; Surhone, Susan F., eds. (2010). Nemerle. Betascript Publishing. p. 192. ISBN 9786130909895. Retrieved 2011-02-11. The contents of this book are from Wikipedia and other free online sources.[2]
- Books LLC, ed. (2010). Ml Programming Language Family: Ml, Standard Ml, Objective Caml, Mythryl, F Sharp, Nemerle, Alice, Standard Ml of New Jersey, Concurrent Ml. Books LLC. p. 100. ISBN 9781155461298. Retrieved 2011-02-11.
{{cite book}}
: Unknown parameter|month=
ignored (help)
References
- ^ Nemerle Studio Microsoft Setup Installer can be installed after installation of Visual Studio Shell 2008 Isolated http://
- ^ "Nemerle, Lambert M. Surhone, (9786130909895) Paperback - Barnes & Noble". Barnes & Noble. Retrieved 2011-02-11.