Every definition of purity I can find that talks about objects/references says that if you pass in the same object/reference with different contents then that's not pure.
Your version differs from mine on that aspect. It passes two unrelated objects.
> Starting from the question that gave birth to this whole thread: "What's the benefit of learning a PURE functional programming language..."
I interpret saying a language is "purely functional" as being more about whether you're allowed to write anything that isn't functional. I can talk about BASIC being a "purely iterative" language or about "pure assembly" programs, without any implication of chunks of code being pure.
I now believe that learning a language like Haskell (or Elm or PureScript) forces you to see your program as pipes that you fuse together.
It's not just functions. Haskell has only expressions and declarations. That means, for example, that you are forced to provide an `else`, when you use `if`. The idea is that you have to keep the data flowing. If a function doesn't provide a meaningful value (so it returns nil, None), you have to handle that explicitly.
And, btw
> Your version differs from mine on that aspect. It passes two unrelated objects.
Those two objects are not unrelated. They have the exact same structure (an attribute named "x"). So they could be considered two values of the same type.
I mean that the identity is unrelated. Yes, you can say they're the same type. But I'm actually passing the same object in. If f evaluated lazily, it could return 2 from both calls. Something like:
define f(o): return o.x
let a = {x=1}
n = f(a) // n is not evaluated yet
a.x = 2
m = f(a)
return n + m // returns 4
Ok, you're probably proving the point that purity also requires immutability. I'm not sure, as I haven't considered all the implications of Haskell's design.
My two rules about inputs and outputs are more like heuristics. They can improve code organisation and probably also decrease the likelihood of some errors, but they don't guarantee correctness, as you're pointing out. They're shortcuts, so they're not perfect.
Edit: If I remember right, it's laziness that requires immutability. I think I read something about this in the Haskell subreddit as an explanation for Haskell's design.
Doesn't that example also show a kind of laziness?
I say this because the second solution to that question offers the solution of using `i` as a default argument when defining the function. That forces its evaluation and fixes the problem.
for i in xrange(3):
def func(x, i=i): # the *value* of i is copied in func() environment
return x * i
flist.append(func)
That could also be written "def func(x, foo=i): return x * foo". It's just copying i's value to another variable. In the next line, i's value is still 1, 2, or 3, so when the function is called during the next line of the body of the loop, the value held by i is bound to foo.
It's not evaluating a thunk representing i, which is how lazy variables are evaluated in Haskell.
Ok, I had a better look at the code and I realised that it doesn't follow the rule I was talking about, namely having the function only work on values it receives as inputs.
I think that's why I don't use closures, because they read values from the environment. Their only use case (that comes to mind) can be solved with partial application, which is safer.
Oh, and I wasn't using laziness in the Haskell sense, but more in the general sense of deferring evaluation.
Purely functional language is pretty universally taken to mean that the language enforces function purity for all functions [perhaps with some minor escape hatches like Haskell's unsafePerformIO].
Every definition of purity I can find that talks about objects/references says that if you pass in the same object/reference with different contents then that's not pure.
Your version differs from mine on that aspect. It passes two unrelated objects.
> Starting from the question that gave birth to this whole thread: "What's the benefit of learning a PURE functional programming language..."
I interpret saying a language is "purely functional" as being more about whether you're allowed to write anything that isn't functional. I can talk about BASIC being a "purely iterative" language or about "pure assembly" programs, without any implication of chunks of code being pure.