35

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))"

もっともっと (F#)

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

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

F# :

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

ネメル:

["A", "B"].Iter(x => printf("%d", x.Length))

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

ネメルレ :

[Record]
class X
  public A : string { get; }
  public B : string { get; }

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;
    }
}

そして、これは私がすでにF#に変換できない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; }

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;
    }
}

Nemerle コードの方がサポートしやすく、読みやすいことは明らかです。

@Brianそれが私が尋ねている理由です.F#でこのイーザーを作成することが本当かどうかを教えてください。

4

8 に答える 8

15

F#でこれを簡単にするのが本当かどうかを見せてください。C#も、明らかに同じにする他の方法がわからないので、私が間違っているのを見たら。

F#とC#の例はあまり簡潔ではありません。OPの例のいくつかを書き直してみましょう。

パターンマッチング

Nemerle:

match(STT)
    | 1 with st= "Summ"
    | 2 with st= "AVG" =>
        $"$st : $(summbycol(counter,STT))"

F#:

あなたのコードが何をしているのか100%わかりませんが、この答えに基づいているようです。一致式で新しい変数を作成するのは簡単ではないと思いますが、アクティブなパターンはやり過ぎだと思います。

私はこのようなコードを書きます:

let st = match stt with 1 -> "Summ" | 2 -> "Avg"
sprintf "%s ..." st

マップも機能します:

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

私も<3 ジョンの提案

let 1, st, _ | 2, _, st = stt, "Summ", "AVG"

記録

Nemerle:

[Record]
class X
  public A : string { get; }
  public B : string { get; }

F#:

type X = { A : string; B : string }

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;
    }
}

クラス

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; }

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

ここで注意すべき点がいくつかあります。

  • F#インターフェイスは、abstractキーワードを使用して定義されます。[<AbstractClass>]属性を使用して、それらを抽象クラスに変換できます。

  • インターフェイスは明示的に実装されます。通常、インターフェイスメンバーを呼び出すには、オブジェクトをインターフェイス定義にキャストする必要がありますlet x = My("a", "b"); printf "%s" (x :> IB).B。キャストを回避するには、インターフェイスメソッドをミラーリングするパブリックメンバーを作成する必要があります。

  • 仮想関数はabstract memberdefault実装でを定義します。

これらすべてのコンポーネントを組み合わせると、眼の神経に有害なクラス定義が得られます。ただし、クラスは一般的にあまり使用されないため、問題ありません。ほとんどのF#オブジェクトモデルは、ユニオンとレコードを介して定義されます。クラス使用される場合、クラス階層は深いのではなく非常にフラットであるため、C#よりもF#で頻繁に使用される継承または仮想関数は表示されません。

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;
    }
}

簡単に言えば、F#はNemerleにかなり匹敵すると思いますが、あなたはそれを学んでいるように見えます。心配しないでください。私がF#を学んでいたとき、基本的にC#をよりファンキーな構文でミラーリングした醜くてかさばるコードを書いていました。もっと慣用的に書くことができるようになるまでに少し時間がかかりました。

私は次のことをお勧めします:

  • Nemerleに精通していて、それを使用するのが好きな場合は、引き続き使用してください:)
  • F#を学びたいのであれば、あなたのプロジェクトは始めるのに良い場所だと思います。Nemerleと同じかそれ以上のF#を書くことができると思います。
  • C#も問題ありませんが、パターンマッチングやシンボル処理を頻繁に行う場合は、どちらの言語よりもC#を使用することはお勧めしません。
于 2011-01-03T19:19:56.963 に答える
12

F#とNemerleのバージョンはまったく異なります。

  1. Nemerleはクラスを定義し、F#は構造体を定義します。
  2. Nemerleは読み取り専用メンバーを定義し、F#は可変メンバーを定義します。
  3. Nemerleはパブリックプロパティを定義し、F#はパブリックフィールドを定義します。
  4. Nemerleはコンストラクターを定義しますが、F#はコンストラクターを定義しません。

F#の例に類似したNemerleコードは次のとおりです。

struct X
  mutable A : string
  mutable B : string

2番目の例はほとんど同じです:

  1. NemerleはMyのコンストラクターを定義しますが、F#はそれを定義しません。
  2. Nemerleはコンストラクターで渡された値を返すプロパティを定義し、F#は定数値でプロパティを定義します。

Nemerleバージョンは、ここのF#バージョンよりもはるかに短く明確です。

PS中括弧とインデント構文について。Nemerleは両方の構文をサポートしています。

次のいずれかを書くことができます:

class M
{
  static Main() : void
  {
    Console.WriteLine("A");
  }
}

またはインデントを使用します:

#pragma indent
class M
  static Main() : void
      Console.WriteLine("A");

または、両方のスタイルを使用することもできます。

#pragma indent
class M
  static Main() : void { Console.WriteLine("A"); }
于 2010-12-30T11:08:24.703 に答える
4

F# レコードの構文は次のとおりです。

type X = { 
    A : string
    B : string 
}

変換できないコードについて

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

type IB = 
    abstract B : string

type MyClass(a, b) = 
    inherit ABase()
        override this.A = a
    interface IB with 
        member this.B = b

パターン マッチングの例が何をしようとしているのかよくわかりませんが、F# には構文があります (探していると思います)。

match (STT) with
    | 1 when st = "Sum" -> ...
    | 2 when st = "Avg" -> ...
于 2010-12-30T15:19:35.093 に答える
3

F#のレコード構文は次のとおりです。

type X = struct
  val mutable A : string
  val mutable B : string
end

F#に変換されたコードがあります:

[<AbstractClass>] 
type ABase = 
    abstract member A : string
    // you can declare default implementation using default keyword like this:
    // default this.A with get () = "default implementation"

type IB =
    interface
        abstract member B : string
    end

type My = class
    inherit ABase
        override my.A with get() = "A"
    interface IB with
        member my.B with get() = "B"
end
于 2010-12-30T10:26:21.180 に答える
3

Sparkie によって投稿されたコード変換は、B プロパティが仮想ではなく、型 My のインスタンスで直接公開されないという点で、C# 変換に少し不誠実です (B にアクセスするには、インスタンスを IB にキャストする必要があります)。より忠実な変換を次に示します。

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

type IB =
    abstract B: string

type My(a, b) =
    inherit ABase()

    override this.A = a

    abstract B: string
    default this.B = b

    interface IB with
        member this.B = this.B

F# を初めて使用する場合の注意点: インターフェイス メンバーの実装に渡される this 参照は、宣言するクラスの型であるため、(上記の) IB の B の実装は、クラスで宣言された B プロパティを参照します。

于 2011-01-03T18:21:51.633 に答える
3

両方の言語が好きなら、それらを混ぜてみませんか? マクロを使用して Nemerle でいくつかのライブラリを構築し、それ以外はすべて F# で構築できます。それがマネージド ランタイムを使用する利点の 1 つではありませんか? :D

次に、C# や VB.NET などのより便利な言語を使用して UI (ある場合) を構築できます。

また、製品にスクリプト サポートを追加することを決定したら、IronPython/IronRuby を使用できます。

私の理解では、Nemerle IDE のサポートは VS2008 でのみ機能し (ただし、.net3.5 および 4.0 をサポートします)、F# は VS2010 と VS2008 の両方で機能するため、構文の違いに加えて、どの IDE であるかを判断する必要があると思います。使用します。

于 2011-05-27T12:24:28.017 に答える
2

別の比較。

キーワードを使用:

F#

use x = X()
use y = Y()
use z = Z()
...

ネメル:

using (o = SomeType())
  ...

using (x = X())
using (y = Y())
using (z = Z())
  ... 

文字列のフォーマット:

F#:

let a = 1
let b = "x"
sprintf "%d %s" (a + 1) b

ネメル:

def a = 1;
def b = "x";
def c = Nemerle.IO.sprintf("%d %s", a + 1, b);

文字列補間:

F# にはこの機能がありますか?

ネメル:

def a = 1;
def b = "x";
def c = $"$(a + 1) - $b"; // 0 - x

foreach キーワード: F#:

let list1 = [ 1; 5; 100; 450; 788 ]
for i in list1 do
  printfn "%d" i

let list1 = [ 1; 5; 100; 450; 788 ]
Seq.iteri (printfn "%d - %d")

let list1 = [ 1; 5; 100; 450; 788 ]
Seq.iteri (fun i x -> if i > 10 then printfn "%d - %d" i x)

let list1 = [ 1; 5; 100; 450; 788 ]
for x in list1 do
  printf "%s" (if x > 10 then printf "A"
               elif x < 10 then printf "B"
               elif "C"

ネメル:

def list1 = [ 1, 5, 100, 450, 788 ]
foreach (i in list1)
  WriteLine($"$i")

def list1 = [ 1, 5, 100, 450, 788 ]
foreach (i in list1 with index) // index has an index of item. works for any collection.
  WriteLine($"$index - $i")

def list1 = [ 1, 5, 100, 450, 788 ]
foreach (i when i > 10 in list1 with index) // Pattern in foreach
  WriteLine($"$index - $i")

def list1 = [ 1, 5, 100, 450, 788 ]
foreach (_ in list1) // Implicit match
  | i when i > 10 => WriteLine("A")
  | i when i < 10 => WriteLine("B")
  | _ => WriteLine("C")

foreach (_ in [])
  | i when i > 10 => WriteLine("A")
  | i when i < 10 => WriteLine("B")
  | _ => WriteLine("C")
otherwise // Otherwise is taken when there were no iterations
  WriteLine("X")
于 2010-12-30T12:21:25.507 に答える
2

「Nemerle コードの方がサポートしやすく、読みやすいことは明らかです。」

誰をサポートしやすいですか?

誰にとってより読みやすいですか?

あなた自身の言語の経験とあなた自身の個人的な偏見以外に、その判断は何に基づいていますか? 私は何年も C++ でコーディングしてきたので、コード ブロックを区切るために中かっこを使用しない言語は、少し直感に反するものだと思います。しかし、Lisp (または Lisp ベースの言語) でコーディングしたことがある人は、中括弧を使用するという概念が非常に奇妙であり、直感に反することに気付くでしょう。Pascal または Pascal ベースの言語でコーディングしたことがある人は、コード ブロックを区切るために "begin" と "end" を見たいと考えています。

F# や C# よりも Nemerle 構文の方がコードの理解度が高いことを証明する研究はありますか? それは、Nemerle コードが「サポートしやすく、読みやすい」ことを証明する、私が考えることができる唯一の経験的で客観的な尺度だからです。

プロの開発者にとっては、3 つの異なる構文にすぎません。特定の言語をBrainf*ckと比較している場合を除き、基本的には、どのような種類の構文に既に慣れているか、新しい構文構造をどれだけの期間習得する必要があるかという問題にすぎません。

于 2010-12-30T14:59:35.087 に答える