3 ms·
In corporate, especially in MS shops, to modify an old adage, "Nobody ever got fired for choosing C#". For side projects, I'd imagine most people working on th
by daxfohl 9y ago
In corporate, especially in MS shops, to modify an old adage, "Nobody ever got fired for choosing C#". For side projects, I'd imagine most people working on those would rather do something not Microsoft-specific.
For me, I've done plenty of freelance projects in F# over the past few years and enjoy it. I've done about two years worth of projects in Clojure, and about a half year in Scala, and F# was the nicest of the three for me.
It takes a while to figure out your style however. Since it's a FP-OO hybrid, there are often many approaches to doing the same thing (https://fsharpforfunandprofit.com/posts/13-ways-of-looking-at-a-turtle/ https://fsharpforfunandprofit.com/posts/13-ways-of-looking-a...) and lots of different "styles" of how FP you want to go. Some people end up with "C# in F#" and some go almost to "Haskell in F#". (I personally end up somewhere in the middle). And until you figure that out, it's hard to be as productive as in a language you already know. But once you do, I think F# provides the ability to be more productive than C#. (Granted I think immutable records and `with` syntax would get C# half way there).
However I will admit that when it comes time to transition the code back to the owner, I kind of regret using an edgy language. Fact is most workaday developers don't have a ton of interest in new languages and would rather work with something they already know.
Most of the pain points are due to running on a runtime designed for OOP. So even though idiomatic F# code shouldn't need null checks or much exception handling, you still need them if you're using C# libraries. There's also an annoying mix of camelCase and PascalCase everywhere (the former for logical consistency: a function is a value, and the latter for consistency with C# conventions).
- pc86 9y agoI love doing side projects in C#. I'm in it all day at work so I don't need to spend hours figuring out how to configure my local environment or why I'm getting a blank page (horrors from my early days in PHP). If I'm trying to get something out the door to get that sweet, sweet AdSense money, it's going to be in C# unless a static POC site will do. If the side project is to learn something new, the language is usually what I'm trying to learn, so it's harder to pick what to build rather than which language to use.
- narimiran 9y ago> I've done plenty of freelance projects in F# over the past few years and enjoy it Could you give some examples of what did you do in F#? Did you choose F# just because you wanted to see if you can do it in it, or did F# have some advantages over other (functional) languages? > It takes a while to figure out your style however. (...) Some people end up with "C# in F#" (...) And until you figure that out, it's hard to be as productive as in a language you already know. My plan is to avoid as much as possible "writing Python in F#", because I choose F# as an opportunity to learn something new/different (which might transfer to writing better Python later). Any tips for this?
- pkese 9y agoSo far I've used F# form smaller projects, basically anywhere there's any un-trivial problem. Just the fact that the editor helps you write correct and concise code means that once you correct the mistakes that the editor (Ionide) higlights for you, things will just compile and work out of the box. Compared to Python, I'd assume that 1) I write a bit less code to solve the same problem in F# as I would in Python, 2) it takes a bit more time, but it is more fun, 3) once it compiles, there are seldom any bugs. So technically you trade some of programming speed for less time spent in debugging and writing test code. In the end, you are way faster and more productive. Especially once the code base starts getting bigger, the type system starts bringing in extra benefits. Major point is that detecting and correcting bugs in editor is faster than in compilation, and in compilation is better than at testing. So compared to Python, you get 2 orders of magnitude of better and faster development.
- daxfohl 9y agoMy main project over the last few years has been a photobooth, so I've done server-side in suave (I LOVE suave compared to any other .net framework), client-side in WPF (F# experience in WPF is meh), and a bundle of other mini projects. I did it in F# because it was interesting, not because it was more productive at the time. My personal landing point is about #6 in the turtles article. I still like classes and interfaces and think they fit perfectly well. However, inheritance is something I avoid completely now. The effect can be done much more flexibly and transparently by several other means. But one great thing about classes is that you get nice autocomplete when you type `myservice.`. And note I only use OO for "services"; data is data is data. So if you're doing DB stuff, prefer an anemic data model and a platform that supports it (so Dapper rather than EF or NHibernate). Basically do `db.Save(myData)` rather than `myData.Save()`. Another big change I've noticed is I don't use "private" functions much anymore. In OO I spent a lot more energy making sure that people using my classes couldn't use them wrongly. They could only do exactly what the requirements allowed. I think OO mindset (at least in C#/Java, maybe Python is different) makes you paranoid and guides you to putting "app code" into what should be "libraries". This sometimes made e.g. unit testing more of a pain; you can't test your "validate" functions directly because they're private. Now I tend to open most everything up and let developers do what they want with my code, but I add a few helper functions to cover the common cases to guide them in the right direction. In general I consider everything a library now; the only "app-specific" code I write goes in `main` function that glues everything together. Of course I still don't open functions that expose contained services, or that leave things in an inconsistent state, but that's about all. And of course embrace immutability and recursion (or the library functions that do it for you). Probably the most annoying thing for you, especially coming from Python, will be "similar records". So you'd need a `User` that just has raw data, `UserDb` that maybe has that plus an ID/DateAdded/DateModified, a `UserOut` that maybe has that minus PasswordHash, a `UserIn` that maybe has RawPassword/RawPasswordAgain, etc, and conversions between them all. Not to mention if you want different schemes for jsonNaming, db_naming, RecordNaming, etc. I've yet to come up with a happy typesafe way of doing this.