Thhat is a fine point which I rarely see discussed in connection with FP. (Pure) FP is commonly understood (?) to mean that there can be no mutable data. You can "bind" a value to a variable but only once. Right?
But within a function you can have local variables. I don't see why it would be bad to assign multiple different values to the same local variable, which only exists during the execution of the function. The variable only exists in the "stack" not in the "heap" and is gone as soon as the function returns.
So if I run a while-loop and repeatedly assign a new value to the local variable "i" for instance, would that be unacceptable according to "FP"? Why? I can't see any ill effects from modifying a variable whose value can not "linger" past the execution of the function.
What am I missing? Why is it (supposed to be) bad to rebind any number of different values to a local variable?
I thought (from what I've read so far) that "no mutable state" is the definition of "pure FP".
So should the definition of pure FP be "No un-encapsulated mutable state"? Instead state must always be "encapsulated". Where can I read more on this? Thanks
It’s actually quite liberating not having to worry about what’s “right or wrong” and instead just do whatever you like that compiles.
I suggest getting started with Haskell through http://www.learnyouahaskell.com/ - it was my favorite.
I'd say "pure" is if the calculation can be done with a function without side effects and it is a deliberate choice to restrict a language to (almost) only that. No side effects at all would mean no interaction with "the outside world" and no access to input data though.
It’s poor because it invites other meanings: some people think purity means immutability for example; but that’s only part of it.
There is no definition of what FP is that is agreed upon by everyone, but the key is the word "functional" in FP.
This comes from a mathematical function, which is a mapping of input values to output values.
You could write a definition of a function f(x) to be such that the value of f(x) is the result of the execution of some imperative-looking code (including loops that mutate variables).
Mathematicians would be satisfied with such a definition and would confirm that f(x) is a function just as valid as any other.
And so functional programmers should also accept such a function. In fact, Haskell has specific syntactical support ("do" notation) to allow you to write functions using imperative-looking code including mutations (the ST monad, or other State monads).
It's much more nuanced than that, certainly no arbitrary and unchecked mutable state is. There are ways though of achieving mutable state whilst maintaining referential transparency.
Martin Odersky was discussing this recently. How they found examples of overly-complicated "functional programming" in their codebase (erroneous, and hard to understand) when an imperative function would be way easier, performant and correct.
The takeout? The imperative version was still pure. Mutability was limited to the scope of the function.
I have never tried Haskell, so I cannot really hold any truly fair opinion there, but I find Odersky's "values" or approach to programming language design much more in line with my own. Scala 3 seems like a very well designed language (pragmatic, expressive, conceptually solid).
You're technically correct, which is the best kind of correct. Scala is not based on the Lambda calculus. The DOT calculus (which is what Scala is theoretically built upon) is based on objects.
Yet, at the same time
> please do not judge functional programming based on how it looks in Scala
based on my research into the labour market, I would guess that Scala is the programming language where most of the Functional Programming takes place, both in the general sense and also in the Pure FP sense. It is more widely used than Haskell, F#, Clojure, Elixir, Erlang, OCaml, Racket, etc.
And it works rather nicely in my opinion. There are still areas that I'd like to see improved, of course, like the for-comprehension, but I'm already quite content.
> effects to be controlled, checked and reasoned about
Definitely! We have so called Functional Effect System libraries for that in Scala. Not just one, but two: Cats Effect and ZIO. Check them out. I would recommend anybody using Scala do use either of those.
KEYNOTE Simply Scala Martin Odersky
It's mostly a matter of preference. I think experienced programmers will favour the pure approach unless there's a good reason to do otherwise, and know well how to solve common problems without relying on mutable structures (typically, it's very rare that you need a while loop in OCaml). But sometimes, it makes more sense and is less verbose to use mutable DS.
I can agree with that. Yet I somehow perceive an opinion that it is not FP unless it is Pure FP (?). Like even a small amount of impurity can poison the whole well.
It would necessitate that every side effect, every boundary and every interface to be pure, on top of internals also being pure.
Haskell comes close, but we're skirting the real heavy hitters like Idris/Agda here.
Erlang hits the sweet spot for me, where processes (async, stateful modules) communicate by message, whose internal functions are 'pure' .
Also, functional programming is harder than pure imperative or imperative+object imho, which help gatekeeping, and more impressive (again, only my opinion). There is also a lot a good ideas that (came from/were invented by/were introduced with) FP and are integrated in older languages. This is a perfect setup to have cult-like groups appears, even if the person they revere isn't as "into it" as the group is generally. Imho it's mostly young devs who are/were pretty good for their age group (and thus have a bit of an ego[0]), a bit noisy, and will grow up and be more welcoming in the future.
[0] which is understandable and reasonable, this is absolutely not a shot, i was one of you (lisp/CLOS fanatic instead of FP fanatic, but still) until i worked with people 100 times better than i. The "grow up" is a small shot though, but don't take this seriously :)
I prefer the Erlang way, I find it to fairly nicely solve a problem with the only downside being that I can’t rebind variables, which encourages me to write smaller functions. And the language use fewer tokens, which is an nice if you ever want to parse it for some reason.
https://www.erlang.org/doc/reference_manual/patterns.html https://elixir-lang.org/getting-started/pattern-matching.htm...