[erlang-questions] is there "return" in Erlang.

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Mon Feb 28 16:07:15 CET 2011


On Mon, Feb 28, 2011 at 15:46, Ulf Wiger <ulf.wiger@REDACTED> wrote:
>
> On 28 Feb 2011, at 14:15, Jesper Louis Andersen wrote:
>
>> The problem here is that doSomeThing(a); is done for its side-effect
>> only. The only possible side-effect in Erlang is that it communicates
>> with other processes
>
> Well, there are other ways - all of which could be modelled using processes,
> but in fact aren't (updating ets tables or the process dictionary, for example),
> but I agree with your point, and want to emphasise it.
>
> One thing that will grow in importance as you learn to appreciate the differences
> between pure and impure code, is that code like this - which can *only* be useful
> through side-effects - has a toxic effect on your code structure.

Indeed the problem is that code with side effects are toxic in many
ways. Other programmers can't easily follow the code, there is no
persistence since the side effect leaks, and non-pure functions are
harder to test since you need to mock the side-effects. Further, such
code is not inherently easy to make parallel because of the
impurities. I took the pure view + processes because of simplicity.
Another (monadic) effect which is important are exceptions, but they
were forgotten by me and they do not have a direct process-like
description.

My main point is this though: In (pure) functional programs, the data
flow is as important than the control flow, if not more. If you can
restructure your program so it passes fewer parameters and splits the
data flow, then it is often much more readable. Deeply nested calls
where many functions "along the way" just passes parameters for the
inner function is often better written without the passing and then
returning some value you can call at the top level. For instance:

   f(A,B,C) -> g(A, B, C) -> h(B, C)

is a call chain of f() -> g() -> h() where g has to pass on B and C
because h needs them. If we rearrange such that g does not *call* h,
but instead returns some value which h can be called with, you get an
altered flow:

   f(A,B,C) ->
     R = g(A),
     h(R, B, C)

untangling g from the chain and making it a lot simpler. Often h
doesn't grow much nastier in the process. A naive programmer will
often just shove B and C into the fields of an object or pass it as
global state because it looks easier. But it also hides the coupling
of the functions and using h otherwise now requires the programmer to
follow an undocumented protocol. Worse, many imperative languages put
*severe* restrictions upon the R above, so it is not even possible to
write the code in a data-flow oriented style. The queen has
effectively been beheaded :/


-- 
J.


More information about the erlang-questions mailing list