F#vs C#vs Nemerle

cnd*_*cnd 34 .net c# f# nemerle

在我的TODO中获得了新项目,无法选择F#或Nemerle.

我目前正在学习F#并在Nemerle上有一些项目.

我喜欢F#方式,我喜欢默认缩进(我也希望默认缩进为nemerle2),我喜欢F#的许多功能和魔力,但是没有宏.

F#的目标是VS2010,也许(可能)更大的开发团队,它看起来像Haskell(可以用它创建轻松的Linux程序,它很有趣).

Nemerle的目标是宏,我想我更喜欢Nemerle的一些语法.

而且大多数人都喜欢C#......

  • 所以语言必须是透视的
  • 语法必须合乎逻辑,易于理解,整洁有力(代码少)
  • 它必须易于与.NET一起使用
  • 因此,我选择了这3个,已经关闭了自己.
  • 我可以使用它们,但选择一个.这对我来说并不容易.

就像我喜欢(Nemerle)

match(STT)
    | 1 with st= "Summ"
    | 2 with st= "AVG" =>
        $"$st : $(summbycol(counter,STT))"
Run Code Online (Sandbox Code Playgroud)

更多(F#)

let (|Let|) v e = (v, e)

match stt with 
| Let "Summ" (st, 1) 
| Let "AVG" (st, 2) -> srintf "%s ..." st
Run Code Online (Sandbox Code Playgroud)

F# :

["A"; "B"] |> List.iter (fun s  -> printfn "%d"  s.Length)
Run Code Online (Sandbox Code Playgroud)

Nemerle:

["A", "B"].Iter(x => printf("%d", x.Length))
Run Code Online (Sandbox Code Playgroud)

F#(希望不要误会):

let type X =
    let mytable a = ""
    let mytable b = ""
    new(A, B) = {
    a <- A
    b <- B }
    member X.A 
        with get  = a
    member X.B 
        with get  = a
Run Code Online (Sandbox Code Playgroud)

Nemerle:

[Record]
class X
  public A : string { get; }
  public B : string { get; }
Run Code Online (Sandbox Code Playgroud)

C# :

class X
{
    private readonly string _a;
    public string A { get { return _a; } }

    private readonly string _b;
    public string B { get { return _b; } }

    public X(string a, string b)
    {
        _a = a;
        _b = b;
    }
}
Run Code Online (Sandbox Code Playgroud)

这里是nemerle代码我已经无法转换为F#(所以我只学习它)...

abstract class ABase
    abstract public A : string { get; }

interface IB
    B : string { get; }

[Record]
class My : ABase, IB
    public override A : string { get; }
    public virtual  B : string { get; }
Run Code Online (Sandbox Code Playgroud)

与C#的比较:

abstract class ABase
{
    abstract public string A { get; }
}

interface IB
{
    string B { get; }
}

class My : ABase, IB
{
    private readonly string _a;
    public override A : string { get { return _a; } }

    private readonly string _b;
    public virtual  B : string { get { return _b; } }

    public My(string a, string b)
    {
        _a = a;
        _b = b;
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,Nemerle代码更容易支持,更易读.

@Brian所以这就是我要问的原因,告诉我是否真的可以在F#上创建这个缓动器,C#也是如果你看到我做错了因为我不确定其他方法可以做到明显相同.

Jul*_*iet 15

如果你认为我做错了,因为我不确定其他方法可以做出明显相同的事情.

你的F#和C#示例不是很简洁.让我们重写一下OP中的一些例子:

模式匹配

Nemerle:

match(STT)
    | 1 with st= "Summ"
    | 2 with st= "AVG" =>
        $"$st : $(summbycol(counter,STT))"
Run Code Online (Sandbox Code Playgroud)

F#:

我不是100%肯定你的代码正在做什么,但看起来它基于这个答案.我认为在匹配表达式中创建新变量并不容易,但我认为活动模式是过度的.

我写这样的代码:

let st = match stt with 1 -> "Summ" | 2 -> "Avg"
sprintf "%s ..." st
Run Code Online (Sandbox Code Playgroud)

地图也有效:

let sttMap = [1, "Summ"; 2, "Avg"] |> Map.ofList
sprintf "%s ..." (sttMap.[stt])
Run Code Online (Sandbox Code Playgroud)

我也是<3 乔恩的建议:

let 1, st, _ | 2, _, st = stt, "Summ", "AVG"
Run Code Online (Sandbox Code Playgroud)

记录

Nemerle:

[Record]
class X
  public A : string { get; }
  public B : string { get; }
Run Code Online (Sandbox Code Playgroud)

F#:

type X = { A : string; B : string }
Run Code Online (Sandbox Code Playgroud)

C#:

class X {
    public string A { get; private set; }
    public string B { get; private set; }

    public X(string a, string b) {
        A = a;
        B = b;
    }
}
Run Code Online (Sandbox Code Playgroud)

Nemerle

abstract class ABase
    abstract public A : string { get; }

interface IB
    B : string { get; }

[Record]
class My : ABase, IB
    public override A : string { get; }
    public virtual  B : string { get; }
Run Code Online (Sandbox Code Playgroud)

F#:

[<AbstractClass>]
type ABase() =
    abstract member A : string

type IB =
    abstract member B : string

type My(a, b) =
    inherit ABase()
    override this.A = a

    abstract member B : string
    default this.B = b
    interface IB with
        member this.B = this.B
Run Code Online (Sandbox Code Playgroud)

有些事情需要注意:

  • 使用abstract关键字定义F#接口.您可以使用该[<AbstractClass>]属性将它们转换为抽象类.

  • 接口是明确实现的.通常,您需要将对象强制转换为接口定义以调用接口成员:let x = My("a", "b"); printf "%s" (x :> IB).B.要避免强制转换,您需要创建镜像接口方法的公共成员.

  • 虚函数定义了abstract member一个default实现.

您将所有这些组件放在一起,并获得对眼神有害的类定义.但是它很好,因为类通常不经常使用.大多数F#对象模型是通过联合和记录定义的; 在使用类的地方,类层次结构非常平坦而不是深层,因此您不会看到F#中经常使用的继承或虚函数而不是C#.

C#:

abstract class ABase {
    public abstract string A { get; }
}

interface IB {
    string B { get; }
}

class My : ABase, IB {
    public override string A { get; private set; }
    public virtual string B { get; private set; }

    public My(string a, string b) {
        A = a;
        B = b;
    }
}
Run Code Online (Sandbox Code Playgroud)

长话短说,我认为F#与Nemerle非常相似,但看起来你只是在学习它.别担心,当我学习F#时,我正在编写丑陋,笨重的代码,它基本上反映了C#的语法.我花了一点时间才能写出更多的东西.

我推荐以下内容:

  • 如果您熟悉Nemerle并喜欢使用它,请继续这样做:)
  • 如果你想学习F#,我认为你的项目是一个好的开始.我认为你可以把F#写成干净或比你的Nemerle更好.
  • C#也可以,但如果您正在进行大量的模式匹配或符号处理,我不会喜欢它.

  • 您的C#代码并不等同于Nemerle的记录.Nemerle创建只读变量,而C#创建读写变量:)关于继承,它总是在顶层设计中使用,因为OOP对此有好处. (3认同)

NN_*_*NN_ 12

F#和Nemerle版本截然不同:

  1. Nemerle定义了类,而F#定义了struct.
  2. Nemerle定义了只读成员,而F#定义了可变成员.
  3. Nemerle定义公共属性,而F#定义公共字段.
  4. Nemerle定义了构造函数,而F#没有定义它.

F#示例的类似Nemerle代码如下:

struct X
  mutable A : string
  mutable B : string
Run Code Online (Sandbox Code Playgroud)

第二个例子几乎相同:

  1. Nemerle为My定义了构造函数,而F#没有定义它.
  2. Nemerle定义了Properties,它返回在构造函数中传递的值,而F#定义具有常量值的属性.

Nemerle版本比F#版本更短更清晰.

PS关于花括号vs缩进语法.Nemerle支持这两种语法.

你可以写:

class M
{
  static Main() : void
  {
    Console.WriteLine("A");
  }
}
Run Code Online (Sandbox Code Playgroud)

或者使用缩进:

#pragma indent
class M
  static Main() : void
      Console.WriteLine("A");
Run Code Online (Sandbox Code Playgroud)

甚至使用两种风格!

#pragma indent
class M
  static Main() : void { Console.WriteLine("A"); }
Run Code Online (Sandbox Code Playgroud)