I took the "flat" approach in the Loom server code (see https://loom.cc/source). Formerly I used all the object-oriented module techniques, but finally I scrapped all that for direct calls to functions in a flat name space. I found it more flexible and easier to understand, and it didn't force me to think about artificial boundaries. This makes the Perl code similar to my C code. I don't even use many static functions in C, preferring everything to have a unique name.
I also wrote a functional language interpreter in C. The language is called Fexl (see http://fexl.com/code/). The C code obviously uses a uniquely named flat function space. However, the Fexl language itself has far more flexibility, since you can easily create functions within functions.
For example you can easily do things like this:
\test_print =
(
\test1 = ...
\test2 = ...
...
)
\test_read =
(
\test1 = ...
\test2 = ...
...
)
In that case you're not at all worried about the names test1 and test2 conflicting with anything else. It's very lightweight, just like the Fibonacci example shown on this thread.If you really want to "export" functions declared inside a scope, you can do it like this:
\handy_module =
(
...
\fun1 = ...
\fun2 = ...
\return return fun1 fun2
)
Then to grab the functions you say: handy_module \fun1 \fun2 ... (now use fun1 and fun2)
You can change the names too, like this: handy_module \f1 \f2 ... (now use f1 and f2)
There's no extra magic in the language, you're just applying the module to a handler which grabs the exported functions.