<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=EN-GB link=blue vlink=purple>
<div class=Section1>
<p class=MsoNormal>In irb we have:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='margin-left:.5in'>1 + true<o:p></o:p></p>
<p class=MsoNormal style='margin-left:.5in'>=> TypeError: true can’t be
coerced into Fixnum<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>In rbx we have:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='margin-left:.5in'>1 + true<o:p></o:p></p>
<p class=MsoNormal style='margin-left:.5in'>=> 2<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>There are the following methods for + in Fixnum:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal><span style='font-size:8.0pt;font-family:"Courier New"'>
<span style='color:blue'>public</span> <span style='color:blue'>static</span> <span
style='color:blue'>object</span> Add(<span style='color:blue'>int</span> self, <span
style='color:blue'>int</span> other)</span><o:p></o:p></p>
<p class=MsoNormal style='margin-left:.5in;text-autospace:none'><span
style='font-size:8.0pt;font-family:"Courier New";color:blue'>public</span><span
style='font-size:8.0pt;font-family:"Courier New"'> <span style='color:blue'>static</span>
<span style='color:blue'>double</span> Add(<span style='color:blue'>int</span>
self, <span style='color:blue'>double</span> other)<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:.5in;text-autospace:none'><span
style='font-size:8.0pt;font-family:"Courier New";color:blue'>public</span><span
style='font-size:8.0pt;font-family:"Courier New"'> <span style='color:blue'>static</span>
<span style='color:blue'>object</span> Add(<span style='color:#2B91AF'>CodeContext</span><span
style='color:green'>/*!*/</span> context, <span style='color:blue'>object</span>
self, <span style='color:blue'>object</span> other)<o:p></o:p></span></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>I expected that passing a bool into + operator would have
ended up at the third overload, which would give the correct behaviour when it
tries to coerce on the bool. But it actually gets mapped to the first
overload and there is an implicit conversion of true to 1. You can see
this in the resulting AST dump:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.5pt;
font-family:"Courier New"'>(FixnumOps.Add)(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.5pt;
font-family:"Courier New"'> (.bound $arg0),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.5pt;
font-family:"Courier New"'> (Converter.ConvertToInt32)(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.5pt;
font-family:"Courier New"'>
(Object)(.bound $arg1),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.5pt;
font-family:"Courier New"'> ),<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:8.5pt;font-family:"Courier New"'>)</span><o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>After some digging I found this method in
Ruby.Runtime.Converter:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'> <span
style='color:blue'>private</span> <span style='color:blue'>static</span> <span
style='color:blue'>bool</span> HasImplicitNumericConversion(<span
style='color:#2B91AF'>Type</span> fromType, <span style='color:#2B91AF'>Type</span>
toType) {<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (fromType.IsEnum) <span style='color:blue'>return</span>
<span style='color:blue'>false</span>;<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (fromType == <span style='color:blue'>typeof</span>(<span
style='color:#2B91AF'>BigInteger</span>)) {<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (toType == <span style='color:blue'>typeof</span>(<span
style='color:blue'>double</span>)) <span style='color:blue'>return</span> <span
style='color:blue'>true</span>;<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (toType == <span style='color:blue'>typeof</span>(<span
style='color:blue'>float</span>)) <span style='color:blue'>return</span> <span
style='color:blue'>true</span>;<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (toType == <span style='color:blue'>typeof</span>(<span
style='color:#2B91AF'>Complex64</span>)) <span style='color:blue'>return</span>
<span style='color:blue'>true</span>;<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>return</span> <span style='color:blue'>false</span>;<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
}<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (fromType == <span style='color:blue'>typeof</span>(<span
style='color:blue'>bool</span>)) {<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>if</span> (toType == <span style='color:blue'>typeof</span>(<span
style='color:blue'>int</span>)) <span style='color:blue'>return</span> <span
style='color:blue'>true</span>;<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
<span style='color:blue'>return</span> HasImplicitNumericConversion(<span
style='color:blue'>typeof</span>(<span style='color:blue'>int</span>), toType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
}<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'>
...<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal>Here you can see that bool is automatically converted to an
int. Is this correct behaviour? I appreciate that we can take any
non-nil value as true and nil as false but not the other way round.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>ASIDE: In fact all three methods are added as “Applicable
Targets” but the int version gets there first. Is there a heuristic for
the order in which overloads are considered?<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Regards,<o:p></o:p></p>
<p class=MsoNormal>Pete<o:p></o:p></p>
</div>
</body>
</html>