c# - एफ#बनाम सी#बनाम नेमरले




.net f# (6)

मेरे टोडो में नई परियोजना मिली और F # या Nemerle को नहीं चुना जा सकता

मैं वर्तमान में एफ # सीख रहा हूं और नेर्मल पर कुछ परियोजनाएं हैं I

मुझे एफ # तरह पसंद है, मुझे डिफ़ॉल्ट रूप से इंडेंट करना पसंद है (मैं भी निमेंले 2 के लिए डिफ़ॉल्ट रूप से इंडेंट चाहता हूं), मुझे कई विशेषताएं और F # का जादू पसंद है लेकिन कोई मैक्रो नहीं है।

एफ # का लक्ष्य VS2010 है और शायद (शायद) बड़ा डेवलपर टीम है और यह हास्केल की तरह दिख रही है (इसके साथ प्रकाश लिनक्स प्रोग्राम बना सकते हैं और यह मजेदार है)।

नेमेरेल का लक्ष्य मैक्रोज़ है और मुझे लगता है कि मुझे नीरले के कुछ सिंटैक्स पसंद हैं।

और ज्यादातर लोगों की तरह सी # ...

  • तो भाषा परिप्रेक्ष्य होना चाहिए
  • सिंटैक्स को तार्किक, समझना आसान, स्वच्छ और शक्तिशाली (कम कोड) होना चाहिए
  • .NET के साथ उपयोग करना आसान होना चाहिए
  • इसलिए मैंने पहले से ही इस 3 लोगों के चयन के साथ स्वयं को बंद कर दिया है
  • मैं उन सभी का उपयोग कर सकता हूं, लेकिन इसके बारे में क्या चुना? यह मेरे लिए इतना आसान नहीं है

बस उदाहरण के लिए मुझे पसंद है (नेमेलल)

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

बहुत अधिक (एफ #)

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

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

एफ #:

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

Nemerle:

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

एफ # (यहां गलत नहीं होने की उम्मीद है):

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

Nemerle:

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

सी# :

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 # पर परिवर्तित नहीं कर सकता (इसलिए मैं इसे सीख रहा हूं) ...

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

तुलना सी #:

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 कोड का समर्थन करने के लिए आसान है और अधिक पठनीय।

@ ब्रायन, इसलिए मैं पूछ रहा हूं, मुझे बताइए कि अगर इस एफ़र को एफ #, सी # पर बनाने के लिए असली है, तो भी अगर आप देखते हैं कि मैं इसे गलत करता हूं क्योंकि मैं स्पष्ट रूप से उसी तरह स्पष्ट करने के अन्य तरीकों के बारे में निश्चित नहीं हूं।


"स्पष्ट रूप से समर्थन करने के लिए Nemerle कोड आसान है और अधिक पठनीय।"

किससे समर्थन करना आसान है?

अधिक पढ़ने योग्य है?

आप क्या भाषा के अपने स्वयं के अनुभव और अपने स्वयं के निजी पूर्वाग्रहों के अलावा उस निर्णय पर आधारित हैं? मैंने वर्षों से सी ++ में कोडित किया है और इसलिए मुझे कोई भी भाषा मिलती है जो कोड ब्लॉक को थोड़ी सी प्रति-सहज ज्ञान युक्त करने के लिए घुंघराले ब्रेसिज़ का उपयोग नहीं करती है। लेकिन लिस्प (या लिस्प-आधारित भाषाओं) में कोडित अन्य लोगों को संभवतः घुंघराले ब्रेसिज़ का बहुत अजीब उपयोग करने की कल्पना मिलेगी और इसलिए काउंटर-सहज ज्ञान युक्त पास्कल या पास्कल-आधारित भाषाओं में कोडित लोगों ने कोड ब्लॉकों को सीमांकित करने के लिए "शुरू" और "अंत" देखना होगा - उन्हें लगता है कि "समर्थन करने के लिए आसान और अधिक पठनीय"।

क्या आपके पास कोई भी अध्ययन है जो साबित करता है कि कोड की समझ में एफ # या सी # से Nemerle सिंटैक्स के साथ अधिक है? क्योंकि यह एकमात्र अनुभवजन्य, उद्देश्य उपाय होगा जो मैं सोच सकता हूं कि यह साबित होगा कि नेमेरेल कोड "समर्थन करने के लिए आसान और अधिक पठनीय" है।

पेशेवर डेवलपर के लिए, यह सिर्फ तीन अलग वाक्यविन्यास है जब तक आप कुछ भाषा की तुलना ब्रेनफ * सीके के लिए नहीं कर रहे हैं, मूल रूप से यह सिर्फ एक प्रश्न है कि आप किस प्रकार की वाक्यविन्यास पहले से इस्तेमाल कर रहे हैं और आपको एक नया वाक्यविन्यास संरचना कैसे सीखना है


एक एफ # रिकॉर्ड के लिए सिंटैक्स है

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

एफ # का बेहतर रिकॉर्ड सिंटैक्स है:

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

और आपका कोड है, परिवर्तित एफ #:

[<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

एक और तुलना

कीवर्ड का उपयोग कर:

एफ #

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

Nemerle:

using (o = SomeType())
  ...

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

स्ट्रिंग फ़ॉर्मेटिंग:

एफ #:

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

Nemerle:

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

स्ट्रिंग प्रक्षेप:

एफ # इस सुविधा है?

Nemerle:

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

विदेशी मुद्रा कीवर्ड: एफ #:

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"

Nemerle:

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

यदि आप दोनों भाषाओं को पसंद करते हैं, तो उन्हें मिश्रण क्यों न करें? आप मेर्र्स और दूसरों के उपयोग से नीमरेल में कुछ लाइब्रेरीएं बना सकते हैं, बाकी सब के लिए एफ # में प्रबंधित रनटाइम का उपयोग करने के लाभों में से कोई एक नहीं है? : डी

इसके बाद आप सी # या वीबी.नेट जैसे अधिक सुविधाजनक भाषा का प्रयोग करके यूआई (यदि कोई हो) का निर्माण कर सकते हैं

और एक बार जब आप अपने उत्पाद को स्क्रिप्टिंग समर्थन जोड़ने का निर्णय लेते हैं, तो आप IronPython / IronRuby का उपयोग कर सकते हैं!

मेरी समझ यह है कि निमेरले आईडीई का समर्थन केवल वीएस 2008 में ही काम कर रहा है (लेकिन यह .3.3 और 4.0 का समर्थन करता है) और एफ # दोनों वीएस -2010 और वीएस -2008 में काम करता है, इसलिए सिंटैक्स मतभेदों के अलावा, यह भी लगता है कि आपका निर्णय भी उस पर विचार करने की जरूरत है, जो आईडीई आप उपयोग करेंगे


मुझे बताइए कि अगर इस एफ़र को एफ #, सी # पर बनाने के लिए असली है, तो भी अगर आप देखते हैं कि मैं इसे गलत करता हूं क्योंकि मैं स्पष्ट रूप से उसी तरह से बनाने के अन्य तरीकों के बारे में निश्चित नहीं हूं।

आपका एफ # और सी # उदाहरण बहुत संक्षिप्त नहीं हैं चलो अपने ओपी में कुछ उदाहरणों को दोबारा लिखते हैं:

पैटर्न मिलान

Nemerle:

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

एफ #:

मैं 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; }

एफ #:

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

सी#:

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

एफ #:

[<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

कुछ बातों को यहां नोट करने के लिए:

  • एफ # इंटरफेस को abstract कीवर्ड का उपयोग करके परिभाषित किया गया है। आप उन्हें [<AbstractClass>] विशेषता का उपयोग करके सार कक्षा में बदल सकते हैं

  • इंटरफेस को स्पष्ट रूप से लागू किया जाता है आम तौर पर, आपको एक इंटरफ़ेस परिभाषा के लिए किसी ऑब्जेक्ट को इंटरफ़ेस के सदस्यों को आमंत्रित करने की आवश्यकता है: let x = My("a", "b"); printf "%s" (x :> IB).B let x = My("a", "b"); printf "%s" (x :> IB).B । कलाकारों से बचने के लिए, आपको उन सार्वजनिक सदस्यों को बनाने की आवश्यकता है जो आपके इंटरफ़ेस विधियों को दर्पण करते हैं।

  • वर्चुअल फ़ंक्शंस एक abstract member को एक default कार्यान्वयन के साथ परिभाषित करता है।

आप इन सभी घटकों को एक साथ रख देते हैं, और आप कक्षा परिभाषाएं प्राप्त करते हैं जो ओक्यूलर नसों के लिए हानिकारक होती हैं। लेकिन इसके ठीक होने के बाद से कक्षाएं आम तौर पर बहुत बार उपयोग नहीं की जाती हैं अधिकांश एफ # ऑब्जेक्ट मॉडल यूनियनों और रिकॉर्ड के माध्यम से परिभाषित होते हैं; जहां वर्गों का उपयोग किया जाता है, वर्ग पदानुक्रम गहरे के बजाय बहुत सपाट होते हैं, इसलिए आपको विरासत या वर्चुअल फ़ंक्शन को अक्सर सी # की तुलना में F # में नहीं देखा जाता है।

सी#:

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

छोटी कहानी छोटी है, मुझे लगता है कि एफ # नेमेरेल के लिए बहुत ही तुलनीय है, लेकिन ऐसा लगता है कि आप अभी सीख रहे हैं। चिंता न करें, जब मैं एफ # सीख रहा था, मैं बदसूरत, भारी कोड लिख रहा था, जो कि मूल रूप से एक मजेदार वाक्यरचना के साथ सी # को दर्शाता है। इससे पहले कि मैं और idiomatically अधिक लिख सकता है इससे पहले थोड़ी देर ली।

मैं निम्नलिखित सुझाव देता हूं:

  • यदि आप Nemerle से परिचित हैं और इसे इस्तेमाल करना पसंद करते हैं, तो ऐसा करना जारी रखें :)
  • अगर आप एफ # सीखना चाहते हैं, तो मुझे लगता है कि आपकी परियोजना शुरू करने के लिए एक अच्छी जगह है। मुझे लगता है कि आप एफ # को अपने निमेरल से साफ या बेहतर के रूप में लिख सकते हैं
  • सी # भी ठीक है, लेकिन मैं इसे किसी भी भाषा पर पसंद नहीं करता यदि आप बहुत सारे पैटर्न मिलान या प्रतीक प्रसंस्करण कर रहे हैं।




nemerle