tag:blogger.com,1999:blog-12467669.post8616756961731356784..comments2023-04-29T07:23:25.825-04:00Comments on Jay Fields' Thoughts: Ruby: operator precedence of && and = (which also applies to || or)Jayhttp://www.blogger.com/profile/14491442812573747680noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-12467669.post-23713069612566915822008-05-01T14:10:00.000-04:002008-05-01T14:10:00.000-04:00Wait a minute. The problem is totally with your ex...Wait a minute. The problem is totally with your example. Why do you think that "it should be obvious that setting the total to true or false is not the intended behavior"???<BR/><BR/>total = shopping_cart.empty? and shopping_cart.total<BR/><BR/>As a sentence this says to me, set total to the value of the emptiness of the shopping cart and the the total of the shopping cart combined (true && 100, or false && 100). Not knowing anything about Ruby, I would expect a true or a false back.<BR/><BR/>Of course, Ruby is more generous than that; it will actually give you back the total.<BR/><BR/>>> shopping_cart_empty = true<BR/>=> true<BR/>>> shopping_cart_total = 100<BR/>=> 100<BR/>>> total = shopping_cart_empty and shopping_cart_total<BR/>=> 100<BR/>>> total = (shopping_cart_empty and shopping_cart_total)<BR/>=> 100<BR/>=> true<BR/><BR/>Most programmers would write that sentence the other way, though, since the shopping_cart.total seems to be what's important and the emptiness of the shopping cart is a limiting condition:<BR/><BR/>total = shopping_cart.total and shopping_cart.empty?<BR/><BR/>>> total = shopping_cart_total and shopping_cart_empty<BR/>=> true<BR/>>> total = shopping_cart_total && shopping_cart_empty<BR/>=> true<BR/>>> total = (shopping_cart_total && shopping_cart_empty)<BR/>=> true<BR/>>> shopping_cart_empty = false<BR/>=> false<BR/>>> total = (shopping_cart_total && shopping_cart_empty)<BR/>=> false<BR/><BR/>This shows that the first term is checked and the second value is given if it is true, false if not. Actually, the not-true value is given:<BR/><BR/>>> shopping_cart_empty = nil<BR/>=> nil<BR/>>> total = shopping_cart_total and shopping_cart_empty<BR/>=> nil<BR/>>> total = shopping_cart_empty and shopping_cart_total<BR/>=> nil<BR/> <BR/>In the other order, 100 was returned because it had a not-nil value and was the second term. <BR/><BR/>As others have said, it makes much more sense to just say:<BR/><BR/>total = shopping_cart_total if shopping_cart_empty<BR/><BR/>'and' doesn't make a lot of sense if you're interested in a value and not a boolean comparison. Getting out a non-boolean value is just a hack. We should look at why Ruby programmers think you can do this ever:<BR/><BR/>>> bar = nil<BR/>=> nil<BR/>>> baz = "hello"<BR/>=> "hello"<BR/>>> foo = bar or baz<BR/>=> "hello"<BR/>>> foo = baz or bar<BR/>=> "hello"<BR/>>> foo = (baz or bar)<BR/>=> "hello"<BR/>>> baz = nil<BR/>=> nil<BR/>>> foo = (baz or bar)<BR/>=> nil<BR/><BR/>The 'or' behavior is more intuitive, because you can get either the left or the right one back, depending on whether the first term is nil or not. In the case where both baz and bar are nil, you're technically getting bar back:<BR/><BR/>>> baz = nil<BR/>=> nil<BR/>>> bar = false<BR/>=> false<BR/>>> foo = (baz || bar)<BR/>=> false<BR/>>> foo = (bar || baz)<BR/>=> nil<BR/>>> foo = bar or baz<BR/>=> nil<BR/><BR/>So it's the same as the and behavior. In an and, when two things together are 'and', you get the right term back. In an or, when two things together are neither of them true, you get the right not-true value. I don't see that assignment is the problem.<BR/><BR/>Please tell me if I'm full of it.Unknownhttps://www.blogger.com/profile/07766887018847028504noreply@blogger.comtag:blogger.com,1999:blog-12467669.post-6308293288391031422007-08-16T11:50:00.000-04:002007-08-16T11:50:00.000-04:00The append operator is the same way!I recently cam...<B>The append operator is the same way!</B><BR/>I recently came across a problem doing:<BR/>x = []<BR/>x << y ? "something" : ""<BR/><BR/>DOES NOT WORK because the precidence of << is higher than ?: operator. How can this be? When is that useful?<BR/><BR/>-DavidUnknownhttps://www.blogger.com/profile/13301605934853350720noreply@blogger.comtag:blogger.com,1999:blog-12467669.post-66285211493516963202007-08-07T12:13:00.000-04:002007-08-07T12:13:00.000-04:00The set of rules to avoid these problems is very s...The set of rules to avoid these problems is very simple, imo:<BR/><BR/><B>Use "and" and "or" when asignments are not involved. </B><BR/>ie: <BR/>if thinga and thing b <BR/>...<BR/>end<BR/><BR/><B> Use "&&" and "||" when asignment is involved</B> <BR/>ie: result= a || b<BR/><BR/><B> Never mix them!!! </B><BR/>ie: result= a || b and c<BR/>(note you can use them to avoid the need to parentesis here, but maybe is to much to take into account and error prone)Emmanuelhttps://www.blogger.com/profile/06017463228937154219noreply@blogger.comtag:blogger.com,1999:blog-12467669.post-66220227823834399832007-08-05T21:48:00.000-04:002007-08-05T21:48:00.000-04:00"why write something so tricky?"Because the versio..."why write something so tricky?"<BR/><BR/>Because the version you posted isn't an example that demonstrates how behavior changes based precedence.<BR/><BR/>If I were trying to solve the problem, I too would prefer the snippet you posted, but that wasn't the point.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-12467669.post-2068082312528942012007-08-05T21:18:00.000-04:002007-08-05T21:18:00.000-04:00Agree with jchris. It's more readable, and faster ...Agree with jchris. It's more readable, and faster to boot (from a couple of quick benchmarks I just decided to do anyways).Unknownhttps://www.blogger.com/profile/01523051878088364301noreply@blogger.comtag:blogger.com,1999:blog-12467669.post-65916348190200904502007-08-05T20:44:00.000-04:002007-08-05T20:44:00.000-04:00why write something so tricky?total = shopping_car...why write something so tricky?<BR/><BR/>total = shopping_cart.total unless shopping_cart.empty?J Chris Ahttps://www.blogger.com/profile/11598260533932670972noreply@blogger.comtag:blogger.com,1999:blog-12467669.post-18646767328888029672007-08-05T19:23:00.000-04:002007-08-05T19:23:00.000-04:00nIf you look back at the history of Perl, which is...nIf you look back at the history of Perl, which is where 'and' and 'or' come from, they were explicitly introduced not for readability, but because sometimes the low precedence operators were what you wanted.<BR/><BR/>In Perl, with it's assignment contexts, it really makes sense. Code like:<BR/><BR/>my @fileinfo = stat($file) or die;<BR/><BR/>behaves very differently from:<BR/><BR/>my @fileinfo = stat($file) || die<BR/><BR/>In the second case, the stat gets forced into a scalar context, which is almost certainly not what you want.<BR/><BR/>About the only place you see the 'english' logical operators in good perl is in the 'assignment or die' idiom. In Ruby it makes sense to use them in that context too:<BR/><BR/> value = possibly_false || raise "foo"<BR/><BR/>is a syntax error, and so is:<BR/><BR/> (value = possibly_false) || raise "foo"<BR/><BR/>but<BR/><BR/> value = possibly_false or raise "foo"<BR/><BR/>works fine.<BR/><BR/>Me, I like the '... or raise' approach, but that's pretty much the only place I'd ever use 'or'. As for 'and', it's almost completely useless, but once you've got 'or'...Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-12467669.post-81200125088272684532007-08-05T15:32:00.000-04:002007-08-05T15:32:00.000-04:00Though I prefer 'and' and 'or' for readability, I ...Though I prefer 'and' and 'or' for readability, I no longer use either, ever. Using && and || exclusively obviates subtle bugs popping up due to the precedence issues you mention here. Those kinds of bugs aren't worth the pinch of readability sugar the word forms provide.Anonymousnoreply@blogger.com