Nemerle

Programming language

Nemerle is a general-purpose, high-level, statically typed programming language designed for platforms using the Common Language Infrastructure (.NET/Mono). It offers functional, object-oriented, aspect-oriented, reflective and imperative features. It has a simple C#-like syntax and a powerful metaprogramming system.

Nemerle
ParadigmMulti-paradigm: aspect-oriented, event-driven, functional, generic, imperative, meta, object-oriented, reflective
FamilyC#
Designed byKamil Skalski, Michał Moskal, Prof. Leszek Pacholski, Paweł Olszta at Wrocław University
DeveloperJetBrains (formerly)
RSDN
First appeared2003; 22 years ago (2003)
Stable release
1.2.507.0[1] / 6 August 2016; 8 years ago (2016-08-06)
Typing disciplineInferred, nominal, static, strong
PlatformCLI
Filename extensions.n
Websitenemerle.org
Major implementations
Nemerle
Influenced by
C#, Lisp, ML

In June 2012, the core developers of Nemerle were hired by the Czech software development company JetBrains. The team was focusing on developing Nitra, a framework to implement extant and new programming languages.[2][3][4] Both the Nemerle language and Nitra have seemingly been abandoned or discontinued by JetBrains; Nitra has not been updated by its original creators since 2017 and Nemerle is now maintained entirely by the Russian Software Development Network, independently from JetBrains, although no major updates have been released yet and development is progressing very slowly. Neither Nemerle, nor Nitra have been mentioned or referenced by JetBrains for years.

Nemerle is named after the Archmage Nemmerle, a character in the fantasy novel A Wizard of Earthsea by Ursula K. Le Guin.

Features

Nemerle's most notable feature is the ability to mix styles of programming that are object-oriented and functional. Programs may be structured using object-oriented concepts such as classes and namespaces, while methods can (optionally) be written in a functional style. Other notable features include:

The metaprogramming system allows for great compiler extensibility, embedding domain-specific languages, partial evaluation, and aspect-oriented programming, taking a high-level approach to lift as much of the burden as possible from programmers. The language combines all Common Language Infrastructure (CLI) standard features, including parametric polymorphism, lambdas, extension methods etc. Accessing the libraries included in the .NET or Mono platforms is as easy as in C#.

Type inference

<syntaxhighlight lang="nemerle"> 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] </syntaxhighlight>

Everything is an expression

<syntaxhighlight lang="nemerle"> 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 int.Parse(someString)

       catch { | FormatException() => 0 };

def x = returnBlock :

 {
   foreach (i in [1, 2, 3])
     when (i > 2)
       returnBlock(true); // exit block (x = true)
   false // x = false
 };

</syntaxhighlight>

Tuples

<syntaxhighlight lang="nemerle"> def k = (1, "one"); // k : (int * string) def (a, b) = k; // a = 1, b = "one" </syntaxhighlight>

Pattern matching

<syntaxhighlight lang="nemerle"> def result = match (number) {

 | 0            => "zero"
 | 1            => "one"
 | x when x < 0 => "negative"
 | _            => "more than one"

} </syntaxhighlight>

Other pattern matching examples
"(?<name>(Ala

Functional types and local functions

<syntaxhighlight lang="nemerle"> using System.Console; // classes and modules (static classes) can be put in namespaces 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 fibonacci(i) {

 | 0     => 0
 | 1     => 1
 | other => fibonacci(i - 1) + fibonacci(i - 2)

};

WriteLine(next(9)); // 10 similar to "Console.WriteLine(next(9));" WriteLine(mult(2, 2)); // 4 WriteLine(fibonacci(10)); // 55 </syntaxhighlight>

Variants

Variants (called data types or sum types in SML and OCaml) are forms of expressing data of several different kinds: <syntaxhighlight lang="nemerle">

variant RgbColor {
  | Red
  | Yellow
  | Green
  | Different {
      red : float;
      green : float;
      blue : float;
    }
}

</syntaxhighlight>

Metaprogramming

Nemerle's macro system allows for creating, analysing, and modifying program code during compiling. Macros can be used in the form of a method call or as a new language construct. Many constructs within the language are implemented using macros (if, for, foreach, while, using etc.).

"if" macro example: <syntaxhighlight lang="nemerle"> macro @if (cond, e1, e2) syntax ("if", "(", cond, ")", e1, Optional (";"), "else", e2) {

 /*
   <[ ]> defines an area of quasi-quotation, the Nemerle compiler transforms the code in it 
   to an AST, 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 this: def max = match (a > b) {

 | true => a
 | _    => b

} </syntaxhighlight>

Braceless syntax

Similarly to the braceless syntax later added to Scala, Nemerle allows the programmer to optionally use a whitespace-sensitive syntax based on the off-side rule, similarly to Python.

The following curly-brace snippet:

<syntaxhighlight lang = "nemerle"> using System.Console;

[Qux] class FooBar {

 public static Main(): void {
   WriteLine("Hello")
 }
 static Foo (x: int): void {
   if (x == 3) {
     def y = x * 42;
     Foo (x)
   } else {
     [x].Map (fun (x) {
       x * 2
     })
   }
 }
 static Bar(): int {
   def foo = 2 + 7 * 13;
   foo
 }

} </syntaxhighlight>

could be rewritten as:

<syntaxhighlight lang = "nemerle"> using System.Console;

[Qux] \ class FooBar

 public static Main(): void
   WriteLine("Hello")
 static Foo (x: int): void
   if (x == 3) 
     def y = x * 42;
     Foo (x)
   else
     [x].Map (fun (x) {
       x * 2
     })
 static Bar(): int
   def foo = 2 + 7 * 13
   foo
 

</syntaxhighlight>

Notably, it is not possible to break expressions or alternative clauses in matches over multiple lines without using a backslash \:

<syntaxhighlight lang = "nemerle">

// This will not compile ...

static Bar(): int

 def foo = 2 
    + 7 
    * 13
 foo

match (s)

 | "a"
 | "aa" => 1
 | "b"
 | "bb" => 2
 | _ => 0

// But this will:

static Bar(): int

 def foo = 2 \ 
    + 7 \
    * 13
 foo

match (s)

 | "a" \
 | "aa" => 1
 | "b" \
 | "bb" => 2
 | _ => 0

</syntaxhighlight>

In order to activate this syntax, the user must add #pragma indent to the top of the file or use the compiler option -i.

IDE

Nemerle can be integrated into the integrated development environment (IDE) Visual Studio 2008. It also has a fully free IDE based on Visual Studio 2008 Shell[5] (like Visual Studio Express Editions) and SharpDevelop (link to plugin source code).

Nemerle can be also integrated into Visual Studio (up until 2017) using add-ins and extensions.[6]

Examples

Hello, World!

The traditional Hello World! can be implemented in a more C#-like fashion:

<syntaxhighlight lang="nemerle"> class Hello {

 static Main () : void
 {
   System.Console.WriteLine ("Hello, world!");
 }

} </syntaxhighlight>

or more simply:

<syntaxhighlight lang="nemerle"> System.Console.WriteLine("Hello, world!"); </syntaxhighlight>

Examples of macros

Macros allow generating boilerplate code with added static checks performed by the compiler. They reduce the amount of code that must be written by hand, make code generation safer, and allow programs to generate code with compiler checks, while keeping source code relatively small and readable.

String formatting

The string formatting macro simplifies variables to string manipulations using $ notation: <syntaxhighlight lang="nemerle"> 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 </syntaxhighlight>

Declarative code generation

StructuralEquality, Memoize, json, and with are macros which generate code in compile time. Though some of them (StructuralEquality, Memoize) can look like C# attributes, during compiling, they will be examined by the compiler and transformed to appropriate code using logic predefined by their macros.

<syntaxhighlight lang="nemerle"> [StructuralEquality] // Implement IEquatable[Sample] .Net interface using by element comparison 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 initialization macro "<-" is development of C# curly brackets object initialization

      def k = Diagnostics.Process() <- 
      {
         StartInfo <- // can init inner objects properties without ctor call
         {
             FileName = "calc.exe";
             UseShellExecute = true;
         }   
         Exited += () => WriteLine("Calc done"); // events and delegates
      }
      ReadLine();
  }

} </syntaxhighlight>

Database accessibility

Using Nemerle macros for SQL you can write:

<syntaxhighlight lang="nemerle"> ExecuteReaderLoop("SELECT firstname, lastname FROM employee WHERE firstname = $myparm", dbcon,

 {
   WriteLine ($"Name: $firstname $lastname")
 });

</syntaxhighlight>

instead of

<syntaxhighlight lang="nemerle"> 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)
    }
 }

} </syntaxhighlight>

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:

<syntaxhighlight lang = "nemerle"> macro ReverseFor (i, begin, body) syntax("ford", "(", i, ";", begin, ")", body) {

  <[ for ($i = $begin; $i >= 0; $i--) $body ]>

} </syntaxhighlight>

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: <syntaxhighlight lang="aspx-cs"> <%@ 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" />

<asp:Label ID="Message" runat="server" />

       </form>
   </body>

</html> </syntaxhighlight> ...Or stored in a separate file and entered with a single line: <syntaxhighlight lang="aspx-cs"> <%@ Page Language="Nemerle" Src="test.n" Inherits="Test" %> </syntaxhighlight>

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:

<syntaxhighlight lang="csharp"> 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();
   }

} </syntaxhighlight>

References

  1. ^ Nemerle 1.2.507.0
  2. ^ "Twitter / orangy: We've decided to bring Nemerle". Twitter.com. Retrieved 2013-09-05.
  3. ^ "JetBrains .NET Tools Blog » JetBrains and Nemerle". Blogs.jetbrains.com. 2012-06-27. Retrieved 2013-09-05.
  4. ^ "Google Discussiegroepen". Retrieved 2013-09-05.
  5. ^ Nemerle Studio Microsoft Setup Installer can be installed after installing Visual Studio Shell 2008 Isolated
  6. ^ Visual Studio 2010 add-in

Further reading

External links