Nemerle


Nemerle es una de propósito general , de alto nivel , tipos estáticos lenguaje de programación diseñado para plataformas que utilizan el Common Language Infrastructure ( .NET / Mono ). Ofrece características funcionales , orientadas a objetos e imperativas . Tiene una sintaxis simple similar a C # y un poderoso sistema de metaprogramación . En junio de 2012, los desarrolladores principales de Nemerle fueron contratados por la empresa de desarrollo de software checa JetBrains.. El equipo se está enfocando en desarrollar Nitra, un marco para implementar lenguajes de programación nuevos y existentes. Este marco probablemente se utilizará para crear versiones futuras de Nemerle. [2] [3] [4]

Nemerle lleva el nombre del archimago Nemmerle, un personaje de la novela de fantasía A Wizard of Earthsea de Ursula K. Le Guin .

La característica más notable de Nemerle es la capacidad de mezclar estilos de programación orientados a objetos y funcionales. Los programas pueden estructurarse utilizando conceptos orientados a objetos como clases y espacios de nombres, mientras que los métodos pueden (opcionalmente) escribirse en un estilo funcional. Otras características notables incluyen:

El sistema de metaprogramación permite una gran extensibilidad del compilador , incorporando lenguajes específicos de dominio , evaluación parcial y programación orientada a aspectos , adoptando un enfoque de alto nivel para eliminar la mayor carga posible de los programadores. El lenguaje combina todas las características estándar de Common Language Infrastructure (CLI), incluido el polimorfismo paramétrico , lambdas , métodos de extensión, etc. Acceder a las bibliotecas incluidas en las plataformas .NET o Mono es tan fácil como en C #.

Inferencia de tipo

def  x  =  1 ;  // int def  myList  =  List ();  // Lista genérica [T], el tipo T se deduce del uso en la siguiente línea myList . Suma ( x );  // el compilador deduce el tipo de T como int haciendo que myList sea el tipo de List [int]

Todo es una expresion

def  x  =  {  // similar ax = 3  def  y  =  1 ;  def  z  =  2 ;  y  +  z  // esta última declaración es un valor de retorno de bloque  };def  x  =  if  ( DateTime . Now . DayOfWeek  ==  DayOfWeek . Monday )  // if, using, try son también expresiones  "Monday"  else  "other day" ;def  x  =  intente  int . Parse ( someString )  catch  {  |  FormatException ()  =>  0  };def  x  =  returnBlock  :  {  foreach  ( i  en  [ 1 ,  2 ,  3 ])  cuando  ( i  >  2 )  returnBlock ( verdadero );  // bloque de salida (x = verdadero) falso  // x = falso  };

Tuplas

def  k  =  ( 1 ,  "uno" );  // k: (int * cadena) def  ( a ,  b )  =  k ;  // a = 1, b = "uno"

La coincidencia de patrones

def  resultado  =  coincidencia  ( número ) {  |  0  =>  "cero"  |  1  =>  "uno"  |  x  cuando  x  <  0  =>  "negativo"  |  _  =>  "más de uno" }
Otros ejemplos de coincidencia de patrones

Coincidencia de tipos con vinculación variable:

def  check  ( o  :  object )  {  match  ( o )  {  |  i  es  int  =>  $ "An int: $ i "  |  s  es  cadena  =>  $ "Una cadena: $ ( s .T oUpper ()) "  |  _  =>  "Objeto de otro tipo"  } }

Coincidencia de patrones de tuplas:

coincidencia  ( tupla )  {  |  (  42 ,  _  )  =>  "42 en primera posición"  |  (  _ ,  42  )  =>  "42 en segunda posición"  |  (  x ,  y  )  =>  $ "( $ x , $ y )" }

Coincidencia de expresiones regulares:

utilizando  Nemerle . Texto ; coincidencia de expresiones regulares  ( str ) { | "a +. *" => printf ( "a \ n" ); | @ "(?  \ d +) - \ w +" => printf ( "% d \ n" , num + 3 ); | "(?  (Ala | Kasia))? ma kota" => coincidir con ( nombre ) { | Algunos ( n ) => printf ( "% s \ n" , n ) | Ninguno => printf ( "noname? \ N" ) }                               |  _  =>  printf ( "predeterminado \ n" ); }

Tipos funcionales y funciones locales

utilizando  System . Consola ;  // las clases y los módulos (clases estáticas) se pueden poner en espacios de nombres def  next ( x )  {  x  +  1  };  // el tipo de argumento x y otros argumentos de función se pueden deducir del usodef  mult ( x ,  y )  {  x  *  y  };def  fibonacci ( i ) {  |  0  =>  0  |  1  =>  1  |  otro  =>  fibonacci ( i  -  1 )  +  fibonacci ( i  -  2 ) };WriteLine ( siguiente ( 9 ));  // 10 similar a "Console.WriteLine (next (9));" WriteLine ( mult ( 2 ,  2 ));  // 4 WriteLine ( fibonacci ( 10 ));  // 55

Variantes

Las variantes (denominadas tipos de datos o tipos de suma en SML y OCaml) son formas de expresar datos de varios tipos diferentes:

 variante  RgbColor  {  |  Rojo  |  Amarillo  |  Verde  |  Diferente  {  rojo  :  flotar ;  verde  :  flotar ;  azul  :  flotar ;  }  }

Metaprogramación

El sistema de macros de Nemerle permite crear, analizar y modificar el código del programa durante la compilación. Las macros se pueden utilizar en forma de llamada a un método o como una nueva construcción de lenguaje. Muchas construcciones dentro del lenguaje se implementan usando macros (if, for, foreach, while, using, etc.).

Ejemplo de macro " si ":

macro  @if  ( cond ,  e1 ,  e2 ) syntax  ( "if" ,  "(" ,  cond ,  ")" ,  e1 ,  Optional  ( ";" ),  "else" ,  e2 ) {  / *  <[]> define una área de cuasi-comillas, el compilador de Nemerle transforma el código en  un AST, tales transformaciones son algo similares a una compilación de Expresión en C #  * /  <[  match  ( $ cond  :  bool )  {  |  verdadero  =>  $ e1  |  _  =>  $ e2  }  ]> }// usando esta macro en el código: def  max  =  if  ( a  >  b )  a  else  b ; // durante un tiempo de compilación, la línea superior se transformará en esto: def  max  =  match  ( a  >  b ) {  |  verdadero  =>  a  |  _  =>  b }

Nemerle se puede integrar en el entorno de desarrollo integrado (IDE) Visual Studio 2008 . También tiene un IDE totalmente gratuito basado en Visual Studio 2008 Shell [5] (como Visual Studio Express Editions ) y SharpDevelop ( enlace al código fuente del complemento ).

Nemerle también se puede integrar en Visual Studio 2010 mediante un complemento. [6]

¡Hola Mundo!

¡El tradicional Hello World! se puede implementar de una manera más similar a C #:

class  Hola {  static  Main  ()  :  void  {  System . Consola . WriteLine  ( "¡Hola, mundo!" );  } }

o más simplemente:

Sistema . Consola . WriteLine ( "¡Hola, mundo!" );

Ejemplos de macros

Las macros permiten generar código repetitivo con comprobaciones estáticas adicionales realizadas por el compilador. Reducen la cantidad de código que debe escribirse a mano, hacen que la generación de código sea más segura y permiten que los programas generen código con comprobaciones del compilador, manteniendo el código fuente relativamente pequeño y legible.

Formato de cadena

La macro de formato de cadena simplifica las variables a manipulaciones de cadenas usando la notación $:

def  s  =  $ "El número es $ i " ;  // inserta el valor de la variable i donde se coloca $ i def  s  =  $ " $ x + $ y = $ ( x + y ) " ;  // $ (...) se puede usar para hacer cálculos o acceder a miembros

Generación de código declarativo

StructuralEquality , Memoize , json y with son macros que generan código en tiempo de compilación. Aunque algunos de ellos ( StructuralEquality , Memoize ) pueden verse como atributos de C #, durante la compilación, el compilador los examinará y los transformará al código apropiado utilizando la lógica predefinida por sus macros.

[StructuralEquality]  // Implementar la interfaz IEquatable [Sample] .Net utilizando la igualdad de comparación de elementos. class  Sample {  [Memoize]  // recuerda el primer resultado de la evaluación  public  static  SomeLongEvaluations ()  :  int  {  MathLib . CalculateNthPrime ( 10000000 )  } [DependencyProperty]  // Propiedad de dependencia de WPF  public  DependencyPropertySample  {  get ;  establecer ;  }  public  static  Main ()  :  void  { / * macro de sintaxis "json" genera código: JObject.Object ([("a", JValue.Number (SomeLongEvaluations ())), ("b", JValue.Number (SomeLongEvaluations () + 1))]) * /  def  jObject  =  json  {  a :  SomeLongEvaluations ();  b :  ( SomeLongEvaluations ()  +  1 )}  // macro de inicialización de objeto "<-" es el desarrollo de la inicialización de objeto de corchetes en C #  def  k  =  Diagnostics . Process ()  <-  {  StartInfo  <-  // puede iniciar las propiedades de los objetos internos sin llamar a ctor  {  FileName  =  "calc.exe" ;  UseShellExecute  =  verdadero ;  }  Salido  + =  ()  =>  WriteLine ( "Calc hecho" );  // eventos y delegados  } ReadLine ();  } }

Accesibilidad a la base de datos

Usando macros de Nemerle para SQL puede escribir:

ExecuteReaderLoop ( "SELECCIONAR nombre, apellido DEL empleado DONDE nombre = $ myparm" ,  dbcon ,  {  WriteLine  ( $ "Nombre: $ nombre $ apellido " ) });  

en vez de

string  sql  =  "SELECCIONAR nombre, apellido DEL empleado DONDE nombre =: a" ; usando  ( NpgsqlCommand  dbcmd  =  new  NpgsqlCommand  ( sql ,  dbcon ,  dbtran )) {  dbcmd . Parámetros . Agregar ( "a" ,  myparm ); usando  ( NpgsqlReader  reader  =  dbcmd . ExecuteReader ())  {  while ( reader . Read ())  {  var  firstname  =  reader . GetString  ( 0 );  var  apellido  =  lector . GetString  ( 1 );  Consola . WriteLine  ( "Nombre: {0} {1}" ,  primer nombre ,  apellido )  }  } }

y esto no es solo ocultar algunas operaciones en una biblioteca, sino trabajo adicional realizado por el compilador para comprender la cadena de consulta, las variables utilizadas allí y las columnas devueltas desde la base de datos. La macro ExecuteReaderLoop generará código aproximadamente equivalente a lo que tendría que escribir manualmente. Además, se conecta a la base de datos en el momento de la compilación para comprobar que su consulta SQL realmente tiene sentido.

Nuevas construcciones de lenguaje

Con las macros de Nemerle también puede introducir una nueva sintaxis en el lenguaje:

macro ReverseFor (i, begin, body) syntax ("ford", "(", i, ";", begin, ")", body){ <[para ($ i = $ comenzar; $ i> = 0; $ i--) $ cuerpo]>}

define una macro que introduce la sintaxis EXPR de ford (EXPR; EXPR) y se puede usar como

ford (i; n) imprimir (i);

Nemerle con ASP.NET

Nemerle se puede incrustar directamente en ASP.NET :

<% @  Page  Language = "Nemerle"  %>     
runat = "server" > Por favor ingrese su nombre: ID = "Name" runat = "server" /> OnClick = "EnterBtn_Click" Text = "Enter" runat = "servidor" />

ID de etiqueta = "Mensaje" runat = "servidor" />