Hacker News new | ask | show | jobs
by quchen 1553 days ago
Should mean the same thing as means has the same result value here. The operational semantics could be different, as you mention: even without side effects, computing x may be very expensive.

This isn’t even special to FP, it’s a basic problem when building a compiler, namely whether inlining/common subexpression elimination is beneficial.

To drive the point home, even in a language like Haskell these two examples might have a factor of two in execution time between them.

1 comments

In theory you're right, but in this specific case they really are the same - the compiler has an optimization pass called "common subexpression elimination" that converts the second to the first in nearly all cases.
They're not exactly the same:

Case 1:

x = foo()

y = bar(x)

z = bar(x)

Case 2:

y = bar(foo())

z = bar(foo())

In case 1 the value of x must be kept in memory across the entire execution of bar(x) since you need it for the second invocation of bar. In case 2, the result of foo() can be discarded once bar is done with it.

To use a contrived example, imagine a program that has 100 mb of available memory.

foo() returns a data struct that is 95 mb in size.

def bar(some_big_data_struct)

   some_small_data = some_big_data_struct[:some_key]

   [A bunch of other code that allocates and then releases 90 mb]

   return some_other_small_data
end

In Case 1 I get an OOM error. In Case 2 I (or the runtime) can reclaim the 95 mb that some_big_data_struct uses and the program works.

Clearly that's a contrived situation but it illustrates my original point. There's a huge gap between theoretical pure functions and what we have to deal with in the real world. These sorts of FP tutorials never go into the weeds and explore these problems.