Подтвердить что ты не робот

Сравнение Nemerle и F # для функционального использования .Net

Вопрос сообщества Wiki:

В соответствии с этим вопросом: В чем преимущества использования Scala в .Net? возникает другой вопрос. Может ли кто-либо изложить сравнительные преимущества (и недостатки) Nemerle и F # для функционального развития на платформе .NET. Я только что посмотрел на Немерле. Похоже, что это разные игры в одном и том же поле, как F #, поэтому мне было интересно, какие отличия там отличаются от очевидных различий в синтаксисе и большое преимущество F # от Microsoft.

4b9b3361

Ответ 1

Ive коснулся обоих этих языков, и мои впечатления от Nemerle кратко следующие: (Я предполагаю, что большинство зрителей знакомы с F #, а Nemerle менее популярен, поэтому ради справедливости я покрою его немного больше)

  • Сообщество F # довольно большое и постоянно растет из-за большого количества блог-постов, статей и т.д. Также оно распространяется по странам. Как противоположность, энтузиасты Nemerle в основном русскоязычны и сосредоточены на RSDN.ru сайте.
  • Синтаксис Nemerle - это очень дружелюбный для разработчиков с фоном в языках типа C.
  • Nemerle (а также F #) имеет функции вывода типа. Механизм ввода типа в Nemerle привязан к телу метода (локальные функции, переменные и т.д.), Противоположный области вывода типа F #. Однако компилятор Nemerle не применяет никаких конкретных идиом написания кода, чтобы помочь механизму ввода типа.

F #

open System.Text

let l = [1; 2; 3]
let r1 = l |> List.fold(fun (sb : StringBuilder) v -> sb.Append(v).AppendLine()) (StringBuilder()) // type annotation is required on the function argument
let r2 = (StringBuilder(), l) ||> List.fold(fun sb v -> sb.Append(v).AppendLine()) //here compiler can infer type of State parameter 

Nemerle

using System.Console; 
using System.Collections.Generic; 
using System.Text; 

def l = [1,2,3]; 
def res = l.FoldLeft(StringBuilder(), (v, acc) => acc.Append(v).AppendLine()); 
WriteLine($"Result:\n$res"); 

def d = Dictionary(); // generic parameters are absent (even placeholders!!!) 
d.Add(1, "!"); 
WriteLine(d.GetType()); // System.Collections.Generic.Dictionary`2[System.Int32,System.String] 

Также вы можете заметить еще одну особенность компилятора Nemerle - он может вывести типы из дальнейшего использования. Для вывода типов F # использует подход, основанный на алгоритме Хиндли-Милнера, и пытается вывести наиболее общий тип. Nemerle, напротив, никогда не сталкивается с полиморфными типами и всегда ищет наиболее специфический тип.

F #

let addInt = (+) 5
let addString = (+) "!!!"

let run f x = f (f x) // ('T -> 'T) -> 'T -> 'T

run addInt 5
run addString "S"

Nemerle в тех же условиях выводит тип run как (int- > int) * int → int.

Подробнее о механизме вывода типа Nemerle можно найти в тезисе MSc Michal Moskal: Тип вывода с отсрочкой

  • Nemerle обладает богатыми возможностями метапрограммирования. Большинство конструкций управления языками, таких как циклы, условные выражения, поддержка LINQ, предстоящая функция синтаксического анализа включала источники С# и многие другие - все они создаются с использованием макросов. Один пример приложений макросов можно найти здесь. BTW, возможности форматирования строк с синтаксисом $ в приведенном выше примере - это также встроенный макрос.

EDIT: Добавлен немного больший образец

using System.Console;
using System.Collections.Generic;
using System.Text;

variant Expr
{
  | Const { value : double }
  | Var { name : string }
  | Operation { id : string; left : Expr; right : Expr }

  public Eval(operations : Dictionary[string, double*double -> double], context : Dictionary[string, double]) : double
  {
    match(this)
    {
        | Const (value) => value
        | Var(name) => context[name]
        | Operation(id, left, right) => 
            def f = operations[id];
            f(left.Eval(operations, context), right.Eval(operations, context))
    }
  }
}

module Program
{
    public Main() : void
    {
        def expr = 
            Expr.Operation(
                "*",
                Expr.Const(10),
                Expr.Operation(
                "+",
                Expr.Var("n"),
                Expr.Const(5)
                )
            );
        def operations = Dictionary.[string, double * double -> double]();
        operations["+"] = (x, y) => x + y;
        operations["*"] = _ * _;

        def vars = Dictionary();
        vars["n"] = 3.0;

        def result = expr.Eval(operations, vars);
        WriteLine($"Result is $result");
    }
}

Ответ 2

Я мало что знаю о Nemerle, но я думаю, что одна из его больших функций - макросы (а-ля гигенные схемы, подобные счастливым макросам, в отличие от уродливых макросов типа C). Я никогда не сталкивался с тем, что люди так много любят макросы, но опять же, я никогда не сталкивался с тем, почему люди так любят алгебраические типы данных и сопоставляют шаблоны, пока я не начал использовать F #. Поэтому я подозреваю, что если вы любите макросы, и используете .NET, то вы являетесь бешеным поклонником Nemerle.