[erlang-questions] noob namespace question

Laszlo Lovei lovei.laszlo@REDACTED
Sat Dec 15 15:54:55 CET 2012


On Wednesday, December 12, 2012 7:40:26 PM UTC+1, rusi wrote:
>
> On Thu, Dec 13, 2012 at 12:00 AM, Thomas Allen <tho...@REDACTED<javascript:>
> > wrote:
>
>> On Wed, Dec 12, 2012 at 11:44:43PM +0530, Rustom Mody wrote:
>> > I dont understand. Let me try and be more explicit about my concern.
>> >
>> > Let h be a higher-order function of one argument (h/1)
>> >
>> > Now in the call h(foo)
>> > How does Erlang know whether foo is a function or an atom?
>>
>> This is not valid, and you will get a "bad function" error if you try to
>> pass your function this way. You must create a "fun" like so:
>>
>>   h(fun foo/0)
>>
>> Similarly, you could pass an anonymous fun (like fun(X) -> X end), or
>> a module-function combination (like fun lists:reverse/1).
>>
>>
> Thanks Thomas that answers succinctly.
>

That is a succinct but incorrect answer :) The call `h(foo)' is completely 
valid, and might even refer to function `foo', although in a different way 
than `h(fun foo/0)'.

I think the common source of misunderstanding here is that atoms are used 
as both run time data and compile time identifiers. The expression `foo' 
simply creates a data of type atom, without any additional meaning. This 
data can be be used to identify something (a module, a function, a record, 
a message - we don't know in advance) at run time. The expression `fun 
foo/0' however creates a run time data of type function reference to 
function foo, and the atom foo itself is only used to identify the function 
at compile time. The same thing happens in expression `foo()', which is 
compiled into a function call to function foo, without actually involving 
the atom foo at run time.

The connection between the compile time identifiers of functions and run 
time atom data is that exported functions are identified by atom data at 
run time, instead of atom identifiers at compile time. So the expression 
`m:foo()' means "look up a function with identifier foo in the export table 
of module m, and call that function", where both atom m and atom foo are 
run time data. You can even use arbitrary expressions to compute the module 
or function name, so for example `h(F) -> m:F().' is valid code, and 
calling `h(foo)' means the same as `m:foo()'. Note that you can't do this 
with local functions: the code `h(F) -> F().' works only when F is a 
function reference, so it must be called as `h(fun foo/0)'. This is what 
Thomas meant.

In `h(foo)', we don't know whether the atom foo stands for a function or 
something else - `h(M) -> M:bar().' is also valid code, and in this case 
`h(foo)' means the same as `foo:bar()', so foo turns out to be a module 
name. Or you can write `h(Tag) -> receive {Tag, Data} -> Data end.', in 
this case `h(foo)' means "wait for a message tagged with foo". And you can 
even choose between these meanings at run time.


L.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121215/bfde04b1/attachment.htm>


More information about the erlang-questions mailing list