Sorry, I think you are wrong there. You have a number of problems when detecting/handling safe functions and calling user defined functions in guards:<br><br>- It is relatively easy to work which local functions are safe, but when you call another module you suddenly leaping without a safety net. Yes, you could analyse that functions within modules but that would not guarantee that at run-time this was so. It has nothing to do with if I explicitly call a module or through a variable, at *run-time* I have no guarantees. This would mean that you would either have to tag functions at compile time and check at run-time or trap unsafe system calls.
<br><br>- dict (and sets, gb_trees, array, etc ) is actually safe as it does no destructive updates.<br><br>- if you were to detect unsafe functions/system calls then what would it actually *mean* when you hit one. The guard is neither true nor false, just unprovable. Today with only simple type and value tests this is not a problem, for example "when 2 * A > 4" contains an implicit type test of A.
<br><br>- it would make it difficult to functions from "unknown" modules as I would not know if they were safe or not.<br><br>- it would mean that many tests which seem perfectly reasonable and used in code would not be allowed in guards, and this would create confusion to the poor user. Seriously.
<br><br>- the semantics of error handling is different in guards from in expressions (normal function calls). In a guard an error is handled as false while in a normal function call it generates an error. That would mean you have to keep track of where you are in a call-stack and know how to handle errors in this case. For example the (trivial) function:
<br><br>is_even(I) -> (I rem 2) == 0.<br><br>would have to know if it called from a guard or expression. You could wrap user function calls in guards with a try but then I think it is getting a bit heavy in the implementation.
<br><br>- as Joe mentioned guards are just extensions of pattern matching and really shouldn't be considered as anything else.<br><br>- allowing users to do dangerous thing like removing the is_guard_bif checking would be very unsafe and seriously compromise the robustness of the emulator.
<br><br>- really all that is left are functions which just contain expressions which are allowed in guards.<br><br>If you are going to come up with a definition of guards which contain calls to user defined functions then you have cover *every* possible case. Just doing for reasonable usage is not the problem, users are usually unreasonable and will dream up cases which the poor language designer and compiler writer never thought anyone would ever consider doing. We have had this problem before.
<br><br>It would probably be better to define a 'cond' which is an extension of 'if' (i.e. lisp cond) which allows user defined functions in tests but does not have the special error handling in guards.<br>
<br>Robert<br><br><div><span class="gmail_quote">On 27/11/2007, <b class="gmail_sendername">David Holz</b> <<a href="mailto:david_holz@hotmail.com">david_holz@hotmail.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>From: <a href="mailto:rvirding@gmail.com">rvirding@gmail.com</a><br>> I actually defy anyone to come up with a safe, consistent and *understandable* definition of<br>> guards which allow user defined functions. It would also be nice if they were relatively easy
<br>> to implement. Joe, remember our ideas with pipes?<br><br>Hmm, how hard is it really to define?  It seems to me to be exactly like C++ const propagation.  There are a few things which can mutate state (process dict, message send/receive, ets et al, etc):
<br><br>- If a function calls built-in state mutators anywhere in its body, it's not pure functional.<br>- If a function calls any other function that isn't pure functional, it's not pure functional.<br>- If a function calls any M:F via variables instead of explicitly, tag it as not pure functional. (to make it easy to implement for an initial revision)
<br>- Only pure functional functions can be called in guards.<br><br>The only challenging part is the dynamic code loading, which has similar issues to the M:F variable situation.  Inside a guard context, M:F call syntax would have to check the purity of the function it's calling, which can be cached between code loads.  This is really a linking issue, though, and could be theoretically designed not to have any per-call overhead for explicitly stated m:f's.  I'm not saying it's dirt simple to implement, but the idea of contagiously propagating "non-functionalness" shouldn't be difficult to define.
<br><br>I, however, would like to see a setting or switch somewhere to just remove the "is_guard_bif" checking completely, leaving it up to me to not do anything stupid, without inflicting any extra load doing runtime guard checks.  I think it should be straightforward to recompile the compiler myself with "is_guard_bif(_,_) -> true." but I haven't bothered with that yet.
<br><br>_________________________________________________________________<br>Share life as it happens with the new Windows Live.Download today it's FREE!<br><a href="http://www.windowslive.com/share.html?ocid=TXT_TAGLM_Wave2_sharelife_112007">
http://www.windowslive.com/share.html?ocid=TXT_TAGLM_Wave2_sharelife_112007</a><br>_______________________________________________<br>erlang-questions mailing list<br><a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org
</a><br><a href="http://www.erlang.org/mailman/listinfo/erlang-questions">http://www.erlang.org/mailman/listinfo/erlang-questions</a><br></blockquote></div><br>