<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:x="urn:schemas-microsoft-com:office:excel" xmlns:p="urn:schemas-microsoft-com:office:powerpoint" xmlns:a="urn:schemas-microsoft-com:office:access" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:b="urn:schemas-microsoft-com:office:publisher" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:oa="urn:schemas-microsoft-com:office:activation" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:q="http://schemas.xmlsoap.org/soap/envelope/" xmlns:D="DAV:" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ois="http://schemas.microsoft.com/sharepoint/soap/ois/" xmlns:dir="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:dsp="http://schemas.microsoft.com/sharepoint/dsp" xmlns:udc="http://schemas.microsoft.com/data/udc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sps="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:udcxf="http://schemas.microsoft.com/data/udc/xmlfile" xmlns:wf="http://schemas.microsoft.com/sharepoint/soap/workflow/" xmlns:mver="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns:mrels="http://schemas.openxmlformats.org/package/2006/relationships" xmlns:ex12t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:ex12m="http://schemas.microsoft.com/exchange/services/2006/messages" 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:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","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;}
p
        {mso-style-priority:99;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
span.gmailquote
        {mso-style-name:gmail_quote;}
span.e
        {mso-style-name:e;}
span.EmailStyle20
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;}
@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-US link=blue vlink=purple>
<div class=Section1>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'>Inline.<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:#1F497D'><o:p> </o:p></span></p>
<div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in'>
<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span
style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>
ironruby-core-bounces@rubyforge.org
[mailto:ironruby-core-bounces@rubyforge.org] <b>On Behalf Of </b>Curt
Hagenlocher<br>
<b>Sent:</b> Sunday, October 14, 2007 6:52 AM<br>
<b>To:</b> ironruby-core@rubyforge.org<br>
<b>Subject:</b> Re: [Ironruby-core] Experimentation<o:p></o:p></span></p>
</div>
<p class=MsoNormal><o:p> </o:p></p>
<div>
<p class=MsoNormal>Thanks for all of the excellent advice; everything is
now working. I had guessed there might be an issue on the overload with
the specific signature of the function, but I wasn't able to find any examples
of existing code that contradicted what I had done. Now that I know what
to look for, of course... :). I wonder if it wouldn't be a good idea for
the ClassInitGenerator to emit a warning when there's a signature containing a
BlockParam that doesn't follow the correct pattern. <o:p></o:p></p>
</div>
<div>
<p class=MsoNormal> <o:p></o:p></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'>Yes, that’s the plan – CIG will check for other errors as
well.<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:#1F497D'><o:p> </o:p></span></p>
</div>
<div>
<p class=MsoNormal>The /*!*/ annotation seems a bit redundant with [NotNull],
doesn't it? I think I'm just resentful that it's a bunch of characters that
totally interrupt the flow of my typing. :P<br>
<br>
<span style='color:#1F497D'><o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'>Yes, you’re right it seems redundant but unfortunately it’s
not. The problem is that our (i.e. DLR’s) NotNull attribute is currently not
understood by Spec# (static verifier). It’s only influencing the overload
resolution, nothing else. So Spec# would complain that you’re e.g. “dotting
thru” a variable that might be null.<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'>If you can define a macro in your favorite text editor, this is the
right use of that feature. <o:p></o:p></span></p>
<p class=MsoNormal> <o:p></o:p></p>
</div>
<div>
<p class=MsoNormal>I considered merging the block form of the scan function
with the blockless form, but it seemed that the result would be considerably
harder to read and understand than keeping them seperate.<o:p></o:p></p>
</div>
<div>
<p class=MsoNormal><o:p> </o:p></p>
</div>
<div>
<p class=MsoNormal>Is this the sort of change you'd like to see submitted to
the project? If so, I'll write some tests (I know; should have done it
the other way around) and generate another patch file.<br>
<br>
<span style='color:#1F497D'><o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'>Yes, we accept contributions to libraries, i.e. to
IronRuby.Libraries.dll. Although MutableString class will stay where it is, Ruby
method implementations for MutableString will soon get factored out to the
Libraries assembly. Hence we could take your contribution then if it will be
correct and efficient.<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:red'>Tomas<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:#1F497D'><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";
color:#1F497D'><o:p> </o:p></span></p>
<p class=MsoNormal> <o:p></o:p></p>
</div>
<div>
<p class=MsoNormal><span class=gmailquote>On 10/13/07, <b>Tomas Matousek</b>
<<a href="mailto:Tomas.Matousek@microsoft.com">Tomas.Matousek@microsoft.com</a>>
wrote:</span> <o:p></o:p></p>
<div>
<div>
<p style='margin-left:.5in;text-indent:-.25in'>1)
Change the signatures to:<o:p></o:p></p>
<p><span style='font-size:10.0pt'> [<span
style='color:#2B91AF'>RubyMethodAttribute</span>(<span style='color:#A31515'>"scan"</span>,
<span style='color:#2B91AF'>RubyMethodAttributes</span>.PublicInstance)] </span><o:p></o:p></p>
<p><span style='font-size:10.0pt'> <span
style='color:blue'>public</span> <span style='color:blue'>static</span> <span
style='color:#2B91AF'>List</span><<span style='color:blue'>object</span>><span
style='color:green'> /*!*/</span> Scan(<span style='color:#2B91AF'>MutableString</span><span
style='color:green'>/*!*/</span> self, [<span style='color:#2B91AF'>NotNull</span>]<span
style='color:#2B91AF'>MutableString</span><span style='color:green'> /*!*/</span>
searchStr)</span><o:p></o:p></p>
<p><span style='font-size:10.0pt'> </span><o:p></o:p></p>
<p><span style='font-size:10.0pt'> [<span
style='color:#2B91AF'>RubyMethodAttribute</span>(<span style='color:#A31515'>"scan"</span>,
<span style='color:#2B91AF'>RubyMethodAttributes</span>.PublicInstance)] </span><o:p></o:p></p>
<p><span style='font-size:10.0pt'> <span
style='color:blue'>public</span> <span style='color:blue'>static</span> <span
style='color:blue'>object</span> Scan(<span style='color:#2B91AF'>CodeContext</span><span
style='color:green'> /*!*/</span> context, <span style='color:#2B91AF'>MutableString</span><span
style='color:green'>/*!*/</span> self, [<span style='color:#2B91AF'>NotNull</span>]<span
style='color:#2B91AF'>BlockParam</span><span style='color:green'> /*!*/</span>
block, [<span style='color:#2B91AF'>NotNull</span>]<span style='color:#2B91AF'>MutableString</span><span
style='color:green'>/*!*/</span> searchStr)</span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
<p style='margin-left:.75in;text-indent:-.25in'><span style='font-size:11.0pt;
color:#1F497D'>a) Block is a special parameter
and it must follow self parameter. The order of parameters is: </span><o:p></o:p></p>
<p style='margin-left:1.0in;text-indent:-.25in'><span style='font-size:11.0pt;
font-family:Symbol;color:#1F497D'>·</span><span style='font-size:11.0pt;
color:#1F497D'> </span><span
style='font-size:11.0pt;font-family:Symbol;color:#1F497D'> </span><span
style='font-size:11.0pt;color:#1F497D'>context</span> <o:p></o:p></p>
<p style='margin-left:1.0in;text-indent:-.25in'><span style='font-size:11.0pt;
font-family:Symbol;color:#1F497D'>·</span><span style='font-size:11.0pt;
color:#1F497D'> </span><span
style='font-size:11.0pt;font-family:Symbol;color:#1F497D'> </span><span
style='font-size:11.0pt;color:#1F497D'>self </span><o:p></o:p></p>
<p style='margin-left:1.0in;text-indent:-.25in'><span style='font-size:11.0pt;
font-family:Symbol;color:#1F497D'>·</span><span style='font-size:11.0pt;
color:#1F497D'> </span><span
style='font-size:11.0pt;font-family:Symbol;color:#1F497D'> </span><span
style='font-size:11.0pt;color:#1F497D'>block</span><o:p></o:p></p>
<p style='margin-left:1.0in;text-indent:-.25in'><span style='font-size:11.0pt;
font-family:Symbol;color:#1F497D'>·</span><span style='font-size:11.0pt;
color:#1F497D'> </span><span
style='font-size:11.0pt;font-family:Symbol;color:#1F497D'> </span><span
style='font-size:11.0pt;color:#1F497D'>mandatory parameters </span><o:p></o:p></p>
<p style='margin-left:1.0in;text-indent:-.25in'><span style='font-size:11.0pt;
font-family:Symbol;color:#1F497D'>·</span><span style='font-size:11.0pt;
color:#1F497D'> </span><span
style='font-size:11.0pt;font-family:Symbol;color:#1F497D'> </span><span
style='font-size:11.0pt;color:#1F497D'>optional parameters </span><o:p></o:p></p>
<p style='margin-left:1.0in;text-indent:-.25in'><span style='font-size:11.0pt;
font-family:Symbol;color:#1F497D'>·</span><span style='font-size:11.0pt;
color:#1F497D'> </span><span
style='font-size:11.0pt;font-family:Symbol;color:#1F497D'> </span><span
style='font-size:11.0pt;color:#1F497D'>params array (rest parameters) </span><o:p></o:p></p>
<p style='margin-left:.75in;text-indent:-.25in'><span style='font-size:11.0pt;
color:#1F497D'>b) Specify [NotNull] for
parameters that cannot be null in order to select the overload. You can assume
that parameters doesn't have null value when called from a DLR language. It's
not a CLR attribute though so it doesn't prevent a non-dynamic languages to pass
null. Since the library methods are not supposed to be called directly (only
Ruby runtime should invoke the method), you don't need to check for non-nullity
at runtime. Context parameter is always non-null (no need to check for null at
run-time). Self parameter is also non-null unless the method is a module method
or an instance method of NilClass. </span><o:p></o:p></p>
<p style='margin-left:.75in;text-indent:-.25in'><span style='font-size:11.0pt;
color:#1F497D'>c) Annotate types by /*!*/
annotation if you assume them to be non-null. Although the annotation doesn't
affect run-time behavior at all (being a comment, it's ignored by C#) it is
useful for static analysis and expresses your assumptions. </span><o:p></o:p></p>
<p style='margin-left:.75in;text-indent:-.25in'><span style='font-size:11.0pt;
color:#1F497D'>d) Note also that unless marked by
NotNull attribute, BlockParam is nullable. Hence the overload might be eligible
for invocation even though no block has been passed. A null reference is used
if the block is not specified in a call site and there is no overload that
matches better. So a single overload with BlockParam parameter also works. It
depends on the semantics of the method which variant to chose. If presence of
the block significantly changes the behavior of the method then it's probably
better to have two overloads. Code like [RubyMethod("foo")]public
static Foo(… block …) { if (block != null) { 1 <sup>st</sup>
overload implementation } else { 2<sup>nd</sup> overload implementation} }
should be avoided if possible; two overloads should be defined instead. On the
other hand, if the implementation almost doesn't depend on whether the block is
present or not (it only affects a small part of the implementation) then it's
probably better to have a single overload. </span><o:p></o:p></p>
<p style='margin-left:.75in'><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
<p style='text-indent:-.25in'><span style='font-size:11.0pt;color:#1F497D'>2)
Check out dynamic site in Thread.CreateThread. It should do what you need. The
magic is in ArgumentKind.List (splat).</span><o:p></o:p></p>
<p style='text-indent:-.25in'><span style='font-size:11.0pt;color:#1F497D'>3)
Feel free to patch the Rakefile. Note however, that we are going to change the
shape of libraries a little bit (in particular move Builtins to
IronRuby.Libraries.dll), so it might be necessary to adjust the script again
afterwards.</span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'>Note that MutableString has an
instance method IndexOf, so you don't need to convert to a CLR string (the method
internally makes the conversion but that's only provisional implementation). </span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'>Tomas</span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
<div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in'>
<p><b><span style='font-size:10.0pt'>From:</span></b><span style='font-size:
10.0pt'> <a href="mailto:ironruby-core-bounces@rubyforge.org" target="_blank">ironruby-core-bounces@rubyforge.org
</a>[mailto:<a href="mailto:ironruby-core-bounces@rubyforge.org" target="_blank">ironruby-core-bounces@rubyforge.org</a>]
<b>On Behalf Of </b>Curt Hagenlocher<br>
<b>Sent:</b> Saturday, October 13, 2007 8:16 PM<br>
<b>To:</b> <a href="mailto:ironruby-core@rubyforge.org" target="_blank">ironruby-core@rubyforge.org</a><br>
<b>Subject: </b>[Ironruby-core] Experimentation</span><o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
<p>I thought I'd implement some missing members on the String class in order to
get my feet wet and start to understand the software. I chose String.scan
on the grounds that it was a fairly common function (between 20 and 30
references in the standard library) with straightforward semantics, but one
which requires dealing with overloads and blocks. <o:p></o:p></p>
<p>There are basically four variations of this function:<br>
String.scan <string><br>
String.scan <regexp><br>
String.scan <string>, <block><br>
String.scan <regexp>, <block><o:p></o:p></p>
<p>I've attempted to implement each of these, and believe that all but the last
are correct. The <string> variations are implemented in two
different flavors for both CLR strings and mutable strings. A patch can
be found at <a
href="http://hagenlocher.org/software/MutableString.scan.patch.txt"
target="_blank">http://hagenlocher.org/software/MutableString.scan.patch.txt</a><o:p></o:p></p>
<p>The two issues I ran into are as follows:<br>
1) The overload mechanism is picking the wrong method at runtime. Here
are two of the function prototypes:<o:p></o:p></p>
<p>[RubyMethodAttribute("scan", RubyMethodAttributes.PublicInstance)]<br>
public static List<object> Scan(MutableString/*!*/ self,
MutableString/*!*/ searchStr)<o:p></o:p></p>
<div>
<p>[RubyMethodAttribute("scan", RubyMethodAttributes.PublicInstance)]<br>
public static object Scan(CodeContext/*!*/ context, MutableString/*!*/ self,
MutableString searchStr, BlockParam block)<o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
<p><span style='font-size:11.0pt;color:red'> </span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
<p><span style='font-size:11.0pt;color:#1F497D'> </span><o:p></o:p></p>
</div>
<div>
<p>When I run from rbx.exe, I get the following:<o:p></o:p></p>
</div>
<div>
<p>>>> "hello world".scan("l")<br>
=> ["l", "l", "l"]<o:p></o:p></p>
</div>
<div>
<p>>>> "hello world".scan("l") {|x| print x}<br>
=> ["l", "l", "l"]<o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>In contrast, CRuby gives this:<o:p></o:p></p>
</div>
<div>
<p>irb(main):001:0> "hello world".scan("l")<br>
=> ["l", "l", "l"]<br>
irb(main):002:0> "hello world".scan("l") {|x| print x} <br>
lll=> "hello world" <o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>Am I doing something wrong, or is this a bug? (I have obviously
updated Initializer.Generated.cs, or neither scan would have been found :).<o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>2) My implementation of String.scan <regexp>, <block> is
incomplete. This function is defined to behave as follows:<o:p></o:p></p>
</div>
<p> a.scan(/\w+/) {|w| print "<<#{w}>> "
} <br>
a.scan(/(.)(.)/) {|x,y| print y, x }<o:p></o:p></p>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>In other words, the number of parameters being passed to the block is equal
to the number of groups defined in the regular expression -- or 1 if there are
no groups defined. I haven't been able to find way to pass
parameters or define a call site or that would support this. <o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>Finally, it's a bit annoying to rebuild Initializer.Generated.cs. Whenever
you change a method signature, you have to manually delete the appropriate part
of the old file in order to regenerate it, or you'll get an error. I've
made an empty version of that source file and a batch file that copies it on
top of the previous version before rebuilding ClassInitGenerator.
Assuming that the architecture is going to be here for a while, it would be
nice if there were a target in the Rakefile that performed these steps. <o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>After a few more hours of this, I may have to figure out how to do that
myself. :)<o:p></o:p></p>
</div>
<div>
<p> <o:p></o:p></p>
</div>
<div>
<p>--<o:p></o:p></p>
</div>
<div>
<p>Curt Hagenlocher<o:p></o:p></p>
</div>
<div>
<p><a href="mailto:curt@hagenlocher.org" target="_blank">curt@hagenlocher.org</a><o:p></o:p></p>
</div>
</div>
</div>
</div>
<p class=MsoNormal style='margin-bottom:12.0pt'><br>
_______________________________________________ <br>
Ironruby-core mailing list<br>
<a href="mailto:Ironruby-core@rubyforge.org">Ironruby-core@rubyforge.org</a><br>
<a href="http://rubyforge.org/mailman/listinfo/ironruby-core" target="_blank">http://rubyforge.org/mailman/listinfo/ironruby-core</a><o:p></o:p></p>
</div>
<p class=MsoNormal><o:p> </o:p></p>
</div>
</body>
</html>