<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>The problem you describe is not the priority of the ternary operator but that developers just assume a priority without checking (or learning) whether their assumption is correct. Changing the priority won't solve that problem, it would only shift the problem over to those developers assuming the other priority. Worse, it would create this problem for those developers knowing the correct priority, because they now have to relearn the new priority with the added difficulty of the priority being different from C.</div><div><br></div><div>I'm not sure whether the problem really is one (other operators have priorities too, which have to be learned), but assuming for the moment that it is, a solution would be to replace the ternary operator with an if-expression: <b>if</b> condition <b>then</b> expr1 <b>else</b> expr2</div><div>This would enclose the condition between two keywords and thereby be free of misunderstandings.</div><div>Replacing the ternary operator is on the commonly asked changes list, though, and therefore requires new arguments/insights why a replacement would make sense. I think the possibly confusing priority has been discussed already in the past and therefore wouldn't count as new insight, though I'm not quite sure.</div><div><br></div><div>-Thorsten </div><div><br>Am 03.09.2016 um 11:34 schrieb Vladimir.S via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>:<br><br></div><blockquote type="cite"><div><span>(Seems my first email was not resent by mailing list due to its temporary problems. So second attempt)</span><br><span></span><br><span>I'm not sure if it is a correct time to discuss this, if not - I'll hold this for later time.</span><br><span></span><br><span>I was reading the article of author of some C/C++ static code analyzer tool where he was analyzing and discussing about code of some open source program. And there was a paragraph about bugs people make when using ternary operator. There a lot of bugs in C/C++ sources of well-known open source programs(like Chromium, ReactOS, MongoDB, Unreal Engine 4, Wine, FreeBSD Kernel and many others) made when developer assumes that priority of '?:' operator is higher than other operators like '+', '*', '|', '&' and other.</span><br><span></span><br><span>Examples:</span><br><span></span><br><span>int edge_height = titlebar_bottom->height() -</span><br><span> ShouldShowClientEdge() ? kClientEdgeThickness : 0;</span><br><span></span><br><span>ULONG treg = 0x54 + (dev < 3) ? (dev << 1) : 7;</span><br><span></span><br><span>if (IP_PACKET_SIZE < parsedPacket.info.H263.dataLength +</span><br><span> parsedPacket.info.H263.insert2byteStartCode ? 2:0) {...}</span><br><span></span><br><span>stringstream ss;</span><br><span>ss << (sizeof(char *) == 8) ? " 64bit" : " 32bit";</span><br><span></span><br><span>return UniformVectorExpressions.GetAllocatedSize()</span><br><span> + UniformScalarExpressions.GetAllocatedSize()</span><br><span> + Uniform2DTextureExpressions.GetAllocatedSize()</span><br><span> + UniformCubeTextureExpressions.GetAllocatedSize()</span><br><span> + ParameterCollections.GetAllocatedSize()</span><br><span> + UniformBufferStruct</span><br><span> ?</span><br><span> (sizeof(FUniformBufferStruct) +</span><br><span> UniformBufferStruct->GetMembers().GetAllocatedSize())</span><br><span> :</span><br><span> 0;</span><br><span></span><br><span>.. and so on..</span><br><span></span><br><span>Yes, in Swift we have no problem with mixing lets say Ints and Boolean values. But, it seems that it is highly possible to catch the same kind of problem with ternary operator in Swift for boolean values:</span><br><span></span><br><span>func isOne()->Bool { print(1); return false }</span><br><span>func isTwo()->Bool { print(2); return false }</span><br><span></span><br><span>let a = true</span><br><span>let b = true</span><br><span></span><br><span>let result = a || (b) ? isOne() : isTwo() // prints 1</span><br><span></span><br><span>print(result) // false</span><br><span></span><br><span>As you understand, to work correctly we need parentheses:</span><br><span>let result = a || ((b) ? isOne() : isTwo()) // <nothing></span><br><span>print(result) // true</span><br><span></span><br><span>..or set priority of '?:' operator higher than other operators (but this probably could *silently* break old code?)</span><br><span></span><br><span>I was trying to play with custom operators and ternary operator :</span><br><span></span><br><span>func <<(lhs: inout String, rhs: String) { lhs += rhs }</span><br><span>func <<(lhs: inout String, rhs: Bool) { lhs += rhs.description }</span><br><span></span><br><span>let x = 10</span><br><span>var s = ""</span><br><span></span><br><span>s << "abc"</span><br><span>print(s) // abc</span><br><span></span><br><span>s << (x == 10) ? "10" : "not 10"</span><br><span>print(s)</span><br><span></span><br><span>.. but this crashes the compiler(bug reported), but this shows that could be other ways when ternary operator works not as expected by many developers.</span><br><span></span><br><span>I believe the problem is worth to be discussed and probably solved for Swift in near future.</span><br><span></span><br><span>Opinions?</span><br><span></span><br><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>