|
Folks,
My funs seem to behave differently when the beams are compiled to native code. Is there an explanation to this? I am passing indeed passing funs as {M, F} and then calling them as per the code below. Why does it work when the code is byte-compiled and how do I work around these errors? monitor(self(), Sock, {gen_udp, close}) monitor(Sock, Closer) -> receive {'DOWN', _, process, _, _} -> Closer(Sock); Any -> io:format("Monitor: Unknown:~n~p~n", [Any]), monitor(sock, Closer) end. My make file: {'*',[native]}. The errors that I get when my code is compiled to native: =ERROR REPORT==== 12-Jan-2006::15:42:25 === Error in process <0.31.0> with exit value: {{'EXIT',{{badfun, {randomplay,script}},[]}},[]} =ERROR REPORT==== 12-Jan-2006::15:42:26 === Error in process <0.30.0> with exit value: {{'EXIT',{{badfun, {lobbybot,script}},[]}},[]} =ERROR REPORT==== 12-Jan-2006::15:42:26 === Error in process <0.32.0> with exit value: {{badfun,{gen_udp,close}},[]} Thanks, Joel -- http://wagerlabs.com/ |
|
I could certainly change things to
Closer = fun(Sock) -> gen_udp:close(Sock) end, monitor(self(), Sock, Closer), for this particular case but I'm also passing the name of the module from the command like to invoke the script function in it. I don't see how I can construct a real fun from an atom that is the module name. On Jan 12, 2006, at 4:00 PM, Joel Reymont wrote: > Folks, > > My funs seem to behave differently when the beams are compiled to > native code. > > Is there an explanation to this? I am passing indeed passing funs > as {M, F} and then calling them as per the code below. > > Why does it work when the code is byte-compiled and how do I work > around these errors? > > monitor(self(), Sock, {gen_udp, close}) > > monitor(Sock, Closer) -> > receive > {'DOWN', _, process, _, _} -> > Closer(Sock); > Any -> > io:format("Monitor: Unknown:~n~p~n", [Any]), > monitor(sock, Closer) > end. -- http://wagerlabs.com/ |
|
I worked around this by calling apply(Module, ...). Apparently {M, F}
is deprecated. Still, it's interesting that no error is reported and everything works fine when byte-compiled. On Jan 12, 2006, at 4:03 PM, Joel Reymont wrote: > I could certainly change things to > > Closer = fun(Sock) -> gen_udp:close(Sock) end, > monitor(self(), Sock, Closer), > > for this particular case but I'm also passing the name of the > module from the command like to invoke the script function in it. > > I don't see how I can construct a real fun from an atom that is the > module name. -- http://wagerlabs.com/ |
|
In reply to this post by Joel Reymont
Joel Reymont wrote:
> I could certainly change things to > > Closer = fun(Sock) -> gen_udp:close(Sock) end, > monitor(self(), Sock, Closer), > > for this particular case but I'm also passing the name of the module > from the command like to invoke the script function in it. > > I don't see how I can construct a real fun from an atom that is the > module name. You could do something like this: foo({M,F}) -> Closer = fun(Sock) -> M:F(Sock) end, monitor(self(), Sock, Closer) or if only the module name is changing: foo(M) -> Closer = fun(Sock) -> M:close(Sock) end, monitor(self(), Sock, Closer) etc. The OTP guys recently added dynamic-lookup "funs" on the form 'fun foo:bar/2', but it seems that you cannot create them using variables, as in "fun M:F/A" (which would be handy in my opinion). Perhaps this can be added? The advantage over tuples is that is_function/1 yields true for the funs, and that there is no confusion about the arity of the called function. (E.g., if you use {M,F}, and then change the number of arguments, but forget to update some call site, it might continue to "work" by calling the wrong function. Not good.) Also, analyses like those done by Dialyzer are more easily foiled by passing around atoms - or (shudder!), even manipulating strings and converting them to atoms and finally using those atoms to call a function! /Richard |
|
In reply to this post by Joel Reymont
Joel Reymont wrote:
> I worked around this by calling apply(Module, ...). Apparently {M, F} > is deprecated. Don't do that. Calling apply is generally much more inefficient, since it must traverse a list to push arguments on the stack. Unless your argument lists really vary in length (and then you should stop and ask yourself what the heck you are doing...), it is both faster and cleaner to just do Module:Function(...). /Richard |
|
In reply to this post by Joel Reymont
Joel Reymont writes:
> Folks, > > My funs seem to behave differently when the beams are compiled to > native code. > > Is there an explanation to this? I am passing indeed passing funs as > {M, F} and then calling them as per the code below. > > Why does it work when the code is byte-compiled and how do I work > around these errors? > > monitor(self(), Sock, {gen_udp, close}) > > monitor(Sock, Closer) -> > receive > {'DOWN', _, process, _, _} -> > Closer(Sock); > Any -> > io:format("Monitor: Unknown:~n~p~n", [Any]), > monitor(sock, Closer) > end. > > My make file: > > {'*',[native]}. > > The errors that I get when my code is compiled to native: > > =ERROR REPORT==== 12-Jan-2006::15:42:25 === > Error in process <0.31.0> with exit value: {{'EXIT',{{badfun, > {randomplay,script}},[]}},[]} A simpler test module: ==snip== -module(bar). -compile(export_all). test1() -> bar1({?MODULE,f}, 42). test2() -> bar2({?MODULE,f}, 42). test3() -> bar3({?MODULE,f}, 42). bar1(MF, X) -> MF(X). bar2(MF, X) -> apply(MF, [X]). bar3({M,F}, X) -> M:F(X). f(42) -> ok. ==snip== In this module, test1() to test3() all work in BEAM mode, but only test2() and test3() work after compilation to native code: bar:test1() results in a badfun exception. HiPE could allow bar:test1() to work. The reason it doesn't is largely political: some people have strong opinions against the old-fashioned {M,F} functions, and since there are alternatives, there have been little incentive to extend the compiler to support them. A secondary reason is that it would cause code bloat for all MF(X)-like expressions. /Mikael |
|
In reply to this post by Richard Carlsson
Thank you Richard!
On Jan 12, 2006, at 4:34 PM, Richard Carlsson wrote: > You could do something like this: > > foo({M,F}) -> > Closer = fun(Sock) -> M:F(Sock) end, > monitor(self(), Sock, Closer) -- http://wagerlabs.com/ |
| Powered by Nabble | Edit this page |
