<div dir="ltr">You also need to consider whether or not you want loading to be automatically triggered by this check, or if you indend to ensure in some other way that the modules you are checking are known to be loaded already. Using "try Module:Function() catch ... end", if the function is not found it will cause a trap to the error handler module which will first try to load the module if it is not currently in memory. If you use only erlang:function_exported/3, it will return "false" if the module is not yet loaded.<div><br></div><div>If you assume that modules are usually loaded when you run the test, but you'd like to load them automatically if needed, you can write a function like this:</div><div><br></div><div><div>is_exported(M, F, A) -></div><div>  case erlang:module_loaded(M) of<br></div><div>    false -> code:ensure_loaded(M);</div><div>    true -> ok</div><div>  end,</div><div>  erlang:function_exported(M, F, A).</div><div><br></div><div>(code:ensure_loaded() is slow compared to the fast call to erlang:module_loaded(), even if the module is already in memory).</div><div><br></div><div>If it should be an error if the module cannot be loaded, you can add a check that ensure_loaded(M) returns {module, M} and not {error,_}.</div><div><br></div><div>If you want to prevent repeated attempts to load a module that failed to load the first time <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">(since such attempted loads are slow)</span>, you could add some kind of memoization, or even generate a dummy module<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"> containing no functions,<span> </span></span>that you load instead so that subsequent calls return quickly.</div></div><div class="gmail_extra"><div><div class="gmail_signature" data-smartmail="gmail_signature"><br>        /Richard</div></div>
<br><div class="gmail_quote">2018-03-04 8:09 GMT+01:00 Metin Akat <span dir="ltr"><<a href="mailto:akat.metin@gmail.com" target="_blank">akat.metin@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I haven't yet done rigorous testing with many processes, but what you are suggesting is the slowest so far (at least by the most naive way of measuring, while not under load) :<div><br></div><div><div>37> timer:tc(fun() -> lists:member({not_a_function, 1}, Module:module_info(exports)) end).</div><div>{514,false}</div><div>38> timer:tc(fun() -> try Module:not_a_function() catch error:undef ->  not_defined end end).</div><div>{47,not_defined}</div><div>39> timer:tc(fun() -> erlang:function_exported(<wbr>Module, not_a_function, 1) end).</div><div>{8,false}</div></div><div><br></div><div><br></div><div>The reason I'm asking is because I saw this gen_server:try_dispatch/3 implementation and I am wondering what are the implications under heavy load and concurrency.</div><div><br></div><div><br></div><div><br></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Mar 4, 2018 at 8:47 AM, Zachary Kessin <span dir="ltr"><<a href="mailto:zkessin@gmail.com" target="_blank">zkessin@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-family:garamond,serif">I realize that there is a race condition in that code, if someone reloads the module at the wrong moment it could crash.</div><div style="font-family:garamond,serif"><br></div><div style="font-family:garamond,serif"><br></div></div><div class="gmail_extra"><span><br clear="all"><div><div class="m_7792064739449337464m_5946632003448391729gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><span style="font-family:garamond,serif">Zach Kessin - CEO Finch Software<br><font color="#000000">I boost sales with retail chatbots for fashion and cosmetics</font><br><a href="tel:+972%2054-234-3956" value="+972542343956" target="_blank">+972 54 234 3956</a> / <a href="tel:+44%2020%203734%209790" value="+442037349790" target="_blank">+44 203 734 9790</a> / <a href="tel:+1%20617-778-7213" value="+16177787213" target="_blank">+1 617 778 7213</a></span></div><div><font face="garamond, serif"><a href="https://calendly.com/zkessin/chatbot" target="_blank">Book a meeting with me</a></font></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
<br></span><div><div class="m_7792064739449337464h5"><div class="gmail_quote">On Sun, Mar 4, 2018 at 8:37 AM, Zachary Kessin <span dir="ltr"><<a href="mailto:zkessin@gmail.com" target="_blank">zkessin@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-family:garamond,serif">You can use the function MODULE:module_info/1 something like </div><div><span style="font-family:garamond,serif">is_defined(MyFunc, Arity, MODULE)-></span></div><div><span style="font-family:garamond,serif">   Functions = MODULE:module_inf<wbr>o(</span><font color="#1a1a1a" face="mono, Courier, monospace"><span style="font-size:16px;background-color:rgb(243,243,243)">functions</span></font><font face="garamond, serif">),</font></div><div>   lists:member({MyFunc,Arity}<wbr>, Functions).</div><div><br></div><div>Where MyFunc is an atom of course</div><div><br></div><div>You could also expand that to a call_function_if_defined_with_<wbr>default/N but i will leave that to you</div><div><br></div><div>Zach</div><div><br></div></div><div class="gmail_extra"><br clear="all"><div><div class="m_7792064739449337464m_5946632003448391729m_1031641379390454610gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><span style="font-family:garamond,serif">Zach Kessin - CEO Finch Software<br><font color="#000000">I boost sales with retail chatbots for fashion and cosmetics</font><br><a href="tel:054-234-3956" value="+972542343956" target="_blank">+972 54 234 3956</a> / <a href="tel:+44%2020%203734%209790" value="+442037349790" target="_blank">+44 203 734 9790</a> / <a href="tel:+1%20617-778-7213" value="+16177787213" target="_blank">+1 617 778 7213</a></span></div><div><font face="garamond, serif"><a href="https://calendly.com/zkessin/chatbot" target="_blank">Book a meeting with me</a></font></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
<br><div class="gmail_quote"><div><div class="m_7792064739449337464m_5946632003448391729h5">On Sat, Mar 3, 2018 at 9:42 PM, Metin Akat <span dir="ltr"><<a href="mailto:akat.metin@gmail.com" target="_blank">akat.metin@gmail.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="m_7792064739449337464m_5946632003448391729h5"><div dir="ltr">I'm looking into this code: <a href="https://github.com/erlang/otp/blob/master/lib/stdlib/src/gen_server.erl#L631" target="_blank">https://github.com/erlan<wbr>g/otp/blob/master/lib/stdlib/s<wbr>rc/gen_server.erl#L631</a><br><div><br></div><div>Seems like this try/catch clause is implemented with the idea that most of the time it will succeed, as the callback module will have implemented the corresponding callback function, so we will not have to go into the exception clause where it needs to call erlang:function_exported/2 one more time (presumably as an additional safeguard) which is more expensive than an optimistic try clause.</div><div><br></div><div>I am writing something very similar, where such a check (is a function exported) will be performed by thousands/millions of processes on every message, but in my case... it's quite probable that most of the time this WILL raise the exception. In my case the function will be purely optional - if defined, it will return a value. If not, a default value will be used. </div><div><br></div><div>So my question is, how bad is this? I will test, but I'm still interested if someone has any ideas (maybe do something completely different).</div><div><br></div><div>Other possibilities are:</div><div><br></div><div>- Actually make the callback compulsory. I don't want to do that, as the problem I'm solving with this project is "See, you don't have to implement this boilerplate every time any more"</div><div><br></div><div>-  Put the option in application env where the user can configure it on startup. </div><div><br></div><div><br></div></div>
<br></div></div>______________________________<wbr>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/list<wbr>info/erlang-questions</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div></div></div>
</blockquote></div><br></div>
</div></div><br>______________________________<wbr>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/<wbr>listinfo/erlang-questions</a><br>
<br></blockquote></div><br></div></div>