F# vs C# vs Nemerle [closed]
Asked Answered
R

8

35

Got new project in my TODO and can't chose F# or Nemerle.

I'm currently learning F# and have some projects on Nemerle.

I like F# way , I like indent by default (also I want indent by default for nemerle2), I like many features and magic of F# but there is no macros.

The goal of F# is VS2010 and maybe (maybe) bigger developers team and it's looking like Haskell(can create light Linux programs with it and it's fun).

The goal of Nemerle is macros and I think I like some syntax of Nemerle more.

and most people just like C#...

  • So the language must be perspective
  • Syntax must be logical , easy to understand, neat and powerfull(less code)
  • It must be easy to use with .NET
  • So I already closed my self with the chose of this 3 ones.
  • I can use them all but what about chose one. It's not so easy for me.

just for example I like (Nemerle)

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

much more then (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)

Nemerle:

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

F# (hope not mistaken here):

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

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

and here is nemerle code I already can't convert to F# (so I only learning it) ...

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

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

Clearly Nemerle code is easier to support and more readable.

@Brian So that's why I'm asking , show me if that real to make this easer on F# , C# also if you see I do it wrong because I'm not sure about other ways to make clearly the same.

Retribution answered 30/12, 2010 at 9:37 Comment(5)
+1 and fav'd, I'm keen to see a case for Nemerle - it looks interesting, but so far not interesting enough to end up in the upper half of the languages-to-learn list (which is already way too long).Afterbirth
It would be interesting to see a case for F#. I can't think of any advantage to it, besides VS 2010 support.Hightower
Is there a question here? It seems as if your question is "which is better Nemerle, F# or C#?" That's a broad question and perhaps you could narrow your criteria for selection.Bead
Your choice of syntax examples suggests to me that you know very little about f# or c# syntax.Con
Also see comparison-of-nemerle-and-f-for-functional-on-netJemima
F
12

F# and Nemerle versions quite different:

  1. Nemerle defines class while F# defines struct.
  2. Nemerle defines readonly members while F# defines mutable members.
  3. Nemerle defines public properties while F# defines public fields.
  4. Nemerle defines constructor while F# doesn't define it.

Analogous Nemerle code for F# example is following:

struct X
  mutable A : string
  mutable B : string

The second example is almost the same:

  1. Nemerle defines constructor for My while F# doesn't define it.
  2. Nemerle defines Properties which return the value passed in constructor while F# defines properties with constant values.

Nemerle version is much shorter and clearer than F# version here.

P.S. About curly braces vs indent syntax. Nemerle supports both syntaxes.

You can write either:

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

Or use indent:

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

Or even use both styles !

#pragma indent
class M
  static Main() : void { Console.WriteLine("A"); }
Fruitage answered 30/12, 2010 at 11:8 Comment(0)
J
15

show me if that real to make this easer on F# , C# also if you see I do it wrong because I'm not sure about other ways to make clearly the same.

Your F# and C# examples aren't very concise. Let's rewrite some of the examples in your OP:

Pattern Matching

Nemerle:

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

F#:

I'm not 100% sure what you code is doing, but it looks like its based on this answer. I don't think there is any easy to create new variables in a match expression, but I think active patterns are overkill.

I'd write the code like this:

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

Maps work too:

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

I <3 Jon's suggestion too:

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

Records

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

Classes

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

Some things to note here:

  • F# interfaces are defined using the abstract keyword. You can turn them into abstract classes using the [<AbstractClass>] attribute.

  • Interfaces are implemented explicitly. Generally, you need to cast an object to an interface definition to invoke interface members: let x = My("a", "b"); printf "%s" (x :> IB).B. To avoid the cast, you need to create public members that mirror your interface methods.

  • Virtual functions define an abstract member with a default implementation.

You put all these components together, and you get class definitions which are harmful to the ocular nerves. But its ok since classes generally aren't used very often. Most F# object models are defined through unions and records; where classes are used, the class hierarchies are very flat instead of deep, so you don't see inheritance or virtual functions used as often in F# than 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;
    }
}

Long story short, I think F# is pretty comparable to Nemerle, but it looks like you're just learning it. Don't worry, when I was learning F#, I was writing ugly, bulky code that basically mirrored C# with a funkier syntax. It took a little while before I could write more idiomatically.

I recommend the following:

  • If you're familiar with Nemerle and like using it, continue to do so :)
  • If you want to learn F#, I think your project is a good place to start. I think you can write F# about as clean or better than your Nemerle.
  • C# is ok too, but I wouldn't prefer it over either language if you're doing lots of pattern matching or symbol processing.
Jerome answered 3/1, 2011 at 19:19 Comment(1)
Your C# code is not direct equivalent of Nemerle's Record. Nemerle creates readonly variables while C# creates read-write variable :) About inheritance it is always used in top design cause OOP is good for this.Fruitage
F
12

F# and Nemerle versions quite different:

  1. Nemerle defines class while F# defines struct.
  2. Nemerle defines readonly members while F# defines mutable members.
  3. Nemerle defines public properties while F# defines public fields.
  4. Nemerle defines constructor while F# doesn't define it.

Analogous Nemerle code for F# example is following:

struct X
  mutable A : string
  mutable B : string

The second example is almost the same:

  1. Nemerle defines constructor for My while F# doesn't define it.
  2. Nemerle defines Properties which return the value passed in constructor while F# defines properties with constant values.

Nemerle version is much shorter and clearer than F# version here.

P.S. About curly braces vs indent syntax. Nemerle supports both syntaxes.

You can write either:

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

Or use indent:

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

Or even use both styles !

#pragma indent
class M
  static Main() : void { Console.WriteLine("A"); }
Fruitage answered 30/12, 2010 at 11:8 Comment(0)
N
4

The syntax for an F# record is

type X = { 
    A : string
    B : string 
}

As for the code you can't convert

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

I'm not too sure what your pattern matching example is trying to do, but F# has the syntax (I think you're looking for)

match (STT) with
    | 1 when st = "Sum" -> ...
    | 2 when st = "Avg" -> ...
Nictitate answered 30/12, 2010 at 15:19 Comment(2)
F# specification does not indicate that records are stored inside a stack frame!Myer
@Lazin - the CLI spec doesn't indicate that structs are stored inside a stack frame either. The difference between struct and class in .NET has nothing to do with stack vs heap.Nictitate
M
3

F# have a better record syntax:

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

and there is your code, converted to 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
Myer answered 30/12, 2010 at 10:26 Comment(4)
I don't see how this is better than: [Record] struct X { mutable a : string; mutable b : string; } If anything, Nemerle syntax is more clear and concise.Hightower
I think, there is no much difference in clarity. F# syntax has its own advantages. For example type inference, powered by Hindly-Miller algorithm works globally. In Nemerle, type inference works only inside method bodies.Myer
mutable is not read only I guess ... after all , why you still doing OCalm class + end ?Retribution
Hindly-Miller inference doesn't work well with overloads. To be more precise it doesn't allow function overloading. This why Nemerle doesn't have Hindly-Miller global type inference. But has another sort of inference. It is better since it doesn't split the whole world for two types: 1. Currying support 2. No currying support. In Nemerle if you need currying you can use lambda or partial application : [1,2,3].Fold(_ + _) or CallFunc(MyFunc(1, _)) , the latest same as CallFunc(x => MyFunc(1, x)).Fruitage
S
3

The code conversion posted by Sparkie is slightly unfaithful to the C# conversion, in that the B property is not virtual and is not directly exposed on instances of type My (you have to cast the instances to IB to access B). Here's a more faithful conversion:

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

One thing to note if you're new to F#: the this reference passed to implementations of interface members is of the type of the declaring class, so (in the above) IB's implementation of B references the B property declared in the class.

Sacksen answered 3/1, 2011 at 18:21 Comment(0)
A
3

if you like both languages, why not mixing them? You can build some libraries in Nemerle using macros and others in F# for everything else. Isn't that one of the advantages of using managed runtime? :D

You can then build the UI (if any) using a more convenient language for it such as C# or VB.NET.

And once you decide adding scripting support to your product, you can use IronPython/IronRuby!

My understanding is that Nemerle IDE support is working only in VS2008 (but it supports .net3.5 and 4.0) and F# works in both VS2010 & VS2008, so besides the syntax differences, it think your decision also needs to consider that, which IDE you will be using.

Anaclinal answered 27/5, 2011 at 12:24 Comment(4)
Hi ! Welcome to the StackOverflow, glad to see you here. Nemerle fully supports VS 2010 and I'm currently using such mixing. But sometimes there is some big parts where you can't just say "here nemerle / or C# / or F# is better" and you need to chose one :) Currently I'm using F# for main purposes and C#/VB for UI but I'm really missing Nemerle! and adding small Nemerle modules >_< My desire to choose C# or VB.NET for design - pure random. But as you can see such mixing project with 5 languages in use is..You know when I will change my job, The one who will support it..He will gonna kill me!Retribution
oh yes, nemerle is fully supported in VS2010 except for the Indent mode i think, looks like that will be ready in Nemerle 2.Anaclinal
I see what you mean, the one who will support it will get mad. I wish there was an easy conversions between languages feature such as the one in SharpDevelop using NRefactory (C#, VB.NET and Boo only)Anaclinal
No idea about Nemerle 2 yet ) if we will work on indent support then you will meet it, no other ways.Retribution
F
2

Another comparison.

using keyword:

F#

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

Nemerle:

using (o = SomeType())
  ...

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

String formatting:

F#:

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

String interpolation:

Has F# this feature ?

Nemerle:

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

foreach keyword: 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"

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")
Fruitage answered 30/12, 2010 at 12:21 Comment(2)
In most cases it makes sense to use the use keyword in F# instead of the using function, in which case you don't need an explicit lambda.Streit
You are right. I forgot about use keyword.Fruitage
B
2

"Clearly Nemerle code is easier to support and more readable."

Easier to support to whom?

More readable to whom?

Upon what are you basing that judgement other than your own experience of the language and your own personal biases? I've coded in C++ for years and therefore I find any language which doesn't use curly braces to delimit code blocks a bit counter-intuitive. But other people who've coded in Lisp (or Lisp-based languages) would probably find the notion of using curly braces very odd and therefore counter-intuitive. People who've coded in Pascal or Pascal-based languages would rather see "begin" and "end" to delimit code blocks--they'd find that "easier to support and more readable".

Do you have any studies that prove that code comprehension is higher with Nemerle syntax than F# or C#? Because that would be the only empirical, objective measure I can think of which would prove that Nemerle code is "easier to support and more readable".

To the professional developer, it's just three different syntaxes. Unless you're comparing some language to Brainf*ck basically it's just a question of what sort of syntax you're already used to and how long you have to learn a new syntactic structure.

Bead answered 30/12, 2010 at 14:59 Comment(1)
More fun to me ... I'm not talking about you or someone else chose here. So but I understand your point. How could people know what do I like. But I have theory there is a things that Just better without any opinions. like "let x = 5" is better then "define some variable named x with value 5" and Nemerle record is damngod better then C# record. But there a lot of things to compare. And what I do here ? I do compare.Retribution

© 2022 - 2024 — McMap. All rights reserved.