[erlang-questions] Style wars: junk comments

Richard O'Keefe ok@REDACTED
Thu Sep 13 04:38:23 CEST 2012

On 13/09/2012, at 1:38 PM, Fred Hebert wrote:

> Some Schemes also allow things like:
> (define (fib x)
>   (define (fib-rec n a b)
>      (cond [(= n 0) b]
>            [true (fib-rec (- n 1) b (+ a b))]))
>   (fib-rec x 0 1))
> which can be called as(fib 4).

I think you missed the point.  Except for the use of square brackets,
this is absolutely standard RnRS Scheme for at least n = 2..5.  It is
also trivial and in this context unhelpful, because a helper function
defined this way is necessarily private to its client.  You can do
_this_ much in practically every functional language but Erlang.

Defining one function inside another is just plain not interesting;
we've been able to do _that_ since 1960.  Only languages in the
BCPL->C->C++->Java lineage think there is anything unusual or
tricky about *that*.  (Even Fortran and COBOL let you defined
nested procedures.)

Heck, even in Erlang you can do

fib(X) ->
    F = fun (_, 0, _, B) -> B
          ; (G, N, A, B) -> G(G, N-1, B, A+B)
    F(F, X, 0, 1).

> This allows to define private or helper functions within the context of their main function, without needing destructive assignment or whatever, and then later on executing it.

Even Scheme doesn't _really_ need destructive assignment;
you can manage without it by introducing an auxiliary name:

(define add-and-del
  (letrec ((rebalance (lambda (t) ...))
    (list (lambda (k v t) ...)) ;add
          (lambda (k t) ...)))) ;del
(define add (car  add-and-del))
(define del (cadr add-and-del))

Common Lisp lets you get the multiple-private-helpers-
shared-by-multiple-clients effect by bending the
scope rules rather horribly:

  (labels ((rebalance (t) ...))
    (defun add (k v t) ...)
    (defun del (k t) ...))

DEFUN always "Defines a new function ... in the global environment."

The mechanics are of no great interest,
what is of interest is the ability by _some_ mechanism
to have one or more helper functions that are
*outside* their clients (so they do *not* have access to
the clients' internal data) and are accessible to one or
*more* clients without being accessible to _all_ the
top-level functions in the module.

Defining a function inside another function does NOT allow
 - private helper functions used by two or more functions
   (which was the point of what I was talking about)
 - private helper functions used in more than one clause
   of the same function, a very important issue in Erlang.

> Python allows something similar:
> def fib(x):
>    def fib_rec(x, a, b):
>        if x == 0:
>            return b
>        else:
>            return fib_rec(x-1, b, a+b)
>    return fib_rec(x, 0, 1)

Yawn.  So Python has caught up with 1960.  This *still* cannot
handle the non-trivial case of a helper function shared by more
than one function.
> You can separate one-use helpers from module-wide helpers that way, too.

Yes, that's been pretty much obvious since 1960.
The issue is helpers that are NEITHER one-use NOR module-wide.

Non-functional languages usually go for nested modules for that.
Like I said, I don't care about the mechanics.
> Nothing would keep us from doing something similar in Erlang iff anonymous functions were not so anonymous (and if self-recursion in anonymous function wasn't that annoying to read).

I don't see anything *annoying* in
    F = fun (_, 0, _, B) -> B
          ; (G, N, A, B) -> G(G, N-1, B, A+B)
Mildly irritating, yes; annoying, no.
I seem to recall suggesting a small syntax
extension where

   fun F(X, Y, Z) -> ... F(...) ...
     ; F(...) ... F ... 

would turn into

   F = (fun (G) -> fun (X, Y, Z) -> G(G, X, Y, Z) end end)
       (fun (F, X, Y, Z) -> ... F(F,...) ...
          ; (F, ...) ... fun (X, Y, Z) -> G(G, X, Y, Z) end ...

but on the whole, perhaps not.

More information about the erlang-questions mailing list