[racket] Why functional?
Lawrence Bottorff <borgauf at ...> writes:
>
> I posted the following question at stackoverflow and got 3 pluses and a
star (favorite question) -- although only one response. I'd really like to
clear these issues up in my mind. Here goes:
> ----
>
>
> I've read some of the discussions here, as well as followed links to other
explanations, but I'm still not able to understand the mathematical
connection between "changing state" and "not changing state" as it pertains
to our functional programming versus non-FP debate. I understand the basic
argument goes back to the pure math definition of a function, whereby a
function maps a domain member to only one range member. This is subsequently
compared to when a computer code function is given certain input, it will
always produce the same output, i.e., not vary from use to use, i.e.i.e.,
the function's state, bzw. its domain to range mapping behavior, will not
change.
------------------------------
Lawrence,
Take a different perspective entirely. Forget the mathematical and
theoretical
stuff for the moment. Think about sources for bugs in imperative,
procedural or OO programming,
when left up to a programmer to manage:
1. pointers
2. memory management
3. assigning and reassigning values to variables/memory locations
4. breaking an interface (whether it’s OO or not)
Let’s just stop at those 4. People might mention others…
Also think about some other things that we do repeatedly in coding solutions
to many problems:
5. iterate over a list or collection to do something to each element of
that collection
6. interrupt computation at time t, restart from the same point at time
t+x.
7. use “potentially infinite” and possibly recursive data set
Pure functional languages do not allow (re)assignment. You can assign a
variable/identifier once,
then it is immutable. If you need a new value, it is a different identifier
(different memory location
under the covers). It removes a number of shared-memory bugs caused by
updating a location
incorrectly, whether your application is single-threaded or multi-threaded
or distributed.
Similarly a programmer can create new things, like lists, but is not
*required* to explicitly manage when
a list gets destroyed/deallocated. Typically, the system will do it.
Functional languages allow a clean way of passing functions (and closures)
as parameters and
returning functions as values from another function. This enables higher-
order functions such as map, filter,
fold and list comprehensions to work in predictable, sane ways. Again so
the programmer doesn’t have to explicitly manage, or even think about,
operating on a collection as explicit iteration. Functions with closures
allow you to cleanly stop execution of a function, “memorize it” (to use
some jargon) and restart it later, with the expectation that it will
generate the same result as though it had simply run from beginning to end.
And then there is lazy versus strict evaluation. When dealing with
potentially infinite data, the programmer’s
code does not have to change versus dealing with a collection that only has
10 items. Typically the programmer includes
a lazy version of the same code, or change a library import, or something
like that—which is much less likely
to introduce bugs in code than having to change a lot of function/method
names. Lazy versus strict evaluation
of code/data is a behavioral, semantic issue, usually not a syntactic one.
George