5 ms·
Think of it like other features: * Encapsulation? What's the point of having it if's perfectly sealed off from the world? Just dead-code eliminate it. * Priv
by mrkeen 2y ago
Think of it like other features:
* Encapsulation? What's the point of having it if's perfectly sealed off from the world? Just dead-code eliminate it.
* Private? It's not really private if I can Get() to it. I want access to that variable, so why hide it from myself? Private adds nothing because I can just choose not to use that variable.
* Const? A constant variable is an oxymoron. All the programs I write change variables. If I want a variable to remain the same, I just wont update it.
Of course I don't believe in any of the framings above, but it's how arguments against FP typically sound.
Anyway, the above features are small potatoes compared to the big hammer that is functional purity: you (and the compiler) will know and agree upon whether the same input will yield the same output.
Where am I using it right now?
I'm doing some record linkage - matching old transactions with new transactions, where some details may have shifted. I say "shifted", but what really happened was that upstream decided to mutate its data in-place. If they'd had an FPer on the team, they would not have mutated shared state, and I wouldn't even need to do this work. But I digress.
Now I'm trying out Dijkstra's algorithm, to most efficiently match pairs of transactions. It's a search algorithm, which tries out different alternatives, so it can never mutate things in-place - mutating inside one alternative will silently break another alternative. I'm in C#, and was pleasantly surprised that ImmutableList etc actually exist. But I wish I didn't have to be so vigilant. I really miss Haskell doing that part of my carefulness for me.
- DeathArrow 2y ago>I'm in C#, and was pleasantly surprised that ImmutableList etc actually exist. C# has introduced many functional concepts. Records, pattern matching, lambda functions, LINQ. The only thing I am missing and will come later is discriminated unions. Of course, F# is more fited for the job if you want a mostly functional workflow.
- mrkeen 2y agoI don't want functional-flavoured programming, I want functional programming. Back when I was more into pushing Haskell on my team (10+ years ago), I pitched the idea something like: You get: the knowledge that your function's output will only depend on its input. You pay: you gotta stop using those for-loops and [i]ndexes, and start using maps, folds, filters etc. Those higher-order functions are a tough sell for programmers who only ever want to do things the way they've always done them. But 5 years after that, in Java-land everyone was using maps, folds and filters like crazy (Or in C# land, Selects and Wheres and SelectManys etc,) with some half-thought-out bullshit reasoning like "it's functional, so it must good!" So we paid the price, but didn't get the reward.
- hnra 2y agoUsing map, fold etc. is not the hard part of functional programming. The hard part is managing effects (via monads, monad transformers, or effects). Trying to convert a procedural inner mutating algorithm to say Haskell is challenging.
- mrkeen 2y ago> The hard part is managing effects You can say that again! Right now I'm working in C#, so I wished my C# managed effects, but it doesn't. It's all left to the programmer.
- codr7 2y agoI don't know, stacking monads is a comparable level of pain to me.
- jcadam 2y agoNever used monads with Clojure (the only Lisp I've done "serious" work in). Haskell introduced them to me, but I've never done anything large with Haskell (no jobs!). Scala, however, has monads via the cats or (more recently) the ZIO library and they work just fine there. The main problem with Monads is you're almost always the only programmer on a team who even knows what a Monad is.
- troupo 2y ago> I don't want functional-flavoured programming, I want functional programming. > you gotta stop using those for-loops and [i]ndexes, and start using maps, folds, filters etc. You mean what C# literally does everywhere because Enumerable is the premier weapon of choice in the language, and has a huge amount of exactly what you want: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable https://learn.microsoft.com/en-us/dotnet/api/system.linq.enu... (well, with the only exception of foreach which is for some odd reason is still a loop). > But 5 years after that Since .net 3.5 18 years ago: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable?view=netframework-3.5 https://learn.microsoft.com/en-us/dotnet/api/system.linq.enu... > So we paid the price, but didn't get the reward. Who is "we", what was the price, and what was the imagined reward?
- pfdietz 2y agoThose starred rhetorical questions initially looked to me like a critique of Lisp! Because that's how Lisp (particularly Common Lisp) works. All those things are softish. You can see unexported symbols even if you're not supposed to use them. There is no actual privacy unless you do something special like unintern then recreate a symbol.
- bobbylarrybobby 2y ago> you (and the compiler) will know and agree upon whether the same input will yield the same output What exactly does this mean? Haskell has plenty of non-deterministic functions — everything involving IO, for instance. I know that IO is non-deterministic, but how is that expressed within the language?
- mrkeen 2y agoFunctions which use IO are tagged as such in the type system. IO can call non-IO, but not vice-versa.