|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 | Next > |
|
|
comma vs andalsoI noticed that inets code uses
foo(...) when Condition1 andalso Condition2 -> ... Is the comma deprecated? For example, why not foo(...) when Condition1, Condition2 -> ... A related pet peeve of mine is that the following does not properly indent in the latest Emacs mode handle_info({tcp, Socket, Bin}, State) when State#state.transport /= undefined, State#state.socket == Socket -> ... I have to manually insert spaces to align State#state... above and using andalso above does not help either. Thanks, Joel --- Mac hacker with a performance bent http://www.linkedin.com/in/joelreymont ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoJoel Reymont <joelr1@...> writes:
> A related pet peeve of mine is that the following does not properly > indent in the latest Emacs mode > > handle_info({tcp, Socket, Bin}, State) > when State#state.transport /= undefined, > State#state.socket == Socket -> > ... > > I have to manually insert spaces to align State#state... above and > using andalso above does not help either. I found that this happens because there is a "." in the guard. This change to erlang-mode (actually erlware-mode, but the code should be similar) seems to fix it: diff --git a/erlang.el b/erlang.el index 6ad03ea..916037e 100644 --- a/erlang.el +++ b/erlang.el @@ -2097,7 +2097,7 @@ Value is list (stack token-start token-type in-what)." ((looking-at "when[^->\.]*case[^->\.]*->")) ((looking-at "when[^->\.]*receive[^->\.]*->")) ;; Normal when case - ((looking-at "when [^->\.]*->") + ((looking-at "when [^->]*->") (erlang-push (list 'when token (current-column)) stack)) ((looking-at "after[.]+->") (erlang-push (list 'icr token (current-column)) stack)) Not sure what other cases that would mess up, though. The comment above mentions one possible gotcha: ;; In test suites you may want to do something like ;; ?match(Mem when integer(Mem), mnesia:table_info(Tab, ;; memory)), and then the following if/case/receive ;; statement will mess up the indentation by fooling the ;; erlang mode to think the 'when' in the argument is a ;; "real" when. The following three clauses will avoid ;; this problem. -- Magnus Henoch, magnus@... Erlang Training and Consulting http://www.erlang-consulting.com/ ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn 06/lug/09, at 13:13, Joel Reymont wrote: > I noticed that inets code uses > > foo(...) when Condition1 andalso Condition2 -> ... > > Is the comma deprecated? For example, why not > > foo(...) when Condition1, Condition2 -> ... the difference is very simple. comma indicates that both guard operators need to be evaluated, while on the contrary 'andalso' means that the second condition is evaluated ONLY if condition1 is true. same goes for 'orselse'. this is particularly relevant when condition2 would result for instance in an evaluation error if condition1 is not met, as in: foo(..) when (islist(X) == true ansalso (lists:nth(1,X) == 'test') -> .. hope this clears. r. ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn 06/lug/09, at 14:19, Roberto Ostinelli wrote: > foo(..) when (islist(X) == true ansalso (lists:nth(1,X) == 'test') - > > .. that would be foo(..) when (islist(X) =:= true) ansalso (lists:nth(1,X) =:= 'test') - > .. pardon me i was in python mode. r. ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn Mon, Jul 6, 2009 at 2:21 PM, Roberto Ostinelli <roberto@...>wrote:
> > On 06/lug/09, at 14:19, Roberto Ostinelli wrote: > > foo(..) when (islist(X) == true ansalso (lists:nth(1,X) == 'test') -> .. >> > > that would be > > foo(..) when (islist(X) =:= true) ansalso (lists:nth(1,X) =:= 'test') -> .. > '==' and '=:=' are equivalent except when applied to numbers, are they not? (1 == 1.0) is true, while (1 =:= 1.0) is false. When applied to atoms, as in your example, there is no difference. And the difference between comma and 'andalso' doesn't actually matter much for the purpose of avoiding evaluation errors in guard context, since such an error in a guard just means that the guard fails. For instance, try this: 1> length(a). ** exception error: bad argument in function length/1 called as length(a) 2> Foo = fun(X) when length(X) > 3 -> "Long list"; (X) -> "Short or no list" end. 3> Foo(a). "Short or no list" Also, lists:nth(X) is an illegal guard expression. ;) |
|
|
|
|
|
Re: comma vs andalsoRoberto Ostinelli wrote:
> the difference is very simple. comma indicates that both guard operators > need to be evaluated, while on the contrary 'andalso' means that the > second condition is evaluated ONLY if condition1 is true. same goes for > 'orselse'. No, the comma separator in guards also uses short-cut evaluation and will not evaluate the subsequent tests if one test fails. If there are alternatives expressed with semicolon, the next such alternative will be tried instead; otherwise, the whole guard fails. What you describe is true for the 'and' operator compared to 'andalso'. /Richard ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
|
|
|
Re: comma vs andalsoRoberto Ostinelli wrote:
> let me point another (and correct) example then: > > foo(..) when X =/= 0 andalso 1/X > 0.1 -> .. > > the following expression would fail instead: > > foo(..) when X =/= 0, 1/X > 0.1 -> .. Aye, but an exception in a guard test is always caught and treated as if the test evaluated to "false". In this example, there is no observable difference between the two. /Richard ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn Jul 6, 3:25Â pm, Roberto Ostinelli <robe...@...> wrote:
> > 1> F3 = fun(X) when X=/=0 and (1/X > 0.1) -> true; (_) -> false end. > #Fun<erl_eval.6.13229925> > 2> [ F3(X) || X <- [0, 0.0, 0.1, 10, 9]]. > [false,false,false,false,false] Ah, but that's because the expression (0 and (1/X > 0.1)) is bad. (I've learned to be very afraid of how strongly 'and' binds. ;)) By contrast, 25> F4 = fun(X) when (X =/= 0) and (1/X > 0.1) -> true; (_) -> false end. #Fun<erl_eval.6.13229925> 26> [ F4(X) || X <- [0, 0.0, 0.1, 10, 9]]. [false,false,true,false,true] And to iterate my previous point, 28> F5 = fun(X) when 1/X > 0.1 -> true; (_) -> false end. #Fun<erl_eval.6.13229925> 29> [F5(X) || X <- [0, 0.0, 0.1, 10, 9]]. [false,false,true,false,true] ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Re: comma vs andalsoOn 06/lug/09, at 15:52, whongo@... wrote: > > Ah, but that's because the expression (0 and (1/X > 0.1)) is bad. > (I've learned to be very afraid of how strongly 'and' binds. ;)) definitely interesting. i guess you've learned it the hard way :) r. |
|
|
Re: comma vs andalsoOn Jul 7, 2009, at 12:19 AM, Roberto Ostinelli wrote: > the difference is very simple. comma indicates that both guard > operators need to be evaluated, while on the contrary 'andalso' > means that the second condition is evaluated ONLY if condition1 is > true. same goes for 'orselse'. He's wrong, but he's not _crazy_. Section 6.24 of the reference manual _ought_ to explain this clearly, but doesn't. -------------------------- 6.24 Guard Sequences A guard sequence is a sequence of guards, separated by semicolon (;). The guard sequence is true if at least one of the guards is true. (The remaining guards, if any, will not be evaluated.) Guard1;...;GuardK A guard is a sequence of guard expressions, separated by comma (,). The guard is true if all guard expressions evaluate to true. GuardExpr1,...,GuardExprN -------------------------- I propose rewriting these paragraphs something like this: A guard sequence is a sequence (G1;...;Gk) of guards separated by semicolons. Guards are tested from left to right. If some guard succeeds, the guard sequence as a whole succeeds, and the remaining guards will not be checked. If all guards fail, the guard sequence as a whole fails. A guard is a sequence (GE1,...,GEn) of guard expressions separated by commas. Guard expressions are tested from left to right. If some guard expression fails, the guard as a whole fails, and the remaining guard expressions will not be checked. If all guard expressions succeed, the guard as a whole suceeds. A guard expression is a very special restricted expression. It is said to succeed it it evaluates to true. It is said to fail if it evaluates to anything else or raises an exceptions. Exceptions never propagate out of guard expressions, they are just taken as lack of success. (then continue with the existing third paragraph) ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn Tue, Jul 07, 2009 at 12:47:23PM +1200, Richard O'Keefe wrote:
> > I propose rewriting these paragraphs something like this: <snip> I found your explanation a *lot* clearer and even learned something reading it, so I'd definitely agree that it's an improvement. I'm still unclear as to where 'andalso' differs from a comma though, how is true, false. any different from true andalso false. Andrew ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn 07/lug/2009, at 02.47, "Richard O'Keefe" <ok@...> wrote:
> > On Jul 7, 2009, at 12:19 AM, Roberto Ostinelli wrote: >> the difference is very simple. comma indicates that both guard >> operators need to be evaluated, while on the contrary 'andalso' >> means that the second condition is evaluated ONLY if condition1 is >> true. same goes for 'orselse'. > > He's wrong, but he's not _crazy_. > Section 6.24 of the reference manual _ought_ to explain this > clearly, but doesn't. that is the paragraph i'd been referring to and apparently i had been interpreting it wrongly. i thought this had already been cleared yesterday and yes, an editing as proposed would be a good thing, i might not be the only one doing so. r. ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoOn Jul 7, 2009, at 4:16 PM, Andrew Thompson wrote: > I found your explanation a *lot* clearer and even learned something > reading it, so I'd definitely agree that it's an improvement. Purr. > > I'm still unclear as to where 'andalso' differs from a comma though, > how > is > > true, false. > > any different from > > true andalso false. First, some historical background. Erlang was influenced by Prolog via Strand-88. (By the way, does anyone have a Strand manual they don't want?) In Prolog, there is one and only one way to get and-then (,) and one and only one way to get or-else (;). To oversimplify, <disjunction> ::= <conjunction> {';' <conjunction>}... <conjunction> ::= <primary> {',' <primary>}... <primary> ::= ['\+'] ( <call> | '(' <disjunction> ')' ) <call> ::= <atom>['(' <arguments> ')'] One of the things I've left out of that is infix, prefix, and postfix operators. So something like cousin_sibling_or_self(X, Y) :- ( father(X, P) ; mother(X, P) ), ( father(Y, Q) ; mother(Y, Q) ), ( father(P, G) ; mother(P, G) ), ( father(Q, G) ; mother(Q, G) ). is possible, where "or" is nested inside "and". Let's return to Erlang. This syntax was adopted for Erlang guards, *ALMOST*. (It was also adopted for Erlang function bodies, almost. The C-like use of comma in Erlang expressions is rooted in Prolog's comma, not C's.) The *ALMOST* part is that Erlang does not allow nesting. You cannot write f(X, Y) when (X == 1 ; X == 2), (Y == 1 ; Y == 2) -> You aren't even allowed to write (GE1,GE2),GE3 but *must* write GE1,GE2,GE3. Nor may you write G1;(G2;G3). Weird. This has never made sense to me. Such combinations are perfectly meaningful, and allowing them would make the definition of some guard macros considerably easier. The obvious thing to do is to remove this arbitrary restriction. That's not the path Erlang took. (Honestly, you couldn't make this stuff up.) Instead, *new* operators 'andalso' and 'orelse' (copied from SML, which is a fine language with some fine compilers) were added. Most of the time, you can use 'andalso' and 'orelse' in a guard, where you would have used ',' and ';'. "Most of the time" means "when under the normal rules of evaluation you would certainly not have had an exception." Let's take two apparently similar functions: f(X) when is_atom(element(3, X)) ; true -> 42. g(X) when is_atom(element(3, X)) orelse true -> 42. By actual test, f(99) -> 42. By actual test, g(99) -> a function_clause exception. That is, in a guard, an expression using 'andalso' or 'orelse' is still an expression, and if an exception occurs in the left-hand operand, the whole expression is still skipped. The thing is that 'andalso' and 'orelse' can be used in any expression, not just guards. Erlang is treating them in guard expressions exactly the same way that it treats them in any other expressions. And that's _different_ from the way ',' and ';' are treated when there's an exception. I conclude that (1) you had best be EXTREMELY cautious about using 'andalso' and 'orelse' in guards; they are NOT drop-in replacements for ',' and ';', and (2) it is long past time that Erlang allowed nested use of ',' and ';' in guards. ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalso> I conclude that > (1) you had best be EXTREMELY cautious about using 'andalso' > and 'orelse' in guards; they are NOT drop-in replacements > for ',' and ';', and > (2) it is long past time that Erlang allowed nested use of > ',' and ';' in guards. (3) this topic should be discussed in details (with examples) in the doc. Alpar ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalso----- Original Message ---- > From: Richard O'Keefe <ok@...> > > Let's take two apparently similar functions: > > f(X) when is_atom(element(3, X)) ; true -> 42. > > g(X) when is_atom(element(3, X)) orelse true -> 42. > > By actual test, f(99) -> 42. > By actual test, g(99) -> a function_clause exception. > > That is, in a guard, an expression using 'andalso' or > 'orelse' is still an expression, and if an exception > occurs in the left-hand operand, the whole expression > is still skipped. > I conclude that > (1) you had best be EXTREMELY cautious about using 'andalso' > and 'orelse' in guards; they are NOT drop-in replacements > for ',' and ';', and > (2) it is long past time that Erlang allowed nested use of > ',' and ';' in guards. Guards are an awful mess in Erlang. I'd be quite surprised if the above difference in behaviour was intentional. If so, what possible purpose does it serve? At one point, you could also use "and"/"or", the boolean operators manque, in guards. (I haven't checked recently whether this is still the case.) So we then have three very similar sets of guard operators. Not to mention the twin set of type tests, introduced, as far as I know, to get rid of the lone double entendre of float/1 (as a test or conversion not the most frequent of operations). And now, for our convenience, the shorter form of these tests is being deprecated. Sigh. Best, Thomas ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoThomas Lindgren wrote:
> ----- Original Message ---- >> From: Richard O'Keefe <ok@...> >> That is, in a guard, an expression using 'andalso' or 'orelse' is >> still an expression, and if an exception occurs in the left-hand >> operand, the whole expression is still skipped. > > Guards are an awful mess in Erlang. I'd be quite surprised if the > above difference in behaviour was intentional. If so, what possible > purpose does it serve? It is intentional in the respect that 'andalso'/'orelse' behave just like any other operator in a guard test. As for purpose, all Erlang's operators are allowed in guard expressions, so why make an exception? > At one point, you could also use "and"/"or", the boolean operators > manque, in guards. (I haven't checked recently whether this is still > the case.) So we then have three very similar sets of guard > operators. 'and'/'or' have always (as far back as I can remember, anyway) been allowed in guards, again, probably simply by virtue of being general operators in the language. And they don't behave like ','/';' either. So to add to Richard O'Keefe's examples: h(X) when is_atom(element(3, X)) or true -> 42. which for h(99) behaves just like the orelse version, i.e., throws a function_clause error. Quite simply, and/or/andalso/orelse behave just like +, ==, or any other operator; compare e.g.: i(X) when is_atom(element(3, X)) == true -> 42. > Not to mention the twin set of type tests, introduced, as far as I > know, to get rid of the lone double entendre of float/1 (as a test or > conversion not the most frequent of operations). That was one details, yes, but the main reason was to make it possible to refactor a piece of code without being forced to change the names of the function tests if you moved an expression from within a guard to an ordinary expression and vice versa. Recall that before the is_... versions, there was no way of saying e.g., "Bool = (is_integer(X) and is_atom(Y))" without writing a case/if or a separate predicate function. The old type tests didn't correspond to any built-in functions, so you had to treat them as "primops" inside the compiler, you couldn't refer to them and pass them around, etc. But the old type test names "atom(X)" and so forth could not simply be made to work outside guards because there would be name clashes (with the float(X) bif and with any existing code that defined a function such as list(X) or integer(X)), hence the is_... prefix for the generally usable versions that are proper built-in functions (defined in the 'erlang' module along with all the others). Now that we have the new is_-forms, the old forms are merely an obstacle to refactoring. As a simple example, this macro nowadays works in both guard expressions and in general expressions - it didn't back then: -define(is_a_foo(X), (is_integer(X) or is_binary(X))). (we can even use orelse here, and it will still work in a guard). > And now, for our convenience, the shorter form of these tests is being > deprecated. Hold your horses - nobody is deprecating the use of ',' and ';'. But as Richard O'Keefe has rightly described, they *are* different from the plain boolean operators. A guard has the following general form: ... when *, ..., * ; *, ..., * ; ... -> that is, one or more semicolon-separated alternatives, each consisting of one or more comma-separated _tests_ (marked with a * here). Each test is (conceptually) evaluated in a try/catch that simply transforms any exception into 'false'. (Subexpressions of a test are evaluated as normal, which is why 'orelse' does not continue executing if there is an exception in the left-hand expression.) This fail-to-false behaviour was in my opinion a mistake, because it occasionally hides a bug in the guard and turns what should have been an observable runtime crash into a silent "well, we take the next clause then". Some people like to use this as a trick to write more compact guards, but that makes it hard for someone reading the code to tell whether the crash-jumps-to-the-next-case is intentional or not. However, Erlang seems to be stuck with these semantics of guards. But it means that if you do things inside your guard test like element(N,T), length(Xs), or anything else that could crash if it gets bad arguments, you need to think about the effect on what clause, if any, will be selected. The thing to remember is that exceptions always stop at the top of each separate test in the guard. Complicated expressions that might throw an unwanted exception are generally better evaluated before the switch, so that bugs are not hidden. I'm not sure I have any real arguments against nesting of ','/';', but I fear the grammar could get rather messy, and that such nested guards could be quite difficult to read in practice. /Richard ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalsoThomas Lindgren wrote:
> Not to mention the twin set of type tests, introduced, as far as I > know, to get rid of the lone double entendre of float/1 (as a test or > conversion not the most frequent of operations). And now, for our > convenience, the shorter form of these tests is being deprecated. > Sigh. Oh, and I forgot this beauty, which is a consequence of the doubleplusweird scope rules for the old type tests in guards: 1> if integer(42) -> ok; true -> no end. ok 2> if integer(42) == true -> ok; true -> no end. * 1: illegal guard expression because, you see, it is only at the absolute top of the guard test that the name 'integer(X)' can be used to refer to the type test. Shove it into one side of an '==', and it is no longer recognized. The new forms work everywhere: 3> if is_integer(42) == true -> ok; true -> no end. ok 4> if is_integer(42) == true -> ok; true -> no end. ok And for my final trick, here's the old double entendre you mentioned: 5> if float(3.14) -> ok; true -> no end. ok 6> if float(3.14) == true -> ok; true -> no end. no why, isn't it obvious? The first clause uses the type test float(X), while the second ensures that 3.14 is cast to a float and then compares the number to 'true'. Sticking to the modern is_-forms of the type tests lets you stay sane. /Richard ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: comma vs andalso2009/7/8 Richard Carlsson <richardc@...>
> Thomas Lindgren wrote: > > Not to mention the twin set of type tests, introduced, as far as I > > know, to get rid of the lone double entendre of float/1 (as a test or > > conversion not the most frequent of operations). And now, for our > > convenience, the shorter form of these tests is being deprecated. > > Sigh. > > Oh, and I forgot this beauty, which is a consequence of the > doubleplusweird scope rules for the old type tests in guards: > > 1> if integer(42) -> ok; true -> no end. > ok > 2> if integer(42) == true -> ok; true -> no end. > * 1: illegal guard expression > > because, you see, it is only at the absolute top of the guard test > that the name 'integer(X)' can be used to refer to the type test. > Shove it into one side of an '==', and it is no longer recognized. It has nothing to do with scope rules really. In the original guards only simple tests were allowed so there was no problem. It only became weird when expressions were allowed. Life was simpler in the old days! :-) Robert |
| < Prev | 1 - 2 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |