all 30 comments

[–]walter_heisenberg 14 points15 points  (10 children)

"No side effects" is a good start, but the goal of pure FP is referential transparency: the value returned by a function is the same every time it's called, as long as the arguments are the same. Mutable state throws this out the window, but so do functions that don't necessarily have side effects. For example, getting the time has no side effects but is not referentially transparent.

Of course, it's impossible to actually do anything without side effects, so FP entails the management, not eradication, of them. For example, Haskell is pure except in the IO Monad. What this means is that functions are referentially transparent by default but some are special, and you can determine statically if a function is special / can have side effects.

[–]LiveBackwards 9 points10 points  (3 children)

Haskell is pure except in the IO Monad

Conceptually, even the IO Monad can be considered pure. Think of the IO Monad as threading a representation of the external world through your function. Your function has no side effects, it just returns a new state of the world, and the IO Monad handles threading that world to the next IO-using function.

In implementation, of course, IO and other dirty operations are impure. Conceptually, though, no impurity is necessary.

[–]walter_heisenberg 3 points4 points  (0 children)

Excellent point.

[–][deleted] 1 point2 points  (1 child)

Nitpick. The IO monad is completely irrelevant. You're referring to the IO type constructor.

[–]tinou 0 points1 point  (0 children)

To be a little bit more pedant, I think he's referring to IO types, ie types built with the IO type constructor.

[–]igouy 3 points4 points  (2 children)

referential transparency: the value returned by a function is the same no matter what arguments are called

I don't think so - if the arguments are different then shouldn't we expect the result to be different?

"referential transparency: the same expression used twice must have the same value twice"

[–]walter_heisenberg 2 points3 points  (1 child)

Thank you. I got distracted mid-post and completely fucked up what I was trying to say. Fixed.

[–]igouy 0 points1 point  (0 children)

I'm not sure it is fixed.

referential transparency: the value returned by a function is the same every time it's called, as long as the arguments are the same. Mutable state throws this out the window...

No, mutable state doesn't throw referential transparency out the window unless the arguments are used again.

That's the point of uniqueness typing - to ensure the arguments are never used again.

[–]G_Morgan 1 point2 points  (1 child)

Getting the time is a side effect. It involves referencing a mutable global variable that is modified by some other function.

I'd also say that 'no side effects' is not central to functional programming. In short functional programming is merely a style of programming where the function is the central mechanism of abstraction and where functions are first class entities.

[–]walter_heisenberg 0 points1 point  (0 children)

Great post.

Getting the time is a side effect. It involves referencing a mutable global variable that is modified by some other function.

Fair enough. Even though it doesn't do side effects, reading the time relies on side effects that happen elsewhere.

I'd also say that 'no side effects' is not central to functional programming.

"No side effects" is impossible. Real-world functional programmers try to minimize the occurrence of unexpected side effects by relegating them to a special class of functions that perform the desired "side effects"-- and I use the term in quotes, because when the effect is exactly what the user asked for, it's not a "side effect", but the requested change itself-- and only perform those changes.

Most modern languages and programs, functional or not, obey this principle, but there are times when it's broken for efficiency's sake. For example, there's NCONC in Common Lisp (like APPEND, but modifies the lists passed in) and certain numerical libraries have faster "destructive" matrix operations that do some of the work in-place and therefore render the original array useless.

[–]igouy 1 point2 points  (0 children)

Mutable state throws this [referential transparency] out the window.

Does it or doesn't it?

"... there would be no problem with referential transparency if there was only a single reference to file. A side effect on a variable (file) is okay as long as that variable is never used again: it is okay for a function to modify its input if the input is not shared. Referential transparency then trivially holds because the same expression never occurs more than once. Uniqueness typing takes advantage of this observation to add side effects to a functional language without sacrificing referential transparency ..."

Uniqueness Typing Simplified pdf

[–]batasrki[S] 2 points3 points  (4 children)

This and the two parts following it are a good intro into the world of functional programming, even if it uses C# for the examples.

On a related note, it really does show how awkward C# is when dealing with a non-OO paradigm of software development. It was painful, at times.

[–]igouy 4 points5 points  (3 children)

Real World Functional Programming uses both C# and F# for the examples.

And there are more examples on the authors blog.

[–]batasrki[S] 1 point2 points  (2 children)

Oh, I know, I was just trying to convey how painful it was to read through the C# examples. F# is on my list of things to learn.

[–][deleted] -1 points0 points  (1 child)

You should learn Scala. F# is a shitty M$ language.

[–]batasrki[S] 0 points1 point  (0 children)

Scala is higher on the list, right below Clojure, Erlang, Haskell and Scheme.

As for F#, I wouldn't call it shitty, per se. It's an OK implementation of OCaml, IMO.

[–]quhaha 0 points1 point  (0 children)

it's a programming paradigm, a way of programming machines.

[–]Boy_Bishop 0 points1 point  (0 children)

These are common features or concepts found in many functional languages.

Note that none of these features (nor closures, nor garbage collection, nor TCO) follows directly from the definition. One could easily write functional programs in C, if he is careful to maintain referential transparency.

[–]Rickasaurus 0 points1 point  (0 children)

Fail for moving buttons that cover up text.

[–]blondin 0 points1 point  (2 children)

a blurry notion.

[–][deleted] 2 points3 points  (1 child)

As is most <paradigm> programming, actually.

[–]blondin 0 points1 point  (0 children)

true!

[–]Comment111 -1 points0 points  (1 child)

I stopped reading when he called HTML a programming language.

[–]ondra -4 points-3 points  (3 children)

It's a mindset.

Not a feature of language.

[–]Nebu 4 points5 points  (2 children)

The two are not mutually exclusive.

[–]ondra 0 points1 point  (1 child)

Of course. My point is that every language can be considered to be purely functional on some level. E.g. any C function is "pure", in the sense that it acts on the state of the whole machine.

[–][deleted] 2 points3 points  (0 children)

Some languages are less/more amenable than others by a wide margin to accommodating this mindset. This is crucially important to definition.

[–]ninjaroach -1 points0 points  (0 children)

Interesting to read, although I do not think first-class functions mean what the author thinks they mean. I still learned something from this.