Re: Newbie Question: Is it allowed for the function to change the value of parameters?
- From: Ulf Wiger <etxuwig@xxxxxxxxxxxxxxx>
- Date: Fri, 27 Jul 2007 14:17:22 +0200
"JD" == Joachim Durchholz <jo@xxxxxxxxxxxxx> writes:
JD> These things don't go well with side effects - if you construct
JD> a function and pass it around, you lose a great deal of control
JD> when it will be evaluated, and that means you can't easily
JD> control the order in which the side effects will happen. So many
JD> FPLs indeed try to restrict or control side effects (Haskell,
JD> Clean), others rely on "common sense" and simply make
JD> side-effect-free programming easy (OCaml, SML, some
JD> styles/schools of Lisp programming).
There are places where higher order functions and side effects
go well together (these fall into the latter category, where the
programmer must exercise caution.
The Erlang-based distributed real-time dbms, Mnesia, uses
function objects to encapsulate database transactions, e.g.
F = fun() ->
[P] = mnesia:read({person, X}),
P1 = update_salary(P, 1000),
mnesia:write(P1)
end,
mnesia:transaction(F).
The side effects inside the closure should be under Mnesia's
control, i.e. you should use only API functions meant for
transactions. If you do, Mnesia can use distributed deadlock
prevention, and restart the transaction when needed.
Very useful, but the programmer is strongly cautioned against
introducing other kinds of side effect. In practice, this
works out well.
Another example: I once wrote a virtual channel manager
intended for communication between heterogeneous systems.
The novel feature was that it had version negotiation and
supported automatic chaining of data conversion functions
to allow communication between different versions of the
same software (within limits.) These funs were of course
side-effect free.
Another use of funs was to hide the details of the
communication mechanism. When setting up a channel,
you instrumented it with specific behaviour, e.g.
{on_receive,
fun(ChNo, SendF, {To,{From,Msg}} = What) ->
To ! {ChNo, fun(Reply) ->
SendF(From, {To,Reply})
end, Msg}
(which meant that the on_receive handler would pass
on the message, along with the fun to use if the
receiver wanted to reply to the sender.)
A server could then handle messages in this fashion:
rex_loop(Channel) ->
receive
{ChNo, ReplyF, ping} when is_integer(ChNo),
is_function(ReplyF,1) ->
ReplyF(pong),
rex_loop(Channel)
end.
The same server could then easily be called on using
normal Erlang messages:
Rex ! {0, fun(M) -> Me ! {reply, M} end, ping}.
Obviously, nothing stops an evil program from sending
a fun(_) -> exit(suicide) end. Again, programmer
cooperation is required.
Not that any of this refutes your argument. Higher-order
functions can be extremely useful together with side-effects,
but mainly as long as you are willing to give up a lot of
that compile-time safety. Erlang falls squarely into your
"common sense" category. (:
As a general rule, this type of programming is evil and
should be used as sparingly as possible.
BR,
Ulf W
--
Ulf Wiger, Senior Specialist,
/ / / Architecture & Design of Carrier-Class Software
/ / / Team Leader, Software Characteristics
/ / / Ericsson AB, IMS Gateways
.
- Follow-Ups:
- References:
- Prev by Date: Re: Sweeney presentation "The Next Mainstream Language"
- Next by Date: Non-academic use of Haskell
- Previous by thread: Re: Newbie Question: Is it allowed for the function to change the value of parameters?
- Next by thread: Re: Newbie Question: Is it allowed for the function to change the value of parameters?
- Index(es):
Relevant Pages
|