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.
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:
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#.
defx=1;// intdefmyList=List();// generic List[T], type T is deduced from the usage in the next linemyList.Add(x);// compiler deduces type of T as int making myList type of List[int]
defx={// similar to x = 3defy=1;defz=2;y+z// this last statement is a block return value};defx=if(DateTime.Now.DayOfWeek==DayOfWeek.Monday)// if, using, try are also expressions"Monday"else"other day";defx=tryint.Parse(someString)catch{|FormatException()=>0};defx=returnBlock:{foreach(iin[1,2,3])when(i>2)returnBlock(true);// exit block (x = true)false// x = false};
defk=(1,"one");// k : (int * string)def(a,b)=k;// a = 1, b = "one"
defresult=match(number){|0=>"zero"|1=>"one"|xwhenx<0=>"negative"|_=>"more than one"}
Type matching with variable binding:
defcheck(o:object){match(o){|iisint=>$"An int: $i"|sisstring=>$"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:
usingNemerle.Text;regexpmatch(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");}
usingSystem.Console;// classes and modules (static classes) can be put in namespacesdefnext(x){x+1};// the type of x argument and other function arguments can be deduced from usagedefmult(x,y){x*y};deffibonacci(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));// 4WriteLine(fibonacci(10));// 55
Variants (called data types or sum types in SML and OCaml) are forms of expressing data of several different kinds:
variantRgbColor{|Red|Yellow|Green|Different{red:float;green:float;blue:float;}}
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:defmax=if(a>b)aelseb;// during a compile time the upper line will be transformed to this:defmax=match(a>b){|true=>a|_=>b}
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:
usingSystem.Console;[Qux]classFooBar{publicstaticMain():void{WriteLine("Hello")}staticFoo(x:int):void{if(x==3){defy=x*42;Foo(x)}else{[x].Map(fun(x){x*2})}}staticBar():int{deffoo=2+7*13;foo}}
could be rewritten as:
usingSystem.Console;[Qux]\ classFooBarpublicstaticMain():voidWriteLine("Hello")staticFoo(x:int):voidif(x==3)defy=x*42;Foo(x)else[x].Map(fun(x){x*2})staticBar():intdeffoo=2+7*13foo
Notably, it is not possible to break expressions or alternative clauses in matches over multiple lines without using a backslash \
:
// This will not compile ...staticBar():intdeffoo=2+7*13foomatch(s)|"a"|"aa"=>1|"b"|"bb"=>2|_=>0// But this will:staticBar():intdeffoo=2\+7\ *13foomatch(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
.
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]
The traditional Hello World! can be implemented in a more C#-like fashion:
classHello{staticMain():void{System.Console.WriteLine("Hello, world!");}}
or more simply:
System.Console.WriteLine("Hello, world!");
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.
The string formatting macro simplifies variables to string manipulations using $ notation:
defs=$"The number is $i";//insert the value of the variable i where $i is placed defs=$"$x + $y = $(x+y)";// $(...) can be used to make calculations or access members
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.classSample{[Memoize]// remember first evaluation result publicstaticSomeLongEvaluations():int{MathLib.CalculateNthPrime(10000000)}[DependencyProperty]// WPF dependency propertypublicDependencyPropertySample{get;set;}publicstaticMain():void{/* syntax macro "json" generates code: JObject.Object([("a", JValue.Number(SomeLongEvaluations())), ("b", JValue.Number(SomeLongEvaluations() + 1))])*/defjObject=json{a:SomeLongEvaluations();b:(SomeLongEvaluations()+1)}// object initialization macro "<-" is development of C# curly brackets object initializationdefk=Diagnostics.Process()<-{StartInfo<-// can init inner objects properties without ctor call{FileName="calc.exe";UseShellExecute=true;}Exited+=()=>WriteLine("Calc done");// events and delegates}ReadLine();}}
Using Nemerle macros for SQL you can write:
ExecuteReaderLoop("SELECT firstname, lastname FROM employee WHERE firstname = $myparm",dbcon,{WriteLine($"Name: $firstname$lastname")});
instead of
stringsql="SELECT firstname, lastname FROM employee WHERE firstname = :a";using(NpgsqlCommanddbcmd=newNpgsqlCommand(sql,dbcon,dbtran)){dbcmd.Parameters.Add("a",myparm);using(NpgsqlReaderreader=dbcmd.ExecuteReader()){while(reader.Read()){varfirstname=reader.GetString(0);varlastname=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.
With Nemerle macros you can also introduce some new syntax into the language:
macroReverseFor(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 can be either embedded directly into ASP.NET:
<%@PageLanguage="Nemerle"%><scriptrunat="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><formrunat="server">Pleaseenteryourname:<asp:TextBoxID="Name"runat="server"/><asp:ButtonOnClick="EnterBtn_Click"Text="Enter"runat="server"/><p><asp:LabelID="Message"runat="server"/></p></form></body></html>
...Or stored in a separate file and entered with a single line:
<%@PageLanguage="Nemerle"Src="test.n"Inherits="Test"%>
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:
usingSystem;usingSystem.Runtime.InteropServices;classPlatformInvokeTest{[DllImport("msvcrt.dll")]publicexternstaticputs(c:string):int;[DllImport("msvcrt.dll")]internalexternstatic_flushall():int;publicstaticMain():void{_=puts("Test");_=_flushall();}}
Common Intermediate Language (CIL), formerly called Microsoft Intermediate Language (MSIL) or Intermediate Language (IL), is the intermediate language binary instruction set defined within the Common Language Infrastructure (CLI) specification. CIL instructions are executed by a CIL-compatible runtime environment such as the Common Language Runtime. Languages which target the CLI compile to CIL. CIL is object-oriented, stack-based bytecode. Runtimes typically just-in-time compile CIL instructions into native code.
In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function with the value or reference to which the name was bound when the closure was created. Unlike a plain function, a closure allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.
The C preprocessor is the macro preprocessor for several computer programming languages, such as C, Objective-C, C++, and a variety of Fortran languages. The preprocessor provides inclusion of header files, macro expansions, conditional compilation, and line control.
In mathematics and computer science, a higher-order function (HOF) is a function that does at least one of the following:
The syntax of the C programming language is the set of rules governing writing of software in C. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction. C was the first widely successful high-level language for portable operating-system development.
A function pointer, also called a subroutine pointer or procedure pointer, is a pointer referencing executable code, rather than data. Dereferencing the function pointer yields the referenced function, which can be invoked and passed arguments just as in a normal function call. Such an invocation is also known as an "indirect" call, because the function is being invoked indirectly through a variable instead of directly through a fixed identifier or address.
In computer programming, foreach loop is a control flow statement for traversing items in a collection. foreach is usually used in place of a standard for loop statement. Unlike other for loop constructs, however, foreach loops usually maintain no explicit counter: they essentially say "do this to everything in this set", rather than "do this x times". This avoids potential off-by-one errors and makes code simpler to read. In object-oriented languages, an iterator, even if implicit, is often used as the means of traversal.
The syntax of Java is the set of rules defining how a Java program is written and interpreted.
In mathematics and in computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments. Support for variadic functions differs widely among programming languages.
Exception handling syntax is the set of keywords and/or structures provided by a computer programming language to allow exception handling, which separates the handling of errors that arise during a program's operation from its ordinary processes. Syntax for exception handling varies between programming languages, partly to cover semantic differences but largely to fit into each language's overall syntactic structure. Some languages do not call the relevant concept "exception handling"; others may not have direct facilities for it, but can still provide means to implement it.
The C and C++ programming languages are closely related but have many significant differences. C++ began as a fork of an early, pre-standardized C, and was designed to be mostly source-and-link compatible with C compilers of the time. Due to this, development tools for the two languages are often integrated into a single product, with the programmer able to specify C or C++ as their source language.
Haxe is a high-level cross-platform programming language and compiler that can produce applications and source code for many different computing platforms from one code-base. It is free and open-source software, released under an MIT License. The compiler, written in OCaml, is released under the GNU General Public License (GPL) version 2.
In software engineering, a fluent interface is an object-oriented API whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a domain-specific language (DSL). The term was coined in 2005 by Eric Evans and Martin Fowler.
This article describes the syntax of the C# programming language. The features described are compatible with .NET Framework and Mono.
In programming languages, a label is a sequence of characters that identifies a location within source code. In most languages, labels take the form of an identifier, often followed by a punctuation character. In many high-level languages, the purpose of a label is to act as the destination of a GOTO
statement. In assembly language, labels can be used anywhere an address can. Also in Pascal and its derived variations. Some languages, such as Fortran and BASIC, support numeric labels. Labels are also used to identify an entry point into a compiled sequence of statements.
In software engineering, the module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept.
Objective-C is a high-level general-purpose, object-oriented programming language that adds Smalltalk-style message passing (messaging) to the C programming language. Originally developed by Brad Cox and Tom Love in the early 1980s, it was selected by NeXT for its NeXTSTEP operating system. Due to Apple macOS’s direct lineage from NeXTSTEP, Objective-C was the standard language used, supported, and promoted by Apple for developing macOS and iOS applications from 1997, when Apple purchased NeXT until the introduction of the Swift language in 2014.
Nim is a general-purpose, multi-paradigm, statically typed, compiled high-level system programming language, designed and developed by a team around Andreas Rumpf. Nim is designed to be "efficient, expressive, and elegant", supporting metaprogramming, functional, message passing, procedural, and object-oriented programming styles by providing several features such as compile time code generation, algebraic data types, a foreign function interface (FFI) with C, C++, Objective-C, and JavaScript, and supporting compiling to those same languages as intermediate representations.
{{cite journal}}
: Cite journal requires |journal=
(help)