Nemerle: Difference between revisions
Added in the list of statically typed programming languages (as described in 'Typing discipline'). |
|||
(41 intermediate revisions by 31 users not shown) | |||
Line 1: | Line 1: | ||
{{Short description|Programming language}} |
|||
{{tooshort|date=January 2013}} |
|||
{{manual|date=January 2013}} |
|||
{{Infobox programming language |
{{Infobox programming language |
||
|name = Nemerle |
|||
|logo = |
|||
|paradigm = [[Multi-paradigm programming language|Multi-paradigm]]: [[aspect-oriented programming|aspect-oriented]], [[event-driven programming|event-driven]], [[functional programming|functional]], [[generic programming|generic]], [[imperative programming|imperative]], [[metaprogramming|meta]], [[object-oriented programming|object-oriented]], [[reflective programming|reflective]] |
|||
|family = [[C Sharp (programming language)|C#]] |
|||
|designers = Kamil Skalski, Michał Moskal, Prof. Leszek Pacholski, Paweł Olszta at [[Wrocław University]] |
|||
|developer = [[JetBrains]] (formerly) <br /> RSDN |
|||
|released = {{Start date and age|2003}} |
|||
|latest release version = [https://github.com/rsdn/nemerle/downloads 1.0.0] |
|||
|latest release version = 1.2.507.0<ref>[http://nemerle.org/Downloads Nemerle 1.2.507.0]</ref> |
|||
|latest release date = {{Start date and age|2016|8|6|df=yes}} |
|||
|typing = [[static typing|static]], [[strong typing|strong]], [[inferred typing|inferred]], [[Nominative type system#Nominal subtyping|nominal]] |
|||
|typing = [[Type inference|Inferred]], [[Nominal type system|nominal]], [[type system|static]], [[strong and weak typing|strong]] |
|||
|implementations = Nemerle |
|||
|implementations = Nemerle |
|||
|dialects = |
|||
|dialects = |
|||
|influenced_by = [[C Sharp (programming language)|C#]], [[ML (programming language)|ML]], [[Lisp (programming language)|Lisp]] |
|||
|influenced_by = [[C Sharp (programming language)|C#]], [[Lisp (programming language)|Lisp]], [[ML (programming language)|ML]] |
|||
|influenced = |
|||
|influenced = |
|||
|platform = [[Common Language Infrastructure|CLI]] ([[.NET Framework|.Net]] & [[Mono (software)|Mono]]) |
|||
|platform = [[Common Language Infrastructure|CLI]] |
|||
|file ext = .n |
|||
|file ext = .n |
|||
|website = {{URL|nemerle.org}} |
|||
}} |
}} |
||
'''Nemerle''' is a [[general-purpose programming language|general-purpose]] [[ |
'''Nemerle''' is a [[general-purpose programming language|general-purpose]], [[High-level programming language|high-level]], [[static typing|statically typed]] [[programming language]] designed for platforms using the [[Common Language Infrastructure]] ([[.NET Framework|.NET]]/[[Mono (software)|Mono]]). It offers [[functional programming|functional]], [[object-oriented]], [[aspect-oriented programming|aspect-oriented]], [[reflective programming|reflective]] and [[imperative programming|imperative]] features. It has a simple [[C Sharp (programming language)|C#]]-like syntax and a powerful [[metaprogramming]] system. |
||
In June 2012, the core developers of Nemerle were hired by the [[Czech Republic|Czech]] [[software]] development company [[JetBrains]]. The team was focusing on developing Nitra, a framework to implement extant and new programming languages.<ref>{{cite web|url=https://twitter.com/orangy/status/216127804482404352 |title=Twitter / orangy: We've decided to bring Nemerle |publisher=Twitter.com |access-date=2013-09-05}}</ref><ref>{{cite web|url=http://blogs.jetbrains.com/dotnet/2012/06/jetbrains-and-nemerle/ |title=JetBrains .NET Tools Blog » JetBrains and Nemerle |publisher=Blogs.jetbrains.com |date=2012-06-27 |access-date=2013-09-05}}</ref><ref>{{cite web|url=https://groups.google.com/forum/#!topic/nemerle-en/LKkEcftHF9I |title=Google Discussiegroepen |access-date=2013-09-05}}</ref> 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. |
|||
The language was named after the Archmage Nemmerle, a character in the fantasy novel ''[[A Wizard of Earthsea]]'' by [[Ursula K. Le Guin]]. |
|||
Nemerle is named after the Archmage Nemmerle, a character in the fantasy novel ''[[A Wizard of Earthsea]]'' by [[Ursula K. Le Guin]]. |
|||
==Features== |
==Features== |
||
{{ |
{{no footnotes|section|date=September 2013}} |
||
Nemerle's most notable feature is the ability to mix [[object |
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: |
||
* strong [[type inference]] |
* strong [[type inference]] |
||
* a flexible metaprogramming subsystem (using macros) |
* a flexible metaprogramming subsystem (using [[Macro (computer science)|macros]]) |
||
* full support for [[ |
* full support for [[object-oriented programming]] (OOP), in the style of C#, [[Java (programming language)|Java]], and [[C++]] |
||
* full support for functional programming |
* full support for functional programming, in the style of [[ML (programming language)|ML]], [[OCaml]], and [[Haskell (programming language)|Haskell]], with these features: |
||
** [[higher-order |
** [[higher-order function]]s |
||
** [[pattern matching]] |
** [[pattern matching]] |
||
** [[algebraic types]] |
** [[algebraic types]] |
||
Line 38: | Line 40: | ||
** [[partial application]] of functions |
** [[partial application]] of functions |
||
The metaprogramming system allows for |
The metaprogramming system allows for great [[compiler]] extensibility, embedding [[domain-specific language]]s, [[partial evaluation]], and [[aspect-oriented programming]], taking a [[High-level programming language|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]], [[Anonymous function|lambdas]], [[extension method]]s etc. Accessing the libraries included in the .NET or Mono platforms is as easy as in C#. |
||
The language combines all [[Common Language Infrastructure|CLI]] standard features, including [[generic programming|parametric polymorphism]], [[Lambda (programming)|lambda]]s, [[extension method]]s etc. Accessing the libraries included in the [[Microsoft .NET|.NET]] or [[Mono (software)|Mono]] platforms is as easy as in C#. |
|||
===Type inference=== |
===Type inference=== |
||
< |
<syntaxhighlight lang="nemerle"> |
||
def x = 1; // int |
def x = 1; // int |
||
def myList = List(); // generic List[T], type T is deduced from the usage in the next line |
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] |
myList.Add(x); // compiler deduces type of T as int making myList type of List[int] |
||
</syntaxhighlight> |
|||
</source> |
|||
===Everything is an expression=== |
===Everything is an expression=== |
||
< |
<syntaxhighlight lang="nemerle"> |
||
def x = |
def x = |
||
{ // similar to x = 3 |
{ // similar to x = 3 |
||
Line 58: | Line 59: | ||
def x = |
def x = |
||
if (DateTime.Now.DayOfWeek == DayOfWeek.Monday) // if, using, try |
if (DateTime.Now.DayOfWeek == DayOfWeek.Monday) // if, using, try are also expressions |
||
"Monday" |
"Monday" |
||
else |
else |
||
Line 74: | Line 75: | ||
false // x = false |
false // x = false |
||
}; |
}; |
||
</syntaxhighlight> |
|||
</source> |
|||
===Tuples=== |
===Tuples=== |
||
< |
<syntaxhighlight lang="nemerle"> |
||
def k = (1, "one"); // k : (int * string) |
def k = (1, "one"); // k : (int * string) |
||
def (a, b) = k; // a = 1, b = "one" |
def (a, b) = k; // a = 1, b = "one" |
||
</syntaxhighlight> |
|||
</source> |
|||
===Pattern matching=== |
===Pattern matching=== |
||
< |
<syntaxhighlight lang="nemerle"> |
||
def result = match (number) |
def result = match (number) |
||
{ |
{ |
||
Line 91: | Line 92: | ||
| _ => "more than one" |
| _ => "more than one" |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
{{hidden|Other pattern matching examples|style = border:1px dashed gray;| |
{{hidden|Other pattern matching examples|style = border:1px dashed gray;| |
||
Type matching with variable binding: |
Type matching with variable binding: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
def check (o : object) { |
def check (o : object) { |
||
match (o) |
match (o) |
||
Line 104: | Line 105: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Tuple pattern matching: |
Tuple pattern matching: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
match (tuple) |
match (tuple) |
||
{ |
{ |
||
Line 113: | Line 114: | ||
| ( x, y ) => $"( $x, $y )" |
| ( x, y ) => $"( $x, $y )" |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Regexp matching: |
Regexp matching: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
using Nemerle.Text; |
using Nemerle.Text; |
||
regexp match (str) { |
regexp match (str) { |
||
Line 129: | Line 130: | ||
| _ => printf("default\n"); |
| _ => printf("default\n"); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
}} |
}} |
||
===Functional types and local functions=== |
===Functional types and local functions=== |
||
< |
<syntaxhighlight lang="nemerle"> |
||
using System.Console; // classes and modules (static classes) can be put in namespaces |
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 next(x) { x + 1 }; // the type of x argument and other function arguments can be deduced from usage |
||
Line 149: | Line 150: | ||
WriteLine(mult(2, 2)); // 4 |
WriteLine(mult(2, 2)); // 4 |
||
WriteLine(fibonacci(10)); // 55 |
WriteLine(fibonacci(10)); // 55 |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Variants === |
=== Variants === |
||
[[Sum type|Variants]] (called data types or sum types in SML and OCaml) are forms of expressing data of several different kinds: |
[[Sum type|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{ |
variant RgbColor { |
||
| Red |
| Red |
||
| Yellow |
| Yellow |
||
Line 164: | Line 165: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
===Metaprogramming=== |
===Metaprogramming=== |
||
Nemerle's macro system allows for |
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: |
"'''if'''" macro example: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
macro @if (cond, e1, e2) |
macro @if (cond, e1, e2) |
||
syntax ("if", "(", cond, ")", e1, Optional (";"), "else", e2) |
syntax ("if", "(", cond, ")", e1, Optional (";"), "else", e2) |
||
{ |
{ |
||
/* |
/* |
||
<[ ]> defines an area of quasi-quotation, the Nemerle compiler transforms |
<[ ]> defines an area of quasi-quotation, the Nemerle compiler transforms the code in it |
||
to an AST |
to an AST, such transformations are somewhat similar to an Expression compiling in C# |
||
*/ |
*/ |
||
<[ |
<[ |
||
Line 189: | Line 190: | ||
// using this macro in code: |
// using this macro in code: |
||
def max = if (a > b) a else b; |
def max = if (a > b) a else b; |
||
// during a compile time the upper line will be transformed to |
// during a compile time the upper line will be transformed to this: |
||
def max = match (a > b) |
def max = match (a > b) |
||
{ |
{ |
||
Line 195: | Line 196: | ||
| _ => b |
| _ => b |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Braceless syntax === |
|||
Similarly to the braceless syntax later added to [[Scala (programming language)|Scala]], Nemerle allows the programmer to optionally use a whitespace-sensitive syntax based on the [[off-side rule]], similarly to [[Python (programming language)|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 <code>\</code>: |
|||
<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 <code>#pragma indent</code> to the top of the file or use the compiler option <code>-i</code>. |
|||
== IDE == |
== IDE == |
||
Nemerle can be integrated into [[Visual Studio 2008]]. |
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<ref>[https://code.google.com/p/nemerle/downloads/list Nemerle Studio Microsoft Setup Installer] can be installed after installing [http://www.microsoft.com/downloads/en/details.aspx?FamilyID=aca38719-f449-4937-9bac-45a9f8a73822&displaylang=en Visual Studio Shell 2008 Isolated]</ref> (like [[Visual Studio Express Edition]]s) and [[SharpDevelop]] ([https://code.google.com/p/nemerle/source/browse/#svn%2Fnemerle%2Ftrunk%2Fsnippets%2Fsharpdevelop link to plugin source code]). |
||
Nemerle can be also integrated into [[Visual Studio |
Nemerle can be also integrated into [[Visual Studio]] (up until 2017) using add-ins and extensions.<ref>[http://visualstudiogallery.msdn.microsoft.com/5d93dc0a-0ce9-4b97-970c-ab1993eb934a Visual Studio 2010 add-in]</ref> |
||
==Examples== |
==Examples== |
||
===Hello, World!=== |
===Hello, World!=== |
||
The traditional [[Hello world program| |
The traditional ''[[Hello world program|Hello World!]]'' can be implemented in a more C#-like fashion: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
class Hello |
class Hello |
||
{ |
{ |
||
Line 214: | Line 311: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
or more simply: |
or more simply: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
System.Console.WriteLine("Hello, world!"); |
System.Console.WriteLine("Hello, world!"); |
||
</syntaxhighlight> |
|||
</source> |
|||
===Examples of macros=== |
===Examples of macros=== |
||
Macros allow |
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 ==== |
====String formatting ==== |
||
The string formatting macro simplifies variables to string manipulations using $ notation: |
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 = $"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 |
def s = $"$x + $y = $(x+y)"; // $(...) can be used to make calculations or access members |
||
</syntaxhighlight> |
|||
</source> |
|||
====Declarative code generation==== |
====Declarative code generation==== |
||
''StructuralEquality'', ''Memoize'', ''json'', and ''with'' are macros which generate code in compile time. |
''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. |
||
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. |
|||
< |
<syntaxhighlight lang="nemerle"> |
||
[StructuralEquality] // Implement IEquatable[Sample] .Net interface using by element comparison equality. |
[StructuralEquality] // Implement IEquatable[Sample] .Net interface using by element comparison equality. |
||
class Sample |
class Sample |
||
Line 270: | Line 366: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
====Database accessibility==== |
====Database accessibility==== |
||
Line 276: | Line 372: | ||
Using Nemerle macros for [[SQL]] you can write: |
Using Nemerle macros for [[SQL]] you can write: |
||
< |
<syntaxhighlight lang="nemerle"> |
||
ExecuteReaderLoop("SELECT firstname, lastname FROM employee WHERE firstname = $myparm", dbcon, |
ExecuteReaderLoop("SELECT firstname, lastname FROM employee WHERE firstname = $myparm", dbcon, |
||
{ |
{ |
||
WriteLine ($"Name: $firstname $lastname") |
WriteLine ($"Name: $firstname $lastname") |
||
}); |
}); |
||
</syntaxhighlight> |
|||
</source> |
|||
instead of |
instead of |
||
< |
<syntaxhighlight lang="nemerle"> |
||
string sql = "SELECT firstname, lastname FROM employee WHERE firstname = :a"; |
string sql = "SELECT firstname, lastname FROM employee WHERE firstname = :a"; |
||
using (NpgsqlCommand dbcmd = new NpgsqlCommand (sql, dbcon, dbtran)) |
using (NpgsqlCommand dbcmd = new NpgsqlCommand (sql, dbcon, dbtran)) |
||
Line 301: | Line 397: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
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. |
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. |
||
Line 308: | Line 404: | ||
With Nemerle macros you can also introduce some new syntax into the language: |
With Nemerle macros you can also introduce some new syntax into the language: |
||
<syntaxhighlight lang = "nemerle"> |
|||
'''macro''' ReverseFor (i, begin, body) |
|||
macro ReverseFor (i, begin, body) |
|||
syntax("ford", "(", i, ";", begin, ")", body) |
|||
{ |
|||
{ |
|||
<[ for ($i = $begin; $i >= 0; $i--) $body ]> |
<[ for ($i = $begin; $i >= 0; $i--) $body ]> |
||
} |
|||
</syntaxhighlight> |
|||
defines a macro introducing the ford (EXPR ; EXPR) EXPR syntax and can be used like |
defines a macro introducing the {{mono|ford (EXPR ; EXPR) EXPR}} syntax and can be used like |
||
ford (i ; n) print (i); |
ford (i ; n) print (i); |
||
Line 320: | Line 418: | ||
===Nemerle with ASP.NET=== |
===Nemerle with ASP.NET=== |
||
Nemerle can be either embedded directly into [[ASP.NET]]: |
Nemerle can be either embedded directly into [[ASP.NET]]: |
||
< |
<syntaxhighlight lang="aspx-cs"> |
||
<%@ Page Language="Nemerle" %> |
<%@ Page Language="Nemerle" %> |
||
<script runat="server"> |
<script runat="server"> |
||
Page_Load(_ : object, _ : EventArgs) : void { |
Page_Load(_ : object, _ : EventArgs) : void { |
||
Message |
Message.Text = $"You last accessed this page at: $(DateTime.Now)"; |
||
} |
} |
||
EnterBtn_Click(_ : object, _ : EventArgs) : void { |
EnterBtn_Click(_ : object, _ : EventArgs) : void { |
||
Message |
Message.Text = $"Hi $(Name.Text), welcome to ASP.NET!"; |
||
} |
} |
||
Line 344: | Line 442: | ||
</body> |
</body> |
||
</html> |
</html> |
||
</syntaxhighlight> |
|||
</source> |
|||
...Or stored in a separate file and entered with a single line: |
...Or stored in a separate file and entered with a single line: |
||
< |
<syntaxhighlight lang="aspx-cs"> |
||
<%@ Page Language="Nemerle" Src="test.n" Inherits="Test" %> |
<%@ Page Language="Nemerle" Src="test.n" Inherits="Test" %> |
||
</syntaxhighlight> |
|||
</source> |
|||
===PInvoke=== |
===PInvoke=== |
||
Nemerle can take advantage of native platform libraries. The syntax is very similar to C#'s and other |
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; |
||
using System.Runtime.InteropServices; |
using System.Runtime.InteropServices; |
||
Line 371: | Line 469: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
==References== |
==References== |
||
Line 383: | Line 481: | ||
==External links== |
==External links== |
||
*{{ |
*{{Official website|nemerle.org}} |
||
*[ |
*[https://github.com/rsdn/nemerle GitHub project and repository (new development)] |
||
*[ |
*[https://code.google.com/p/nemerle/ Google Code project and repository (old development)] |
||
*[ |
*[https://groups.google.com/group/nemerle-en Nemerle Forum] |
||
*[http://research.microsoft.com/en-us/events/sscli2005/pacholski-moskal.pdf Nemerle presentation on Microsoft Research SSCLI RFP II Capstone 2005 workshop] |
*[http://research.microsoft.com/en-us/events/sscli2005/pacholski-moskal.pdf Nemerle presentation on Microsoft Research SSCLI RFP II Capstone 2005 workshop] |
||
*[http://www.99-bottles-of-beer.net/language-nemerle-869.html Nemerle at 99 Bottles of Beer] |
*[http://www.99-bottles-of-beer.net/language-nemerle-869.html Nemerle at 99 Bottles of Beer] |
||
{{Common Language Infrastructure}} |
|||
{{DotNET}} |
|||
{{DEFAULTSORT:Nemerle}} |
|||
[[Category:Programming languages]] |
|||
[[Category:Procedural programming languages]] |
[[Category:Procedural programming languages]] |
||
[[Category:.NET programming languages]] |
[[Category:.NET programming languages]] |
||
[[Category:Object-oriented programming languages]] |
[[Category:Object-oriented programming languages]] |
||
[[Category:ML programming language family]] |
|||
[[Category:Programming languages created in 2003]] |
[[Category:Programming languages created in 2003]] |
||
[[Category:2003 software]] |
|||
[[Category:High-level programming languages]] |
|||
[[Category:Aspect-oriented programming]] |
|||
[[Category:Functional languages]] |
|||
[[Category:Statically typed programming languages]] |
Latest revision as of 11:54, 15 November 2024
Paradigm | Multi-paradigm: aspect-oriented, event-driven, functional, generic, imperative, meta, object-oriented, reflective |
---|---|
Family | C# |
Designed by | Kamil Skalski, Michał Moskal, Prof. Leszek Pacholski, Paweł Olszta at Wrocław University |
Developer | JetBrains (formerly) RSDN |
First appeared | 2003 |
Stable release | 1.2.507.0[1]
/ 6 August 2016 |
Typing discipline | Inferred, nominal, static, strong |
Platform | CLI |
Filename extensions | .n |
Website | nemerle |
Major implementations | |
Nemerle | |
Influenced by | |
C#, Lisp, ML |
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.
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
[edit]This section includes a list of references, related reading, or external links, but its sources remain unclear because it lacks inline citations. (September 2013) |
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:
- strong type inference
- a flexible metaprogramming subsystem (using macros)
- full support for object-oriented programming (OOP), in the style of C#, Java, and C++
- full support for functional programming, in the style of ML, OCaml, and Haskell, with these features:
- higher-order functions
- pattern matching
- algebraic types
- local functions
- tuples and anonymous types
- partial application of functions
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
[edit]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
[edit]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
};
Tuples
[edit]def k = (1, "one"); // k : (int * string)
def (a, b) = k; // a = 1, b = "one"
Pattern matching
[edit]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
[edit]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
Variants
[edit]Variants (called data types or sum types in SML and OCaml) are forms of expressing data of several different kinds:
variant RgbColor {
| Red
| Yellow
| Green
| Different {
red : float;
green : float;
blue : float;
}
}
Metaprogramming
[edit]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:
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
}
Braceless syntax
[edit]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:
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
}
}
could be rewritten as:
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
Notably, it is not possible to break expressions or alternative clauses in matches over multiple lines without using a backslash \
:
// 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
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
[edit]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
[edit]Hello, World!
[edit]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
[edit]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
[edit]The string formatting macro simplifies variables 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
[edit]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.
[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();
}
}
Database accessibility
[edit]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
[edit]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
[edit]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
[edit]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();
}
}
References
[edit]- ^ Nemerle 1.2.507.0
- ^ "Twitter / orangy: We've decided to bring Nemerle". Twitter.com. Retrieved 2013-09-05.
- ^ "JetBrains .NET Tools Blog » JetBrains and Nemerle". Blogs.jetbrains.com. 2012-06-27. Retrieved 2013-09-05.
- ^ "Google Discussiegroepen". Retrieved 2013-09-05.
- ^ Nemerle Studio Microsoft Setup Installer can be installed after installing Visual Studio Shell 2008 Isolated
- ^ Visual Studio 2010 add-in
Further reading
[edit]- Publications about Nemerle in RSDN Magazine, Russian official science magazine
- Moskal, Michał (27 June 2005). "Type Inference with Deferral" (PDF). Institute of Computer Science, University of Wrocław.
{{cite journal}}
: Cite journal requires|journal=
(help) - Presentation "Nemerle is notable" by Denis Rystsov
- Article "Unconventional languages for unconventional supercomputers" by Andrey Adinetz