Hacker News new | ask | show | jobs
by MichaelGG 4074 days ago
F# is still less verbose and does far better type inference. I wrote teh same program in C# and F# (a few hundred lines of C#) and it F# had only 1/20th of the number of type annotations required.

Also C#'s statement-oriented nature just makes things ugly. Stuff like:

  Bar x;
  if (...) {
    var a = frob();
    x = Foo + a
  } else {
    x = Baz
  }
That's much nicer as a sub-block expression. It also allows you to scope things better. F# allows you to shadow variables, which comes in handy a: to avoid using an "old" variable, b: with nested lambdas.

F#'s Active Patterns are pretty damn nifty. F#'s also has deeper support for immutability. Even simple stuff like optional parameters C# gets wrong.

Overall, it's like using vim. There's some big things (like macros) that really help, but a ton of small things really do add up. I find it enjoyable to write in F#, I can be concise and write what I'm thinking. In C# I've got all this extra boilerplate that doesn't benefit me.

There's no doubt that C# can try to close the gap and certainly provide huge improvements from where they are today. But their overall approach seems to get the biggest "bang for buck" while confusing as few of their users as possible. And elegance/consistency be damned[1]. It's not a bad choice for certain projects (I dunno, maybe writing an ERP where you're adding all sorts of boring rules and need to be able to throw interns and get a known-quantity of quality) but it's hardly terrific if you've got control over your developers.

1: Look at C#'s duck typing, or type inference, or lambda expression support - they were forced in for the LINQ use case and nothing more.

1 comments

> Also C#'s statement-oriented nature just makes things ugly. Stuff like: [code]

I am not following what is bad about the example. Could you reproduce that same code in F# or whatever you're saying is better. It might help explain what you're getting at.

I think OP has something like this in mind:

  let x =
    if ... then
      let a = frob()
      Foo + a
    else Baz
`x` is never in an invalid/uninitialized state, and it's immediately clear exactly what code contributes toward computing its value.

Somewhat related, you can also define nested functions in F#, which is very convenient and tidy. No need for a pile of one-off private helpers at the same syntactic level as your public APIs - just tuck them inside the members which need them.

You can define nested functions in C# in for form of lambdas or anonymous delegates. Admittedly, it's still not quite as pretty as it could be because we don't get to use automatic type propogation (e.g. the `var` keyword).
Of course you could do many things to make C# closer to F# (I've devoted a whole library to coercing it [1]). My preferred approach would be:

    var x = ... 
        ? Foo + frob()
        : Baz;
Or to be truer to the original (using my lib):

    var x = ...
        ? map(frob(), a => Foo + a)
        : Baz;
But the idioms of the language mean that in the real world you see the ugly version with the associated risks of uninitialised variables. I applaud the C# team for the direction they're taking. I suspect C# will end up closer to Scala than it will to F#, which isn't a bad niche for it to be.

[1] https://github.com/louthy/language-ext

Agreed that C# will probably end up closer to Scala. For instance, it's already more straight-forward and elegant to simulate and use type classes/traits in C# than it is in F#.