Hacker News new | past | comments | ask | show | jobs | submit login
More functional C#
111 points by jasallen on Jan 12, 2014 | hide | past | web | favorite | 94 comments
I added this code as a comment to a thread that was almost all the way off the front page by the time I got to it. It was a response to some 'functional folks' criticizing the verbosity of c#. While you can certainly do c# the java way, you can also do it in a near functional way.

I decided to post the code as a full submission because I think c# often gets dismissed as Java copy-cat, which hasn't been true in a decade.

The code (non-destructive, no side effects) calculates square roots :

    public static void Main()
    {
        const int n = 21;

        Observable.Generate<double,double>(1, x=>true, x=> 0.5 * (x + (n/x)), x=>x )
        .Scan(new {prv = 0d, cur = 0d}, (prev, curr) => new {prv = prev.cur, cur = curr})
        .FirstAsync(_ => Math.Abs(_.cur - _.prv) < 1E-10)
        .Select(_ => _.cur)
        .Subscribe(Console.WriteLine);

        // this is just to compare values, so is not part of the solution
        Console.WriteLine(Math.Sqrt(n)); 
        Console.ReadLine();
    }
Read the more OO c# implementation that inspired me here: https://news.ycombinator.com/item?id=7044497

Read the Haskell code that inspired both here: https://news.ycombinator.com/item?id=7043943




You can write Java code which works similarly to your C# code by using RxJava: https://github.com/Netflix/RxJava

Or Python, via RxPy: https://github.com/Reactive-Extensions/RxPy

Or JavaScript, via RxJs: https://github.com/Reactive-Extensions/RxJS

Or Ruby, via Rx.rb: https://github.com/Reactive-Extensions/Rx.rb

Or Objective-C, via Rx.ObjC: https://github.com/Reactive-Extensions/Rx.ObjC

Your code is a good demonstration of how Rx works though, and it's nice to know it's becoming more popular.


Rx was invented by Microsoft, so C# is a rightful first choice for Rx examples :). That code doesn't demonstrate Rx per se, it demonstrates how lambda expressions, extension methods, anonymous types, type inference enable a succinct backwards-compatible (to some extent) functional syntax in C#.


Look at the type signatures of many LINQ and Rx methods. I would hardly say they are succint. While just using expressions can be compact, maintaining a functional library or creating functional methods in your application will be a chore in c# due to the verbosity of the type syntax (Type inference won't help you on method signatures)


But why do things "near functional" when you have F# which is fully functional?


This argument of purity of ideology reminds me more than a bit of the Salon system of French art. Unless your style was absolutely to their liking, your work was deemed refusé. Sometimes doing things in an imperative style, even with state and all the baggage that comes with it, results in easier to read and debug code.


I post a few threads down why I prefer F#, and none of my reasons are for "purity", you should check it out: https://news.ycombinator.com/item?id=7048522


Because "near functional" is sufficient most of the time and if there is no compelling reason to split your codebase among two different languages, you shouldn't do it. Not to mention that there's probably 1000 C# developers for every F# developer

Have a look at http://www.indeed.com/jobanalytics/jobtrends?q=c%23%2C+f%23&...

And someone has to maintain your near functional or functional code


The compelling reason for me is F#'s compiler is far smarter, catching entire types of bugs that the C# compiler will not. For example, if you use option types, you can almost entirely eliminate null reference exceptions, as the compiler will complain about misuse of an option. The lack of default circular references on types enforces a real layered architecture, so you can open up any F# project and read it top to bottom, with the lowest layers coming first. This post has a great explanation of that feature: http://fsharpforfunandprofit.com/posts/cyclic-dependencies/

Also, with default immutability, type providers, and less boilerplate I feel a lot more confident with the quality of the code I write, and I am able to write it faster.

Since it's possible to do full C#-style OO in F#, I personally don't see a reason to use C# at all. F# is more supporting of a multi paradigm codebase, it's safer, and requires less code to do the same things as C#. Combine that with what I would consider to be an extremely short learning curve, I am happy finding C# programmers and letting them learn F# the first week of the job.


I used to use this argument and only now I realize how flawed it was. At some point there were 1000 COBOL programmers for every <your favorite language> programmers. If you decide to go with COBOL career, you will be maintaining bad software for years.


The GP was speaking from the standpoint of the business rather than that of the developer.


The easy solution -- take a few of your best C# developers and give them two weeks to learn F# and build a small project with it.

You don't have to hire developers from outside to bring new technologies into a company. In fact, given the scarcity (i.e., demand > supply) of good developers these days, it's almost certainly going to be easier and faster to have your existing development staff learn those new technologies vs. trying to hire new developers with experience in those technologies.


This is one of the reasons I think F# is such a powerful tool. It is so simple, consistent, and safe I found it very easy to learn quickly.

I think I actually spent more time learning Entity Framework than I did learning F#, and EF still catches me with weird edge cases. Meanwhile F#'s crazy smart compiler is catching all mine ;)


Because programming languages are tools. You can take good parts of functional languages and do it in non-functional languages.


Yes. Exactly. This is like saying visual basic does classes.

Sure, it does, but why would you use it like that?


Because you're already using C# and it can?


Can't you mix C# and F# in the same project though?


Yes, but that's a bit pointless since you can do the same thing in both languages, it's just F#'s syntax is cleaner.


Often mixing them in the same project will result is much less natural code. The above is pretty straightforward.


No you can't, you can use two different projects, but it's a bad solution in most cases.


F# syntax is still a little confusing in the beginning, mostly because it does so much with so little syntax. And every time I'm using F# I seem to run into weird problems around indentation.

I like F# though. But I think it takes some getting used to, and I'm not quite there yet. :)


Keep at it, though! F# does take a bit of getting used to if you're coming from C# or Java, but it doesn't take long -- maybe a week of writing it full-time, two at most -- before you're roughly as productive in F# as you are in other languages. From there, the sky's the limit :)


1. Because my management won't let me. 2. Because nobody cares enough about F# to get the tools right (e.g. no ReSharper, no Roslyn for F# on horizon), it feels like a second class citizen even in MS land.


+1


C#'s functional side is why I actually really enjoy working with it. I get to use a nice blend of OO and functional, where each makes sense. OO more on a macro scale, organising code.


The future is to have multi-paradigm languages.

Each paradigm gets used depending on the type of problem being solved.


Hopefully, the future is having multiparadigm developers. At the moment, most developers seem to struggle with their first... most of the time without realizing it.


Scala has a lot of this, too. I've started using it because despite loving C#, the JVM is more widely supported on the PaaS providers (e.g. Heroku) than the CLR. You should check it out if you're ever in a position where JVM interop is a hard requirement.


Maybe it's strange for them to see something that is both functional and highly practical?

PS: once Roslyn get's finally released, Java will never catch up again.


No one is using Java because it has great features compared to C#. Java is essentially what C# 2.0 used to be and C# has already moved on to V5. People use Java because it's cross platform. When you write server code you want it to be able to run on whatever box instead of paying for hefty Windows hosting. With now Oracle at helm, Java is likely the worst choice for any new project.


I'm guessing Observable, Scan, FirstAsync and Subscribe are all from the Rx reactive/observable framework? I haven't seen them before.


Observable, Scan and FirstAsync are from Rx. (FirstAsync is roughly equivalent to LINQ First(), except that it doesn't block.) This particular Subscribe method is also part of Rx, but it's basically a helper method around the BCL System.IObservable<T>.Subscribe(IObserver<T>) that saves you having to implement IObserver.


Scan and Observable are part of System.Reactive the other two are I think part of System or System.Data.Entity


Absolutely - C# 3.5 introduced a beautiful suite of FP-ish features that made the language fun to write functional code with, and later versions of C# parallelized and asynced those FP-ish features.


What's the point of writing code in a functional way to end up with something that is completely unreadable?

I'd rather have code written in simple, well factored functions and classes and easy to reason about, than having to deal with such a mess of functional code.

Don't get me wrong, functional code can be very elegant and clear, but the example provided here is a huge turn off to me.


I don't like the underscore notation (I think it's foreign to C#), but other than that it's very readable to me, so I guess it's a matter of practice and (acquired) taste


While sprinkling a few expressions like this around is nice, it's quite a chore to embrace a true dataflow or similiar functionally typed design through your whole application, because the types in c# are so verbose i.e.

    public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, IScheduler scheduler)


Methods with that many arguments are probably not a very good idea anyway.


Unfortunately there's probably not a great alternative in many cases such as this


Yet, when calling that method, type inference will do its job and I will just pass in a few lamdas. What's the problem?


right, just using the method is not a problem. I'm saying it sucks if you have to write a whole bunch of methods like that because you are creating your own generators, etc...


I have read a lot of lang. wars and complaints about programming languages... but C# is one of the only languages that I can't remember reading any complaints about. None.

I must conclude, by the usual Stroustrup quote, that no one uses C#. (yes this is tongue in cheek)


You're not hanging around in the right circles then, I hear complaints about C# all the time ;).

While there's plenty of limitations and frustrations you can run into with C#, I've generally felt they were largely due to intentional tradeoffs I can understand, and fail to know a better alternative to. This makes me significantly less ranty about it, in contrast to my other daily bread and butter of C++. Even if I felt both were as limiting as each other, I'd be ranting about the latter significantly more -- simply out of a sense that "it shouldn't have to be this way".


Am currently reading "Thinking Fast and Slow" by Kahneman, this is a perfect example of a base-rate fallacy (something addressed in the book).

Absent any other evidence, one should assume the amount of complaining a language would get is about proportional to how widely it's used. So the lack of complaining (asserted by the parent) about C# might be as much a reflection on how widely it's used, than on the language itself.


There is other evidence, though. For instance, C# is currently #5 on the TIOBE programming index [0].

[0]: http://www.tiobe.com/index.php/content/paperinfo/tpci/index....


> Am currently reading "Thinking Fast and Slow" by Kahneman, this is a perfect example of a base-rate fallacy (something addressed in the book).

I disagree that Dewie's individual experience constitutes a "base-rate". If you're referring to something else as a "base-rate", you'll have to spell it our more clearly for me, as I'm having difficulty seeing how to apply it validly here.

> Absent any other evidence, one should assume the amount of complaining a language would get is about proportional to how widely it's used.

That's reasonable, and my own experiences and anecdotes don't turn out to be capital D Data. However, neither are Dewie's experiences and anecdotes. And what I would argue isn't reasonable is assuming the amount of complaining that one individual developer hears about a language we get is about proportional to how widely it's used. The data set is far too small to extrapolate that far.

My own experience is that the amount of complaining about a language I hear about varies wildly by what my peers in my communities happen to be using at the time. I went years without hearing any complaints about PHP... and then someone gets employed writing it and it spikes up to the language I hear the most complaints about. I'd be very absurd to assume that PHP went from not used very widely at all to the most used language in that same timeframe!

While I cast a wide net, my time is finite and I pay more attention to some communities than others, quite understandably biasing what I hear significantly.

> So the lack of complaining (asserted by the parent) about C# might be as much a reflection on how widely it's used, than on the language itself.

Granted, but "might be" is a far cry from "is" or "should be assumed to be". Indeed, I wouldn't suggest that "C# might generally be less rant-inducing" to be worthy of assuming either. Dewie "might be" not hanging around .NET devs, but even that's a terribly poor assumption -- I know plenty of devs who don't complain about languages I consider absolutely terrible.


Well, I use it =) C# is a language with a somewhat limited market ("Enterprise" applications running on Windows Servers, and yes, I know about Mono). And in this market, a very strict subset of C# (see: Java) is happily used. I know a lot of people who refrain from using even lambdas and implicit typing, let alone the other "fringe functional stuff", because "they make things complicated".


C# is a great language, in fact, I believe it's the best "general language", if there ever was one. The only real problem C# has is it's bad support of non-Windows platforms. As a language, it's excellent.


Xamarin


ahh no good! C# + X-Platform = #Remarkable


   C# is a language with a somewhat limited market 
   ("Enterprise" applications running on Windows Servers,
   and yes, I know about Mono)
One would think that Windows Phone - fastest growing smartphone OS - would go before Mono... geez, I make a living out of desktop C# apps (WPF). Not solely, but on a daily basis.


Fastest growing is easier to achieve when you have low market share.

Mono is significantly more important for the future of C# than Windows Phone.


You can make it even easier by pretending old versions of your mobile OS don't count. Or at least it appears you're allowed to do this if you left all your prior mobile users high & dry after promising them upgrades, twice.


"Easier" doesn't mean easy - many players to the table, we are yet to see whether Tizen or Firefox OS manage to pull that easy feat.

What makes you think Mono plays (or is about to play) such a pivotal role?


I would be interested to know what these apps are? Who buys them? Where do you sell them? I never found a decent place to sell WPF desktop apps.


I've actually worked at 2 startups using C# and been contacted by 2 others in the last year trying to poach talent. C# is popular in many contexts.


The same goes for me! My first job was at a startup that used ASP.NET with C# (with PHP for micro-sites). From there, I've worked at agencies where I've built both large sites and small sites using ASP.NET and C#.

The whole notion of .NET only being suitable for enterprise development is bullshit.


It's not that it is only ever used for enterprise, just that it seems to be mostly used for enterprise. Think of the licensing costs for visual studio, sqlserver and windows server. Sure there is the Bizspark, but it runs out, and I think most founders would be squeamish with the potential business-technical debt that would represent.

At least right now, MS is still seen (although less lately) like the Big Bad, so giving them money to use what you can get for free or near-free elsewhere seems uncool and like bad business sense.

I suspect too from my own extremely limited sample size that .NET developers make more money on average than the average of the other languages, so that is also a liability when looking for talent when you have limited cash.


Actually, in my experience, I'd say that while .NET is used in enterprise, it's mostly used by small businesses. My experience is mainly within .NET based CMS's, and I've worked for a few agencies and startups that build on .NET, sometimes amongst other things.

I've never really bought the argument that building for .NET is too expensive. Yes, it's a lot more expensive than free, but for a company it's peanuts when it guarantees the company a stable platform and a growing dev market. The only people that will be priced out are bootstrappers. I've built more small-business sites on Umbraco than I can count.


I worked professionally on VS Express for quite a while. Yes it's less convenient, but it can be done. Still a better IDE than (say) NetBeans. I know it's apples and oranges, but I'm speaking about an overall impression.


You should check out Intellij. http://www.jetbrains.com/idea/

I think its free version is still better than most paid VS editions. The $500 edition is the best IDE I've seen. And it supports basically every language but the three .NET languages.


I know, it's very good. I use Android Studio and PHPStorm, both are mutations of Idea.


"Think of the licensing costs for visual studio, sqlserver and windows server."

Think of the costs of paying your developers. Those things are a pittance compared to the cost of hiring and retaining good developers.


Shrug, your costs might be different, but 13k per developer per year is hardly a pittance compared to my salary. I'd much rather have 13k in my pocket or in awesome stuff like monitors, desk, keyboard, etc.


In what world are you paying 13k per developer for year to use Microsoft products? Top of the line MSDN sub is like ~3k, and we get good desks and monitors and keyboards and computers too. Most places don't even buy MSDN, I do fine with a <1k in software to develop on .NET.


I got that price right off their site, top line Ultimate (only slightly less feature rich then Intellij IDEA) clocks in roughly $12500 more than IDEA.

http://www.visualstudio.com/en-us/products/how-to-buy-vs

Then most drop another couple hundred to make it actually have some of the cool Intellij IDEA features by adding in Resharper. I'm not trying to hate, I use VS at work, just I can see why it's not a popular startup ecosystem.


I don't know how that price is arrived at but it's totally not realistic. I would expect to spend ~1.5K on VS2013 Professional plus associated dev. tools (R#, dotTrace etc).


Just yesterday morning (oh the timing) I shook my fists in rage after discovering the long awaited Fakes system for mocking static functions is only available in the Ultimate edition. An actual language feature, restricted to the 13k edition. Shrug, I had that in php 5 years ago...

What I don't get is: if people aren't even buying the top line IDE to use all its features, and are just buying the crappy subset IDEs, why use .NET at all? Where's the value proposition over Java/Scala? It runs on fewer architectures, the language is only mildly better than Java and certainly not better than Scala, and the long promoted IDE has less features and is exorbitantly overpriced. I just don't get it. Is it just inertia at this point? The question in my mind isn't: "why are so few startups using it?" It's "why is anyone still picking that as their business's main stack?"

I know my team is currently locked in to agreements with other companies who require it (naturally). So when a new customer wants our stuff, they have to handle it. Is that the main reason? Everyone using it is in a circle of dependence?

Oh I forgot to mention, the functionality of Fakes used to be free, but in the new iteration it no longer is, so they can squeeze a few more 13k editions.


That really cracks me up! I work in C# probably 80% of the year (python and shudder vbscript make up the remainder) and I use lambda statements, implicit typing, and anonymous functions almost every day. The Linq IEnumerable<> extensions are also pretty well indispensable for me. My biggest complaint with C# is the limitations imposed by the static typing system: anonymous functions can't be generic, so you're forced to either declare delegates or explicitly declare each of your anon signatures; and KeyValuePair<> and Tuple<> both force you into sometimes excruciatingly, comically long object declarations, eg

Tuple<string, IEnumerable<string>, IEnumerable<KeyValuePair<string, bool>>

I've come to a point where I can comfortably write functional code in the language (though I should stress that I don't write "pure" functional code; I don't fall into the camp that abhors side effects in all scenarios). Day to day, it really is a fine language to work in, notwithstanding a few warts. In all honesty though, I'd rather be working in Python or a LISP most of the time


For me, LINQ was definitely a "gateway feature" to the lisp world. If you still use C# at work, I strongly suggest checking out F#: https://news.ycombinator.com/item?id=7048522


It's in other places too. It's just hiding itself very well. For example Unity and the games that are based on it: http://en.wikipedia.org/wiki/List_of_Unity_Engine_games


You're not giving mono the credit it's due.


I think Mono is great. It's just not a big market but of course it has great potential.


>C# is one of the only languages that I can't remember reading any complaints about

I've been using C# for about 3 years now. A year or two into using it I thought I was developing fanboy syndrome so I started a list of all of the dumb quirks and pitfalls the language has. Last time I checked, there were only 3 or 4 items on the list compared my python/c++/java lists which have 1-2 orders of magnitude more quirks.

C# really is a solid language, it's just a terrible shame it had to have the Microsoft label attached to it.


Every good thing has some sort of label attached to it (look at Android now)...


It's a little bit too verbose, it doesn't have quite the flexibility or metaprogramming ability of a language like Python.

But in general it's a very solid choice. You can even get around a lot of the inefficiency of GC by careful usage of structs.


With the rise of Roslyn[0], your second argument is kinda void (metaprogramming)

I never got the verbosity argument. Verbosity comes down to the person using the language. With C#, you can be as verbose as you want to. Do you have any examples?

What kind of inefficiency are you speaking of? the CLR's GC is one of, if not the, most efficient around.

[0] http://msdn.microsoft.com/en-gb/roslyn


Speaking as a C# developer:

I do consider C# more verbose than the languages I love to look at. Think 'SelectMany', 'FirstOrDefault' and similar constructs - even if you write functional C# as much as possible, it still .. is verbose. If compared to F#, Clojure for example.

I don't think that's an issue, mostly, but that I do agree with the notion that C# is 'verbose'.


> Do you have any examples?

Sure, write a self-executing function in C#.


  ((Action)(() => Console.WriteLine("Hello")))();
or

  new Action(() => Console.WriteLine("Hello"))();
Yeah, it's verbose because you have to cast the lambda expression before executing it, but honestly I don't know any case where a self executing function can be useful in C#.


Not too bad. Actions return null though. How about a self-executing function that returns a value? This is useful for assigning values to variables. IIRC it's going to start getting more ugly from here.


    (new Func<int>(() => 2))();


But Python only supports dynamic where C# supports both static and dynamic. It's a good trade-off.


Of course it's more verbose than a dynamically typed language. Silly comparison.


An obvious complaint is that code like the OP's won't even run because it isn't pointlessly wrapped in a class ("class MyProgram").


I have 1. You can't do generic constructors for custom attributes. That's a pretty small complaint though...



Whitespace insensitivity and inability to return void in generic contexts are "critical flaws"?

Anyway, no one's saying C# is flawless. Personally, I would love the ability to declare immutable graph references.


http://hestia.typepad.com/flatlander/2012/01/action-func-voi...

I fail to see how it is an "obvious critical flaw" :)

   You have to create a separate overload that takes an Action instead of a Func, 
   and has an identical implementation except for omitting the return keyword.  
   Granted, that’s not much work for a simple helper like the above, 
   but what if it were more complicated?  
No, it's simply not true that you need "an identical implementation except for omitting the return keyword"...

Eg. this would do the trick without repeating the implementation: http://pastie.org/8628864

Just two one-line overloads as entry points.


Your solution is at least as ugly as the one mentioned in the article.

The problem is that void can't be used as a regular type identifier.

In a lot of langages (like Python, Haskell, F#, ...) there is a regular type for void. This type is often implemented as such :

  sealed struct Void {
  }
Then you can define Action<...> just as Func<Void, ...>.

As the compiler is smart enough to see there is only one kind of Void value, it can be entierly removed from the generated code and thus doesn't make your code slower.


And quite what's so ugly about it? It's hackish, but once you create these overloads, you don't need to worry about it anymore and you can call the method just as if Func<T> could be casted to Action. I don't think it can even be compared to the one suggested in the article, since it does not require "creating a separate overload with an identical implementation" (!!!), potentially copy-pasting hundreds of lines of code if the method in question was indeed "more complicated". This is ridiculous and the fact the author couldn't think of a workaround that didn't involve it baffles me.


This is a joke, right?


This is hobbyist code. It should never actually be used out in the real world. Once you make the distinction, you can better appreciate code snippets like these.


If you are going to criticize this approach to C# you are going to need to be more specific - the classic argument for this kind of thing is correctness, and against is optimization, is it the latter you are implicitly pointing out? And if so, what insight as to implementation details that you think make the solution slower?


Ah, I'm all for that. The comments confused me to thinking it wasn't simply, look how you can do it in C# (but never actually dot his).




Registration is open for Startup School 2019. Classes start July 22nd.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: