<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Zaki.asia</title>
    <link>http://zaki.asia</link>
    <atom:link href="http://zaki.asia/rss.xml" rel="self" type="application/rss+xml" />
    <description>zaki.asia - Personal blog of Zoltan Dezso</description>
    <language>en-us</language>
    <pubDate>Sun, 18 Dec 2011 09:01:15 -0800</pubDate>
    <lastBuildDate>Sun, 18 Dec 2011 09:01:15 -0800</lastBuildDate>

    
    <item>
      <title>Startup Weekend Notes</title>
      <link>http://zaki.asia/2011/11/28/startup-weekend-notes.html</link>
      <pubDate>Mon, 28 Nov 2011 01:55:18 -0800</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2011/11/28/startup-weekend-notes</guid>
      <description>&lt;p&gt;I went to &lt;a href=&quot;http://tokyo.startupweekend.org&quot;&gt;Startup Weekend Tokyo&lt;/a&gt; in November 2011. Below are my unrefined notes about this
experience.&lt;/p&gt;

&lt;h1&gt;Day 1 - Pitches&lt;/h1&gt;

&lt;h2&gt;Half Baked&lt;/h2&gt;

&lt;p&gt;Things started off with a game called &quot;Half Baked&quot;. There is a list of - usually
weird - words from which each team choose two. Those two words will be the name
of the teams' imaginary companies for which each team must come up with a pitch. In five
minutes (time pressure is a recurring theme at Startup Weekend - just like in real life).&lt;/p&gt;

&lt;p&gt;This game is intended to represent Axiom #1:&lt;/p&gt;

&lt;h6&gt;It is not the Idea but the Team that makes a successful startup.&lt;/h6&gt;

&lt;p&gt;Now I'm of the opinion that that proponents of this axiom might have the causality relationship
upside down: the most important part for any startup is the idea. However a good team is necessary
to find that idea (unless you already have a bulletproof idea, which you probably don't)&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;1 - The IDEA is the most important part of a startup. A great TEAM is the best way to it.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;When I threw ideas out in a brainstorming fashion, those were taken as fully formed ideas and were
not challenged. I can't just write this off as a cultural curiosity. Japanese do tend to be conflict-averse
to a pathological level, but these are surely the best and are pioneers. My... uhm... half-baked
idea was selected almost unanimously in a team vote.&lt;/p&gt;

&lt;p&gt;Five minutes preparation time went away pretty quickly and at the end we didn't really have the pitch
down, which put the guy who volunteered to pitch in an unenviable tough position. And to my utter
surprise he built a case out of thin air - he pulled it off spectacularly.&lt;/p&gt;

&lt;h2&gt;The pitch&lt;/h2&gt;

&lt;p&gt;Sixty seconds is not a lot of time to introduce the problem and the proposed solution in a memorable
way. This task is not helped by the fact that everyone pitches and sooner or later (and let me tell
you that it's sooner) &lt;strong&gt;pitch fatigue&lt;/strong&gt; sets in. Out of the 60 or so pitches, after a week, I remember
maybe 3 or 4 and one of them is the pitch of the above guy that I was specifically keeping an eye on
and his cause is helped by the fact that he got selected and that he failed miserably at coming up
with even a hint of project to do and the team dissolved on the first day (although later I understood
that in fact he only wanted to practice the pitch and as such did a brilliant job).&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;2 - More than one pitch causes pitch fatigue. Make sure you have undivided attention.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;There were two problems with my pitch. The first is a cosmetic issue, namely that I was literally
shaking from anxiety. I suck at public speaking but wasn't aware of just how much. And I wasn't aware
how much that is not a unique problem. On the one hand, probably no one else noticed and on the other,
I was looking at others and most everyone was nervous on the stage. I am glad I pushed myself to do it.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;3 - Everyone sweats it. You just have to push yourself.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;The second issue is that I did not articulate the solution as well as I did for the problem. I had
13 seconds left after I introduced the solution and made the split-second decision to not risk botching
it by making a clearer connection between problem and solution. Probably I should have practiced more
beforehand, but the thing I noticed is that with all these problems, my pitch was pretty decent
compared to the other 59. It didn't make the cut, but came closer than I hoped - to the point where
I was actually afraid it might get selected and I have to lead a team (got to third place in the
online voting).&lt;/p&gt;

&lt;p&gt;Looking back, I think I actually sounded confident and brought up a problem that everyone actually had.
I had been mulling over this project for a very long time now (this is unfortunately my MO) and had
a fairly good idea of what I am trying to achieve. From the people who got selected, sounding confident
and telling a story that resonates with the audience are the most important parts of the pitch.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;4 - Tell a story. Sound confident. Involve the audience.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;As I mentioned, I had things thought through before. I thought about target segments, business models,
revenue streams even pivot options if things go awry. Overkill? Definitely. People who got selected
with a few exceptions had absolutely no idea what they are going to build and how they are going to
succeed. As it turns out, two teams dissolved shortly after getting selected. Talk about high failure
rate in startups :)&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;5 - A good pitch is a poor indicator of future success.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;In fact, thinking about it, probably the most successful startups are the ones that don't really
pitch, because there is no way they could not not do what they are doing.&lt;/p&gt;

&lt;h1&gt;Day 1 - Team Building&lt;/h1&gt;

&lt;p&gt;Now, that the 12 teams have been selected, there was a little time to go around and decide on which
team to join. At some point I got the feeling that none of the teams are actually very good. There
were 3 or 4 I didn't really consider from the start. Another 3-4 that didn't really have the slightest
clue of what they are going to do. In the end I decided to not worry too much about it and just have
fun.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;6 - Startup Weekend is NOT a realistic simulation of a startup. Just have fun.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;While in the end I think I got to know great people, out of the 90 or so people
in the room, I would not consider starting a company with maybe 85 (would still work with most,
just didn't feel a connection that's strong enough for starting a company together).
Startup Weekend foregoes something I regard one of the highest priorities in
early startups: getting the best people. It'd be a good idea to tailor the pitch
so that the best people get interested in your idea.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;7 - Get the best people&lt;/h4&gt;&lt;/blockquote&gt;

&lt;h1&gt;Day 2 - Discussions&lt;/h1&gt;

&lt;p&gt;The first half of the second day is when the team really gets together for the first time and discusses
what they are going to do. I was sort of lucky to join a team that mostly knew what to build. Even
with that advantage, it takes a long time to get on the same page.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;8 - Communicate early and often.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;I said I was sort of lucky to join a team that mostly knew what to build. I lied. One of the most
important ingredients was missing, which lead to a lot of rethinking later on: the business model.
As a corollary, the target segment and the revenue model were also up in the air. Free from the
constraints and pressures of Startup Weekend, this would be a great side project that might or might
not become a full business, but that's not what Startup Weekend is about.&lt;/p&gt;

&lt;p&gt;Startup Weekend is about finding/founding the startup that will change the world. A side business or
and interesting idea will not win regardless of how feasible it might be as a real business. After
a lot of thinking, I believe that our team would have been able to build a real company on the idea.
We executed pretty well on a small problem (being one of the really few teams that actually had some
sort of product to show) and that could grow into a profitable venture. But it's not something that
would change the world.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;9 - There is a fundamental difference between a project and a startup.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;It was surprising to learn that no one in my team knew the Lean Canvas or personas or customer
validation etc. I was sweating these things when preparing for my pitch so at least could bring up
these tools. In the end though, probably we went into production mode too early, which bit us in the
final presentation.&lt;/p&gt;

&lt;h1&gt;Day 2 - Development&lt;/h1&gt;

&lt;p&gt;We went into production mode. Or at least I did. That's what I enjoy most. Building things, working
out issues, coming up with solutions to problems, optimizing, tinkering, combining. This is what I'm
best at. One of the side quests I had for Startup Weekend is to work with other brilliant developers
(and as a side effect sort of validate my project). I could have worked with more people, but in the
end, this side quest was pretty successful.&lt;/p&gt;

&lt;p&gt;I had started working on my pitched project before, so in fact had a working application skeleton
that I'd just import and customize for this project and we were up and running with complete
facebook integration in under an hour.&lt;/p&gt;

&lt;p&gt;The thing is, it didn't matter. I am about halfway through Eric Ries' Lean Startup and this is one
of those classic cases where we wouldn't have needed to actually create anything. I think that's one
of the failings of Startup Weekend Tokyo GEW specifically. I can't blame the organizers though, because
this being an international startup battle, it is a lot more important to have a solid idea that can
be elaborated on and then presented in Singapore next year than to create a small startup. Hopefully
the next one will have a different atmosphere where creating a real product has a higher value.&lt;/p&gt;

&lt;p&gt;However, doing all that development gave me a lot of advantages that I wouldn't have had had I not
done it and just thrown together some sketch.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;I had an insane amount of fun&lt;/strong&gt;&lt;br/&gt;
 Did I mention, this is what I enjoy most?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I could work with other great developers&lt;/strong&gt;&lt;br/&gt;
 Which in turn was also adding to the fun factor. That's the sort of atmosphere you want to have in your startup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I realized I'm a good developer&lt;/strong&gt;&lt;br/&gt;
 From time to time &lt;em&gt;impostor syndrome&lt;/em&gt; gets the better of me and it is great to be reminded that it's not real.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;As a side-effect, my teammates tried to nominate me as the person who worked the hardest in the
team. If only they knew just how much fun I had in the meantime :)&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;10 - Having fun is really important. Developing is fun for developers.&lt;/h4&gt;

&lt;h4&gt;11 - When you are having fun, you can pull off impossible-looking feats.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;h1&gt;Day 3 - Crunch&lt;/h1&gt;

&lt;p&gt;The first half of the third day is crunch time leading up to the final presentations. At this point
people are groggy and the fun is starting to dissipate, so we just had to put our heads down and
do what we had to do.&lt;/p&gt;

&lt;p&gt;This is the time where we started having second thoughts about the fundamentals. I thought that
that was not a very good position to be in, but it seems that other teams were also going through
this phase.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;12 - Everyone has doubts just before the end. Just push through.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;h1&gt;Day 3 - Final Presentation&lt;/h1&gt;

&lt;p&gt;Final presentation is the most important part of Startup Weekend. The pitch is just a tool to get
selected and the development is just a tool to put together something that will get the attention of
the VCs. Everything rides on how the final presentation goes.&lt;/p&gt;

&lt;p&gt;Most teams didn't even start creating a product at all (they were busy arguing about the business).
The audience-winning team and the final winner team did not start to create a product.&lt;/p&gt;

&lt;p&gt;What they had though is a compelling story. The presentations before the winning team were all so-so
but when the winner presented, they were something else altogether. It was probably not fair to the
other teams (the winning team was basically the extension of an already existing and successful
company). The presentation though... people suddenly started thinking &quot;Steve Jobs keynote&quot; and it
wasn't very far.&lt;/p&gt;

&lt;p&gt;During their QA with the VCs, I had the most visceral validation of what I once read somewhere
(paraphrased):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Tell your weaknesses up front. Tell your strengths at the end preferably when prodded for.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Things went down approximately like this:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;VC: OK, but what will you do if &amp;lt;other, already successful company in the same field&gt; does the same thing?
XY: Oh, that company happens to be my company.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Boom. Won.&lt;/p&gt;

&lt;p&gt;There was a long deliberation afterwards where I'm sure the other
teams were considered in earnest, but the sheer force of this exchange is hard to ignore. It's hard
to understand from reading about it, but it &lt;em&gt;was&lt;/em&gt; visceral; it &lt;em&gt;was&lt;/em&gt; powerful.
Note, that he wasn't bragging about this, wasn't even going to mention in his presentation,
but when the VC asked about it, that one line had all the more power. Combine this with a very
well executed presentation and at that point I literally forgot what the presentation is
actually about... hand me the pen, where do I sign the check?&lt;/p&gt;

&lt;p&gt;On the other hand, we had the start of a product, but lost because of two things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The idea wasn't big&lt;/li&gt;
&lt;li&gt;The idea wasn't solid&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;That the presentation wasn't too good is just a result of these two.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;13 - Make sure you have a compelling story. Product is secondary.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;h1&gt;Day 3 - General&lt;/h1&gt;

&lt;p&gt;One thing I think I didn't do enough of is talk to other teams. Part of it is because I had
too much fun working on the product. Part of it is that I'm not that good at networking, but
then again now I know that most people aren't either and it's just one of those things
that you need to do against all fear.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;14 - Talk to everyone.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;p&gt;Am I going to go to the next Startup Weekend? Almost certainly, there are a lot of things I
still want to try in the pitch, maybe get selected and have different problems next time. Then
again, maybe next time I'll make it about connecting with others rather than concentrating on
a project.&lt;/p&gt;

&lt;p&gt;So do I recommend going to a Startup Weekend? Yes. Is it really like a startup? I don't think so.
Still, it's one of those experiences that are worth trying out.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rails 3 javascript_include_tag</title>
      <link>http://zaki.asia/2010/11/10/rails-3-javascript_include_tag.html</link>
      <pubDate>Wed, 10 Nov 2010 01:55:18 -0800</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/11/10/rails-3-javascript_include_tag</guid>
      <description>&lt;div class=&quot;alert-message block-message info&quot;&gt;
  The below issue is already fixed in rails.
&lt;/div&gt;


&lt;p&gt;After installing the &lt;em&gt;jquery_ujs &lt;/em&gt;driver for a Rails 3 app, today it started
acting up when I tried using the Cycle jQuery plugin. Specifically, the
following code in application.js would create twice as many pager anchors as
expected.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.featured&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cycle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;fx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fade&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;pager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;#featured-controls&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;pauseOnPagerHover&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;pause&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;pagerAnchorBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;slide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;At first I thought it was a problem with my HTML code as I was using nested
&lt;em&gt;divs &lt;/em&gt;(by chance two internal &lt;em&gt;divs &lt;/em&gt;per container &lt;em&gt;div &lt;/em&gt;I wanted to cycle),
but that wasn't the reason. Tracing the problem, I noticed, that
application.js would get executed twice, and lo and behold, there it is at the
top of the source: application.js included twice. Hmm, that's strange, my
includes look like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_include_tag&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:defaults&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javascript_include_tag&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;jquery.cycle.min&amp;#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In application.rb, I made the following configuration as suggested by the
&lt;a href=&quot;https://github.com/rails/jquery-ujs&quot;&gt;jquery_ujs&lt;/a&gt; github's README:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;javascript_expansions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(jquery rails application)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;As it turns out, however, rails is very smart about javascript files and when
someone includes &lt;strong&gt;:defaults &lt;/strong&gt;(and in :defaults only) it will automatically
append application.js to the list of files to include. Let's take a look at
&lt;strong&gt;&lt;em&gt;actionpack/lib/action_view/helpers/asset_tag_helper.rb&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;expand_javascript_sources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recursive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;all_javascript_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collect_asset_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;javascripts_dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;**&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recursive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;*.js&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;determine_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vc&quot;&gt;@@javascript_expansions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_javascript_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;all_javascript_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniq&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expanded_sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;determine_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vc&quot;&gt;@@javascript_expansions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expanded_sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;application&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exist?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;javascripts_dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;application.js&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expanded_sources&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Removing &lt;em&gt;application &lt;/em&gt;from the &lt;strong&gt;javascript_expansions[:default]
&lt;/strong&gt;configuration removes the duplicate application.js and Cycle now works
properly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Yaml !!merge</title>
      <link>http://zaki.asia/2010/10/08/yaml-merge.html</link>
      <pubDate>Fri, 08 Oct 2010 13:07:58 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/10/08/yaml-merge</guid>
      <description>&lt;p&gt;There are two interesting constructs I came across in the database.yml in the
&lt;a href=&quot;http://github.com/fdv/typo&quot;&gt;typo&lt;/a&gt; source. One of them is for creating and
using a named block, but the other one was a lot more interesting technique to
grab parts of the Yaml tree and merge it into another part of the tree, which
works in combination with the named blocks to result in a DRY configuration
file like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;&amp;amp;login&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;mysql&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;localhost&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;root&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;

  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;development&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;typo_dev&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;*login&lt;/span&gt;

  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;typo_tests&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;*login&lt;/span&gt;

  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;typo&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;*login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;OK, so the login: &amp;amp;login part creates a named block and *login simply uses
that block. This is not incredibly difficult so far, but what on earth are
those &quot;&amp;lt;&amp;lt;:&quot; ? Because I haven't seen them before, for a moment I was wondering
if this is some sort of metaprogramming magic, where the &amp;lt;&amp;lt; method/operator
will somehow get called and execute with the block given to it. To find out
how it works, I went to read the YAML 1.2
&lt;a href=&quot;http://www.yaml.org/spec/1.2/spec.html&quot;&gt;specification&lt;/a&gt;, but interestingly
this syntax wasn't anywhere in the main doc. As it turns out, &amp;lt;&amp;lt; is actually a
shorthand for a tag, namely &lt;strong&gt;!!merge&lt;/strong&gt;, and is mentioned in a separate
document named _&lt;a href=&quot;http://yaml.org/type&quot;&gt;Language-Independent Types for YAML™&lt;/a&gt; _&lt;/p&gt;

&lt;p&gt;There are a few other tags mentioned here as well. In ruby, collection types
seem to create a custom &lt;em&gt;YAML::PrivateType&lt;/em&gt; (or &lt;em&gt;Syck::PrivateType&lt;/em&gt; in 1.9)
object and shove the data in its &lt;em&gt;@value&lt;/em&gt;. I don't really see much use for
these types in ruby now.&lt;/p&gt;

&lt;p&gt;Scalar types on the other hand are better integrated, but tags like
&lt;strong&gt;!!binary&lt;/strong&gt;, &lt;strong&gt;!!value&lt;/strong&gt; or &lt;strong&gt;!!yaml &lt;/strong&gt;still create the &lt;em&gt;PrivateType&lt;/em&gt;
objects, so I guess they are not  supported - and these are all only
recommendations according to the document.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Testing Rails 3.0</title>
      <link>http://zaki.asia/2010/09/13/testing-rails-3.html</link>
      <pubDate>Mon, 13 Sep 2010 16:26:14 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/09/13/testing-rails-3</guid>
      <description>&lt;h2&gt;Getting rails 3&lt;/h2&gt;

&lt;p&gt;Rails 3.0 was released this week (*), so I thought I'd go and try to run it's
test suite - on windows.&lt;/p&gt;

&lt;p&gt;The first step is to get Ruby 1.9.2p0 from the &lt;a href=&quot;http://rubyinstaller.org/&quot;&gt;windows installer
page&lt;/a&gt; and install it. I'm running on
&lt;a href=&quot;http://github.com/vertiginous/pik&quot;&gt;pik&lt;/a&gt;, so after installation and setup, I'd
switch to 1.9.2 with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pik sw 192
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The stock 1.9.2 install contains a slightly old version (2.5.8) of the rdoc
gem, so the first thing to do is to update it with &lt;em&gt;gem update&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Another tool that is necessary is the bundler gem, so install it with &lt;em&gt;gem
install bundler&lt;/em&gt;.  Now to fetch all the prerequisites, all we need to do is
run &lt;em&gt;bundle install&lt;/em&gt; in the root of the rails source. (Note the command is
bundle, the gem name is bundler - I sometimes forget this when typing fast)&lt;/p&gt;

&lt;h2&gt;Testing&lt;/h2&gt;

&lt;p&gt;What I wanted to do is to run the built-in test suite. Theoretically, just
running &lt;em&gt;rake test&lt;/em&gt; in the root should work  and it would test every
component, but in practice that doesn't quite work out that well (lots of
warnings push the results out of screen pretty fast), so I opted to run the
tests for each component separately.&lt;/p&gt;

&lt;h3&gt;activemodel&lt;/h3&gt;

&lt;p&gt;In the activemodel directory, entering rake test will run the test suite for
the activemodel component only. It's result should be just a little bit messy
with a lot of warnings, but in the end, we can get our first easy victory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;400 tests, 1110 assertions, 0 failures, 0 errors, 0 skips
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;activeresource&lt;/h3&gt;

&lt;p&gt;While this pack spews a huge number of warnings, the result is quite tame and
we can more or less trust activeresource on windows.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;272 tests, 789 assertions, 0 failures, 0 errors, 0 skips
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;actionmailer&lt;/h3&gt;

&lt;p&gt;Another easy victory in spite of some warnings.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;175 tests, 479 assertions, 0 failures, 0 errors, 0 skips
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;activesupport&lt;/h3&gt;

&lt;p&gt;After running rake test for activesupport, the picture is slightly different,
but still not unreasonable (these tests were run without memcached). What I
found was&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;2055 tests, 9169 assertions, 35 failures, 1 errors, 0 skips
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's see what these failures are. There are basically two areas of
activesupport that do not pass on my windows machine. One is reasonable, the
other one is slightly more difficult to understand: File operations
(especially permissions) and Time. I've uploaded the exact output in &lt;a href=&quot;http://gist.github.com/558529&quot;&gt;this
gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To dig a little deeper I looked at a few of the time errors.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3) Failure: test_current_returns_time_zone_today_when_zone_default_set
(DateExtCalculationsTest) [test/core_ext/date_ext_test.rb:397]:
&amp;lt;Sat, 01 Jan 2000&amp;gt; expected but was &amp;lt;Fri, 31 Dec 1999&amp;gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code that is responsible for the testing is the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_current_returns_time_zone_today_when_zone_default_set&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zone_default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TimeZone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Eastern Time (US &amp;amp; Canada)&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;with_env_tz&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;US/Central&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stubs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;today&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zone_default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Or in other words, 1999-12-31 23:00 in Central Time should be 2000-01-01 00:00
in Eastern Time. The difference between &lt;em&gt;Date.today&lt;/em&gt; and &lt;em&gt;Data.current&lt;/em&gt; is
that &lt;em&gt;Date.current&lt;/em&gt; is supposed to take the time zone into account.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;current&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zone_default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;today&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;today&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So why doesn't it work on Windows? The answer lies in the with_env_tz method,
which looks like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;with_env_tz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_tz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;US/Eastern&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;old_tz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;TZ&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;TZ&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_tz&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;old_tz&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;TZ&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;old_tz&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;TZ&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This method sets the time zone to be used through an environment variable TZ.
However on windows, this variable can only be set at script startup and not
during runtime (its value will be ignored). In fact, this is the method that
causes all the failing tests on windows. This shouldn't actually cause a
problem for rails projects, though, the timezone is properly set up at
startup.&lt;/p&gt;

&lt;p&gt;A more interesting part is the exception raised in one of the tests. That one
is coming from a test that tries to silence STDERR, which does not work on
windows and raises Errno::EBADF, which is unfortunately not caught. A way to
deal with it would be to catch this exception.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_silence_stderr&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;old_stderr_position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STDERR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tell&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;silence_stderr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STDERR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;old_stderr_position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STDERR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tell&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Errno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ESPIPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Errno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EBADF&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Skip if we can&amp;#39;t STDERR.tell&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Moving on to the other filesystem-related errors, we can find that they are
related to permissions. For instance the following test&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_atomic_write_preserves_default_file_permissions&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Atomic Text&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atomic_write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exist?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exist?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100666&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;umask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_mode&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;is testing if the file's permissions are kept as the default (0666 -rw-rw-
rw-), however here's what the ruby documentations has to say about File.open()&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Opens the file named by fileName according to aModeString (default is ``r'')
and returns a new File object. See Table 22.5 on page 326 for a description of
aModeString. The file mode may optionally be specified as a Fixnum by or-ing
together the flags described in Table 22.3 on page 305. Optional permission
bits may be given in aPermNum. &lt;strong&gt;These mode and permission bits are platform
dependent&lt;/strong&gt;; on Unix systems, see open(2) for details.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The general meaning of &quot;platform dependent&quot; seems to be &quot;it doesn't work on
Windows&quot;.&lt;/p&gt;

&lt;p&gt;The default permission on Windows seems to be  0644, so in this case, the test
itself could account for the differences in the platform and we could fix the
test by writing something like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DEFAULT_PERMISSIONS = Config::CONFIG[‘host_os’] =~ /mswin|mingw/ ? 0100644 : 0100666
&lt;/code&gt;&lt;/pre&gt;

&lt;div class=&quot;alert-message block-message info&quot;&gt;
  Update: Thanks for Luis Lavena to point out the flaws in the original platform checking
&lt;/div&gt;


&lt;p&gt;Although this will not help with the tests that check if permissions can be
set properly, at least it solves the default permission test. At this point
there is only one final type of tests that fail, the FileStoreTests. It would
probably be proper to skip these permission tests on windows altogether.&lt;/p&gt;

&lt;p&gt;The remaining failures come from FileStoreTest in test/caching_test.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;test_crazy_key_characters(FileStoreTest) &amp;lt;3&amp;gt; expected but was &amp;lt;nil&amp;gt;.
test_decrement(FileStoreTest) &amp;lt;2&amp;gt; expected but was &amp;lt;nil&amp;gt;.
test_increment(FileStoreTest) &amp;lt;2&amp;gt; expected but was &amp;lt;nil&amp;gt;.
test_local_cache_of_decrement(FileStoreTest) &amp;lt;2&amp;gt; expected but was &amp;lt;3&amp;gt;.
test_local_cache_of_increment(FileStoreTest) &amp;lt;3&amp;gt; expected but was &amp;lt;2&amp;gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It seems that actually all tests fail on the increment or decrement methods,
so let's try to investigate which feature might be &quot;platform dependent&quot; this
time.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;increment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespaced_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;lock_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merged_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lock_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# :nodoc:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exist?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flock&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LOCK_EX&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flock&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LOCK_UN&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;As it can be guessed, the ruby documentation has this to say about File.flock:
&quot;Not available on all platforms.&quot; In fact the problem happens at read (or more
precisely at read_entry) where a permission denied exception is raised, but is
promptly swallowed and nil is returned instead. This makes increment and
decrement to fail.&lt;/p&gt;

&lt;p&gt;The bottom line about using activesupport on windows is that timezone-changing
via environment variables will not work on the fly. Also, there is the problem
with file-based caching that can easily lead to frustration, but otherwise
activesupport can be trusted.&lt;/p&gt;

&lt;h3&gt;actionpack&lt;/h3&gt;

&lt;p&gt;Nice clean output for the most part and the result is also pretty nice:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;2819 tests, 10698 assertions, 2 failures, 5 errors, 0 skips

1) Failure: test_caching_stylesheet_link_tag_when_caching_on(AssetTagHelperTest)
&amp;lt;55&amp;gt; expected but was &amp;lt;59&amp;gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The failure is a difference in the response size and its expected size. That
means that there is a 4 byte excess. And of course those bytes are coming from
the CRLFs.&lt;/p&gt;

&lt;h3&gt;activerecord&lt;/h3&gt;

&lt;p&gt;Now, ActiveRecord's output is really messy on windows. In fact to the point
that tests don't even run and all I'm left in the end is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Errors running test_mysql, test_mysql2, test_sqlite3, test_postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(*) And because this post already takes a lot longer than I wanted, I'll take
a look at ActiveRecord in another post, and will conclude this one.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Referrer spam in statpress</title>
      <link>http://zaki.asia/2010/07/14/referrer-spam-in-statpress.html</link>
      <pubDate>Wed, 14 Jul 2010 16:50:40 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/07/14/referrer-spam-in-statpress</guid>
      <description>&lt;p&gt;Today I got really fed up with statpress referrer spam, so I decided to
implement a dead simple referrer check function into statpress. The function
works very similar to the current IP banning, so it wasn't very difficult to
get it to work. If I get angry again, I might create a new statpress
Option/Page to make the word banning easier or even make it non-destructive by
only marking the referrer as spam. Of course other than the proactive banning,
one might want to sanitize the referrrers in the statpress table as well. For
me, I just cleared all the referrers with bad words in them, but didn't bother
to entirely remove the entries as I wanted to keep count of the actual access
count.&lt;/p&gt;

&lt;p&gt;Here are my simple changes to statpress.php:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;x&quot;&gt;// A function to check whether a referrer should be&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;// omitted due to a manual ban&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;// To add/remove referrer bans, edit&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;// wp-content/plugins/statpress/def/banreferrers.dat&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;function iriCheckBanReferrer($arg)&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  $lines = file(ABSPATH.&amp;#39;wp-content/plugins/&amp;#39;.dirname(plugin_basename(__FILE__)). &amp;#39;/def/banreferrers.dat&amp;#39;);&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  foreach($lines as $line_num =&amp;gt; $banref)&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    if(strpos($arg,rtrim($banref,&amp;quot;n&amp;quot;))===FALSE)&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;      continue;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    return true; // banned&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  }&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  return false;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;// In function iriStatAppend()&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;$referrer = (isset($_SERVER[&amp;#39;HTTP_REFERER&amp;#39;]) ? htmlentities($_SERVER[&amp;#39;HTTP_REFERER&amp;#39;]) : &amp;#39;&amp;#39;);&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;// BANNED REFERRERS&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;if (iriCheckBanReferrer($referrer)) $referrer = &amp;#39;&amp;#39;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;// END BANNED REFERRERS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Then all I needed to do is create a banreferrers.dat file in the
plugins/statpress/def directory containing one bad word/domain per line and
now hopefully a lot less referrer spam will appear in the statpress overview.
For now this will suffice for me.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>C for Ruby</title>
      <link>http://zaki.asia/2010/07/12/c_for_ruby_byk.html</link>
      <pubDate>Mon, 12 Jul 2010 17:34:46 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/07/12/c_for_ruby_byk</guid>
      <description>&lt;p&gt;Last weekend, I did an informal mini-conference on C and Ruby with a few
friends.&lt;/p&gt;

&lt;h2&gt;Introduction to C&lt;/h2&gt;

&lt;p&gt;We started with an introduction to C as some of my friends didn't know it at
all. Of course pointers in C are a little difficult to wrap heads around at
first, but hopefully the things we covered will get them interested enough to
try and follow up on them. One particular example that started many questions
was something along these lines:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// what happens if we do&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// free(*i);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;%d&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// we should use free(ptr); here (if main() wasn&amp;#39;t exiting anyway)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Especially the part about free-ing before accessing the variable: what happens
if we access the already free-d memory. On one machine we tried it, the number
was still 123, which showed very well how much we cannot trust the compiler/OS
to actually zero out the memory immediately when it is released and how easily
this can lead to bugs that work sometimes and fail sometimes. Next we talked
about the connections between C arrays and pointers.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// an array is in fact a pointer to the head&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// this is the same as the above&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// the C compiler knows how long an int is&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// so the + 1 will point to the first element&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// instead of just plus one byte&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Next up using pointers/arrays, together we implemented a very easy function to
check whether a string was a palindrom:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// lo is set to the first character&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// hi is set to the last character&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// the chars don&amp;#39;t match&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// move lo to the right, hi to the left&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// every char matched, it is a palindrom&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Understanding Array#reverse&lt;/h2&gt;

&lt;p&gt;After we discussed the very basics of C, finally we started diving into the
source code of Ruby (latest trunk from github). I wanted to keep it simple, so
to be connected to the previous discussion, I left out the basics of &lt;em&gt;VALUE&lt;/em&gt;
and the first code we looked at was &lt;em&gt;Array#reverse&lt;/em&gt; and &lt;em&gt;Array#reverse!&lt;/em&gt; These
functions were fairly easy to understand as  there is no complicated resizing
or in &lt;em&gt;String#reverse&lt;/em&gt;'s case, complicated encodings to deal with. In fact,
before looking at the code, we discussed how it could be implemented - and to
no surprise the actual implementation was very similar.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rb_ary_reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;rb_ary_modify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RARRAY_LEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RARRAY_PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// get pointer to first item&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RARRAY_LEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// get pointer to last item&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// imaging p1 as lo and p2 as hi&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// swap *p1 with *p2&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;One thing to remember here is the &lt;em&gt;*p1++&lt;/em&gt; notation. To those unfamiliar with
C, &lt;em&gt;var++&lt;/em&gt; means that first var is &quot;returned&quot; or in other words, var is used
and only then is it incremented. (the ++ is after the variable). On the other
hand, &lt;em&gt;++var&lt;/em&gt; would first increment var and then use this incremented value.
So it is crucial to use &lt;em&gt;*p1++&lt;/em&gt; here instead of &lt;em&gt;*++p1&lt;/em&gt;. Now in ruby, there
are two versions of reverse, one with a bang and one without. From the code in
the above helper function, we can assume that it is for the reverse! type, but
it would not be very useful for &lt;em&gt;Array#reverse&lt;/em&gt; as it would change the array
in place. Instead, we saw in the sources that &lt;em&gt;Array#reverse&lt;/em&gt; actually
internally duplicates the array before doing the in-place reverse on the
duplicated array. This pointed out that &lt;em&gt;Array#reverse&lt;/em&gt; must be slower than
&lt;em&gt;Array#reverse!&lt;/em&gt; and of course it must also use more memory. Even though I
didn't go into too much detail about Ruby's GC (which I'm not all that
familiar with anyway beyond knowing it is a mark-and-sweep type collector,
just like the CLR), I mentioned that the GC will be started when a memory
allocation does not have enough memory. So in the end, not only is it slower
and uses more memory, but there is a chance that &lt;em&gt;Array#reverse&lt;/em&gt; triggers
garbage collection which will make it even slower and use even more memory.
(As an aside, realizations like these are the reasons I wanted to talk about
the internals, as I believe understanding even just a little about how things
work make us better programmers in the long term)&lt;/p&gt;

&lt;p&gt;To understand the
performance implications, we tried implementing &lt;em&gt;Array#reverse!&lt;/em&gt; in ruby which
we benchmarked against the native &lt;em&gt;reverse!&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;benchmark&amp;#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Array&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rb_reverse!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmp&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10_000_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_a&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bm&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reverse!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rb_reverse!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The result was absolutely clear:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    user     system      total        real
0.030000   0.000000   0.030000 (  0.037438)
0.100000   0.040000   0.140000 (  0.142042)
6.290000   0.020000   6.310000 (  6.307183)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Extending Fixnum#succ&lt;/h2&gt;

&lt;p&gt;Next we looked at an (easy-looking) item from
the Ruby ToDo file:
* optional stepsize argument for succ()&lt;/p&gt;

&lt;p&gt;By default &lt;code&gt;Fixnum#succ&lt;/code&gt; doesn't take any arguments and just increments
the variable by 1. So let's take a look at what it's doing internally:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fix_succ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG2NUM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;No surprise here, it takes no arguments (besides a &quot;this&quot;) and increments by
1. To fix this, I explained about variable argument list, so we can take one
or zero arguments and naively implemented a first version of &lt;em&gt;succ&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fix_succ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// this will hold the value to increment by&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// in case we don&amp;#39;t receive any arguments, use 1 as step&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INT2FIX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// just like above&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// when there is one argument, use it as the increment&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// if there are more than 1 arguments, raise error&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rb_raise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rb_eArgError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;wrong number of arguments&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// add the numbers and return&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG2NUM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Of course this in itself does not work, which gave me a chance to briefly
mention how method lookup tables work. Then together we changed that table to
indicate that &lt;em&gt;succ&lt;/em&gt; might take any number of arguments with the entry:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;rb_define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rb_cFixnum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;succ&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fix_succ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;However that naive implementation has a lot of problems that then gave me an
opportunity to again mention other parts of ruby we should be aware of.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# For starters, let&amp;#39;s try the new succ method:&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# OK&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# OK&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1073741823&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1073741824&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# OK&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1073741824&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;73693943&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Hey, what&amp;#39;s going on here&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# other errors&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;73021957&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# whoa, what&amp;#39;s this?&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# OK&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succ&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`succ&amp;#39;: wrong number of arguments(1 for 0) (ArgumentError) #Ooops&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Of course to understand what the problem is, we should know why  1073741824 is
special. As it turns out, &lt;em&gt;Fixnum's&lt;/em&gt; largest representable value is
1073741823, which means that 1073741824 causes an overflow. Even though C
&lt;em&gt;int/long&lt;/em&gt; can go twice as high (2&lt;sup&gt;31),&lt;/sup&gt; &lt;em&gt;Fixnum&lt;/em&gt; can hold up to 2&lt;sup&gt;30&lt;/sup&gt; only. This
means that values that are higher than 1073741823 will be of type &lt;em&gt;Bignum&lt;/em&gt;,
rather than &lt;em&gt;Fixnum&lt;/em&gt;. So one thing we can do is to check if the argument is a
&lt;em&gt;Fixnum&lt;/em&gt;. Only if it is a &lt;em&gt;Fixnum&lt;/em&gt;, should we add the values together, but
when it's a &lt;em&gt;Bignum&lt;/em&gt;, we can call into the regular + method, that will take
care of everything for us. In fact, we could have directly implemented
everything as an addition, but the point here is how to map C types to Ruby
types and how we can deal with the differences and the limitations of the
underlying language.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fix_succ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INT2FIX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rb_raise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rb_eArgError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;wrong number of arguments&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FIXNUM_P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// We can check if step can fit in Fixnum&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// yes, just add it together in a long&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// remember, that long can be twice as big as fixnum,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// so no worries about overflow&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2LONG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LONG2NUM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// If it didn&amp;#39;t fit into Fixnum, so let&amp;#39;s just add it naturally&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb_funcall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&amp;#39;+&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This finally works for numbers, but still has some problems. Also, &lt;em&gt;&quot;'a'.succ
2&quot; &lt;/em&gt;will not work, but the code for &lt;em&gt;String#succ&lt;/em&gt; is very complicated because
of the different encodings. As all my friends (except Huan) had to deal with
emoji conversion at one point in their lives, it didn't take much to scare
them away from looking at those codes (or even try to implement &lt;em&gt;#succ&lt;/em&gt; - but
they are free to do so if they want to)&lt;/p&gt;

&lt;h2&gt;Writing native extensions for Ruby&lt;/h2&gt;

&lt;p&gt;Finally I wanted to look at implementing Ruby extensions in C (and comparing
performance) but unfortunately the &lt;em&gt;mkmf&lt;/em&gt; lib was not found on my machine
(Later I realized that it was because RVM changed to an unusable ruby version
when I wasn't looking), so instead tried implementing binary search together
as an exercise. As a note, here's the final working version:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rbinsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;en&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;en&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# avoid overflow in (st + en) / 2&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# not found&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In fact, I created an extension to do the same thing and benchmarked the Ruby
version against the C version&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;quot;ruby.h&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Convrt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Qnil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Init_convrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method_binsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Init_convrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Convrt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb_define_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Convrt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rb_define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Convrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;binsrc&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method_binsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;method_binsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T_ARRAY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T_FIXNUM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rb_raise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rb_eTypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Invalid arguments&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RARRAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FIX2INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RARRAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FIX2INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RARRAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INT2FIX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INT2FIX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;benchmark&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;convrt&amp;#39;&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Convrt&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rbinsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;en&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;en&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elsif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ARGV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_i&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_a&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bm&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rbinsrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And the result again is very clear, which shows how a C extension for Ruby can
improve performance in bottleneck situations but because it complicates things
a lot, how it should be only used with  good judgment.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ruby test_02.rb 10000
      user     system      total        real
  0.010000   0.000000   0.010000 (  0.016662)
  0.430000   0.020000   0.450000 (  0.449629)
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>F# Discriminated Unions</title>
      <link>http://zaki.asia/2010/07/06/f-discriminated-unions.html</link>
      <pubDate>Tue, 06 Jul 2010 00:50:53 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/07/06/f-discriminated-unions</guid>
      <description>&lt;p&gt;In F# discriminated unions are providing a base for the powerful pattern
matching. Let's examine what happens behind the scene when someone enters the
following innocent-looking code:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Option1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Option2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If we take the generated assembly apart, this simple code generates a
relatively large amount of code. First of all, a class (type) named &lt;em&gt;Test &lt;/em&gt;is
going to be created. What is more surprising is that five nested classes will
also be defined. Of this five, two seems to be crucial as we'll see while the
others seem to be more about administration.&lt;/p&gt;

&lt;p&gt;Talking about administration, the resulting type implements a fair amount of
interfaces automatically.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;IEquatable &lt;/em&gt;adds three &lt;em&gt;Equals &lt;/em&gt;methods: one with the &lt;em&gt;Test &lt;/em&gt;type, but also
two with object type (one of which allows a second &lt;em&gt;IEqualityComparer
&lt;/em&gt;parameter). Similarly &lt;em&gt;IComparable &lt;/em&gt;and &lt;em&gt;IComparable&lt;Test&gt;&lt;/em&gt; are implemented.
In addition &lt;em&gt;IStructuralEquatable&lt;/em&gt; and &lt;em&gt;IStructuralComparable &lt;/em&gt;are also
implemented. I won't talk about these methods.&lt;/p&gt;

&lt;p&gt;What is more important is that one nested class that is inherited from &lt;em&gt;Test
&lt;/em&gt;will be created for each option, named &lt;em&gt;Option1 &lt;/em&gt;and &lt;em&gt;Option2&lt;/em&gt;. Both of these
classes will contain a property named &lt;em&gt;Item &lt;/em&gt;and not surprisingly Item will be
&lt;em&gt;float64 &lt;/em&gt;in &lt;em&gt;Option1 &lt;/em&gt;and &lt;em&gt;int32 &lt;/em&gt;in &lt;em&gt;Option2&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Test &lt;/em&gt;will also contain two more boolean properties: &lt;em&gt;IsOption1 &lt;/em&gt;and
&lt;em&gt;IsOption2 &lt;/em&gt;which return whether this refers to an instance of the respective
type.&lt;/p&gt;

&lt;p&gt;Finally &lt;em&gt;Test &lt;/em&gt;provides two factory constructors named &lt;em&gt;NewOption1 &lt;/em&gt;and
&lt;em&gt;NewOption2 &lt;/em&gt;which create either of the nested option instances. Its
constructor in fact is not public (and doesn't do anything except create the
useless parent &lt;em&gt;Test &lt;/em&gt;instance).&lt;/p&gt;

&lt;p&gt;An implementation in C# therefore (removing much of the automatically
generated interface implementations and helper methods) would look like this.
The generated IL is very similar to that of the original F# code.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Test&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Option1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Test&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Option1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Option2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Test&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Option2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tags&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Test&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NewObject1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Test&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NewObject2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IsOption1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IsOption2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Option1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Option1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Option2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There are two further nested classes named &lt;em&gt;Option1@DebugTypeProxy&lt;/em&gt; and
&lt;em&gt;Option2@DebugTypeProxy&lt;/em&gt;, but I'm not really sure what their functionality is.
Also, there is that &lt;em&gt;Tags &lt;/em&gt;nested class with its const definitions and the
&lt;em&gt;Tag &lt;/em&gt;property in &lt;em&gt;Test &lt;/em&gt;whose role is also not completely clear from this IL
code. It can be related to enums or maybe to do with performance&lt;/p&gt;

&lt;p&gt;After comparing the two implementations, it is very easy to appreciate how -
in probably Don Syme's favorite word - succinct F# really is (and that's even
before diving into heavyweight functional programming.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>F# Currying</title>
      <link>http://zaki.asia/2010/06/30/f-currying.html</link>
      <pubDate>Wed, 30 Jun 2010 22:00:32 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/06/30/f-currying</guid>
      <description>&lt;p&gt;Let's look at how currying works behind the scenes. It is not very surprising
that this code&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adder&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;is compiled to&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;.method public static int32 adder(int32 x, int32 y) cil managed 
{
  .custom instance void Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[])
    = (01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) // Code size 5 (0x5)
  .maxstack 4
  IL_0000: nop
  IL_0001: ldarg.0
  IL_0002: ldarg.1
  IL_0003: add
  IL_0004: ret
} // end of method Program::adder

.method public static int32 partial(int32 x) cil managed
{
  // Code size 9 (0x9)
  .maxstack 4
    IL_0000: nop
    IL_0001: ldc.i4.2
    IL_0002: ldarg.0
    IL_0003: call int32 Program::adder(int32,int32)
    IL_0008: ret
} // end of method Program::partial
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which comes down to the following common C# code&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Test&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and it does generate a similar IL code:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;.method public hidebysig static int32 adder(int32 x,int32 y) cil managed
{
  // Code size 9 (0x9)
  .maxstack 2
  .locals init ([0] int32 CS$1$0000)
  IL_0000: nop
  IL_0001: ldarg.0
  IL_0002: ldarg.1
  IL_0003: add
  IL_0004: stloc.0
  IL_0005: br.s IL_0007
  IL_0007: ldloc.0
  IL_0008: ret
} // end of method Test::adder .method

public hidebysig static int32 partial(int32 x) cil managed
{
  // Code size 13 (0xd)
  .maxstack 2
  .locals init ([0] int32 CS$1$0000)
  IL_0000: nop
  IL_0001: ldarg.0
  IL_0002: ldc.i4.2
  IL_0003: call int32 CSharpTest.Test::adder(int32,int32)
  IL_0008: stloc.0
  IL_0009: br.s IL_000b
  IL_000b: ldloc.0
  IL_000c: ret
} // end of method Test::partial
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</description>
    </item>
    
    <item>
      <title>F# Swap</title>
      <link>http://zaki.asia/2010/06/30/f-sharp-swap.html</link>
      <pubDate>Wed, 30 Jun 2010 02:20:46 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2010/06/30/f-sharp-swap</guid>
      <description>&lt;p&gt;Reading about functional programming, I got curious the other day: one of the
canonical examples is swapping the elements in a tuple but what exactly
happens internally? After all, whatever language is used, eventually it will
be translated to native code.&lt;/p&gt;

&lt;p&gt;F# is very easy to work with in this sense, because it will be compiled to IL
first, so if I only run ILdasm on it, an equivalent C# code could be created.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This innocent short code will generate the following IL code&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;.method public static class System.Tuple`2&amp;lt;!!b,!!a&amp;gt; a&amp;lt;a,b&amp;gt;(!!a x,!!b y) cil managed
{
  // Code size 9 (0x9)
  .maxstack 4
  IL_0000: nop
  IL_0001: ldarg.1
  IL_0002: ldarg.0
  IL_0003: newobj instance void class System.Tuple`2&amp;lt;!!b,!!a&amp;gt;::.ctor(!0, !1)
  IL_0008: ret
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Aha! So we are not fiddling around with temporary variables (which wouldn't
work anyway because variables are immutable by default in F#), instead the
simplest of things happens here: a new variable is constructed with the
parameters swapped and then returned.&lt;/p&gt;

&lt;p&gt;In C#, Swap could be written along these lines&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Swap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;In fact the C# code generates an almost identical IL code (although honestly
I'm not sure what the final branch is supposed to be, as it doesn't do
anything apparently useful)&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;.method public hidebysig static class System.Tuple`2&amp;lt;!!T2,!!T1&amp;gt; Swap&amp;lt;T1,T2&amp;gt;(!!T1 a0, !!T2 a1) cil managed
{
  // Code size 13 (0xd)
  .maxstack 3
  .locals init ([0] class System.Tuple`2&amp;lt;!!T2,!!T1&amp;gt; CS$1$0000)
  IL_0000: nop
  IL_0001: ldarg.1
  IL_0002: ldarg.0
  IL_0003: newobj instance void class System.Tuple`2&amp;lt;!!T2,!!T1&amp;gt;::.ctor(!0, !1)
  IL_0008: stloc.0
  IL_0009: br.s IL_000b
  IL_000b: ldloc.0
  IL_000c: ret
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</description>
    </item>
    
    <item>
      <title>OSGrid in Rei</title>
      <link>http://zaki.asia/2009/12/21/osgrid-in-rei.html</link>
      <pubDate>Mon, 21 Dec 2009 19:26:02 -0800</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/12/21/osgrid-in-rei</guid>
      <description>&lt;h2&gt;Textures&lt;/h2&gt;

&lt;p&gt;Before Rei was released at the end of September, it was called 3Di OpenViewer.
That version didn't need to download textures through the region
server, rather, it would download assets (textures, meshes, avatars) directly
from dedicated asset servers. For this reason, when someone logged in to an upstream
OpenSim grid with 3Di OpenViewer, textures and avatars would not appear.&lt;/p&gt;

&lt;p&gt;But that changed when we released Rei as an open-source viewer at the end of
September. At that time, textures were already being fetched from OpenSim. You
can go ahead and grab the installer from github and it will display textures.
What it won't do with textures is correctly apply UV coordinates in some
(fortunately very rare) twisted-hollow-prim cases (but it was more about
PrimMesher than Rei). Since September, we have done many improvements to
PrimMesher - and Rei too, so now even those rare cases appear correctly (big
thanks to the bug reporters). Texture downloads are slow unfortunately, but
more on that later.&lt;/p&gt;

&lt;h2&gt;Avatars&lt;/h2&gt;

&lt;p&gt;Now this is a very delicate issue. The heart of the issue is that currently
there is no non-LL viewer that supports SecondLife™ avatars. Let me say
that again: there are no viewers that support SL™ avatars. Naali has a
built-in mesh (the same as their old viewer), IdealistViewer has a built-in
mesh, LookingGlass doesn't yet have avatars (correct me if it does), Xenki
doesn't have an avatar yet as far as I know either.&lt;/p&gt;

&lt;p&gt;The closest a viewer gets to SL avatar support is the PandaViewer by dahlia
(&lt;a href=&quot;http://vimeo.com/6812213&quot;&gt;http://vimeo.com/6812213&lt;/a&gt;) , which supports avatar
shapes and actually looks really nice. Unfortunately it's not open source
(yet?), nor is it available in any form.&lt;/p&gt;

&lt;p&gt;The thing with avatar support is that it's pretty difficult to do right. No,
not only technically, but there's the issue of using or not using Linden
Labs™'s original mesh. You can find &lt;a href=&quot;http://secondlife.com/community/avatar.php&quot;&gt;downloadable
meshes&lt;/a&gt;, but there is a nice
warning hidden neatly inside an obj file:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;This model is released for use by residents of Second Life.
It may be imported into external 3D modeling, texturing, and
animation applications to aid in the creation of character
animations and textures for Second Life, as well as for
any non-commercial purpose.
Use or modification of this model for any other commercial purpose is prohibited
without the express written consent of Linden Lab.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;With all this said, we are looking at SL™ avatar support. It definitely
won't happen before the end of this year, the target is early next year.&lt;/p&gt;

&lt;h2&gt;OpenSim support&lt;/h2&gt;

&lt;p&gt;Of course Rei still has issues with upstream OpenSim support. This is
partially due to the very very bad way textures are downloaded (through a
single server, in UDP). The truth is, even the SL™ viewer chokes on those: in
heavy regions it would download the low resolution image, but the full image
is never actually downloaded. My personal opinion is that the sooner we can
break free from that way of transferring assets to clients, the better (guess
how 3Di OpenViewer delivers content, through dedicated asset servers).
Hopefully OpenSim will not remain an
SL™ clone and there will be lots of innovations in the virtual world space
coming from OpenSim. Rei is supposed to show what is possible when we can
control both the viewer and the server side without the fear of not being able
to work on one or the other for six months.&lt;/p&gt;

&lt;h2&gt;The current state&lt;/h2&gt;

&lt;h4&gt;LBSA Plaza&lt;/h4&gt;

&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;640&quot; height=&quot;505&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/cgNL4-oMLOc&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;640&quot; height=&quot;505&quot; src=&quot;http://www.youtube.com/v/cgNL4-oMLOc&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;h4&gt;Wright Plaza&lt;/h4&gt;

&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;640&quot; height=&quot;505&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/FBbR4txM9M4&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;640&quot; height=&quot;505&quot; src=&quot;http://www.youtube.com/v/FBbR4txM9M4&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;So, what do you think of the viewer so far? What sort of improvements do you
think would be nice? What do you think is missing, other than the avatar
support?&lt;/p&gt;

&lt;p&gt;In general, what are the things you absolutely expect from a virtual world
viewer?&lt;/p&gt;

&lt;p&gt;Let me know in the comments.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Wii Controller Plugin for 3Di Viewer Rei</title>
      <link>http://zaki.asia/2009/11/20/wii-controller-plugin-for-3di-rei.html</link>
      <pubDate>Fri, 20 Nov 2009 17:56:53 -0800</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/11/20/wii-controller-plugin-for-3di-rei</guid>
      <description>&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;640&quot; height=&quot;505&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/g_xum05b6xQ&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;640&quot; height=&quot;505&quot; src=&quot;http://www.youtube.com/v/g_xum05b6xQ&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;h3&gt;Wii Controller Plugin&lt;/h3&gt;

&lt;p&gt;3Di Viewer &quot;Rei&quot; provides a great flexibility when it comes to adding custom
functionality to the core viewer by making it possible to create binary
plugins. Just drop these binaries into the Rei folder and let the viewer find
and load it automatically the next time it starts. While these plugins are
still in their early phase - we can do a lot more to ease the process of
deploying plugins and resolving their dependencies - you can get a glimpse at
their power already.&lt;/p&gt;

&lt;p&gt;The WiiControllerPlugin is a fun project, a proof-of-concept, rather than a
commercial solution, so before you dive in, be warned, that it is sometimes
rough around the edges. With that out of the way, if you have Rei, head over
to http://github.com/zaki/ReiWiiControllerPlugin and grab the binary from the
Download section. Just copy the contents into the Rei installation folder
(usually C:Program Files3DiRei). And... that's basically it.&lt;/p&gt;

&lt;h3&gt;How to connect the controller?&lt;/h3&gt;

&lt;p&gt;To use a Wiimote, you will need a Wiimote, a nunchuck and a bluetooth adapter.
I've heard that Toshiba adapters works best, but I have used Broadcomm's chips
successfully as well. It is said that the Microsoft stack doesn't work most of
the time with the Wiimote.&lt;/p&gt;

&lt;p&gt;Before you start the viewer, connect/pair the Wiimote via bluetooth. If you
find it difficult to connect, I found that keeping (1) and (2) pressed
simultaneously while connecting helps a lot.&lt;/p&gt;

&lt;p&gt;Once the Wiimote is connected, start Rei and if everything goes well, the
primary Wiimote will have its first LED turned on. You are now ready.&lt;/p&gt;

&lt;h3&gt;How to use the Wiimote?&lt;/h3&gt;

&lt;p&gt;The WiiControllerPlugin allows you to use the Wiimote and the nunchuck to
control your avatar and the camera. The nunchuck's joystick, or the
directional controller on the wiimote can be used to make you avatar walk. Up
will always make your avatar walk forward, regardless of the position of the
camera.&lt;/p&gt;

&lt;p&gt;The camera is controlled with a combination of the wiimote and the nunchuck.
Zoom in and out by holding down (Z) and tilting the nunchuck forward and
backward. Hold the wiimote straight up; while you press (B), you can tilt the
wiimote in four directions to rotate the camera around your avatar. Remember,
you don't have to look away from the screen to change the camera angle.&lt;/p&gt;

&lt;p&gt;If you get lost with the camera, you can always press (C) to go back to behind
your avatar. Pressing (C) also switches to &quot;follow&quot; mode, so your camera will
&quot;stick&quot; to  your avatar and will follow it from behind if you move. Pressing
(C) another time will switch back to the free camera mode.&lt;/p&gt;

&lt;p&gt;If you get tired of moving with the wiimote and want to switch back to using
the keyboard or mouse, you can disable avatar movements by pressing (-). Your
wiimote's will light the third LED when it's disabled. Press (-) again to
enable moving by the wii controller.&lt;/p&gt;

&lt;h3&gt;About the demo&lt;/h3&gt;

&lt;p&gt;The video above contains a very dull maze, in which there are colored balls
that hurt or heal you when you touch them (I've never said I was a great
contents designer, have I :)) The demo shows how easy it is to integrate
custom features with an unmodified OpenSim grid. All that was used is simple
LSL script that detects collisions and gives commands via llSay. These
commands can be intercepted by javascript and further dispatched to all
plugins, that can act accordingly. In this case a simple health bar is
adjusted.&lt;/p&gt;

&lt;p&gt;As my LSL was sending plaintext commands like &quot;heal,20&quot;, the necessary
javascript looks really simple:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DispatchCommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;strList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;strList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;strList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you have a question, or have a good idea about plugins, or the
WiiControllerPlugin, please share it in the comments.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Please note: WiiControllerPlugin is not endorsed by Nintendo.
WiiControllerPlugin depends on  WiiMoteLib, which is release under the license
MS-PL. For more details, see
&lt;a href=&quot;http://wiimotelib.codeplex.com/&quot;&gt;http://wiimotelib.codeplex.com/&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Plugins for Rei</title>
      <link>http://zaki.asia/2009/11/11/plugins-for-rei.html</link>
      <pubDate>Wed, 11 Nov 2009 18:09:23 -0800</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/11/11/plugins-for-rei</guid>
      <description>&lt;h2&gt;Plugins&lt;/h2&gt;

&lt;p&gt;In “Rei”, there is a curious little green “health” bar above the avatar’s
head. That bar is not something that is built in to the viewer, rather, a
simple plugin provides the functions that are necessary to have a very
rudimentary health bar. Of course this TestPlugin is only to show what sort of
things are possible with “Rei”.&lt;/p&gt;

&lt;ul class=&quot;media-grid&quot;&gt;
  &lt;li&gt;
    &lt;a&gt;
      &lt;img src=&quot;/images/3di-openviewer/TestPlugin.jpg&quot; width=&quot;100&quot; /&gt;
      &lt;h6 class=&quot;portfolio-label&quot;&gt;HEALTH BAR&lt;/h6&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a&gt;
      &lt;img src=&quot;/images/3di-openviewer/TestPlugin_Damage.jpg&quot; width=&quot;100&quot; /&gt;
      &lt;h6 class=&quot;portfolio-label&quot;&gt;DAMAGE&lt;/h6&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a&gt;
      &lt;img src=&quot;/images/3di-openviewer/TestPlugin_Heal.jpg&quot; width=&quot;100&quot; /&gt;
      &lt;h6 class=&quot;portfolio-label&quot;&gt;HEAL&lt;/h6&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a&gt;
      &lt;img src=&quot;/images/3di-openviewer/TestPlugin_Dead.jpg&quot; width=&quot;100&quot; /&gt;
      &lt;h6 class=&quot;portfolio-label&quot;&gt;DEAD&lt;/h6&gt;
    &lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/TestPlugin_JS.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;What do plugins do?&lt;/h2&gt;

&lt;p&gt;Plugins are intended for two main purposes. First, to communicate - through
javascript - with the 2D web, and second, to interact with objects within the
3d scene. Of course a plugin is a .NET assembly, so it can pretty much do
anything, but the main functions it is intended for are the above two. For
instance TestPlugin provides two javascript functions: one to inflict damage
and one to heal, basically allowing a regular 2d web application, for instance
an SNS site or an online game, to change the health meter of the avatar within
the 3d world according its own rules. Responding to these javascript functions
then, the plugin interacts with the 3d world by rendering its own little
health bar above the user’s head.&lt;/p&gt;

&lt;h2&gt;How to write plugins?&lt;/h2&gt;

&lt;p&gt;To make things as simple as possible, “Rei” uses the same method for
developing plugins as OpenSim. Essentially one writes an addin for the
&lt;em&gt;/OpenViewer/Managers&lt;/em&gt; extension by implementing the IManagerPlugin interface
and then creating and embedding a plugin manifest to the assembly.&lt;/p&gt;

&lt;h3&gt;IManagerPlugin&lt;/h3&gt;

&lt;p&gt;All plugins need to implement IManagerPlugin, which means implementing a few
methods:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Initialise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Viewer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;-&lt;strong&gt; Initialise &lt;/strong&gt;is the method that will be called right after constructing the plugin class. This will be only called once for the life of the plugin and is used to create objects that will persist through the entire lifetime such as static resources (textures, models), configurations.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Initialize&lt;/strong&gt; (note the &lt;strong&gt;z&lt;/strong&gt; in the name) will be called when “Rei” is getting ready to enter a region. This happens on the first startup as well as after logout or before entering a new region after a teleport. This is to make sure that unnecessary scene objects do not make it over to a new environment, therefore Initialize would create objects that persist only through the lifetime of one region, such as dynamic resources (textures, meshes) or dynamic information (region data, prim data)&lt;br/&gt;
Liquid error: Flag value is invalid: -O &quot;&quot;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;-&lt;strong&gt; Update&lt;/strong&gt; is called every frame. This is the place to calculate the next state of the plugin, including objects in the 3d scene. This is the only place where it is allowed to change properties of any object that is within the scenegraph. By using the frame parameter, it is possible to count or skip frames.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Draw&lt;/strong&gt; is also called every frame and it is where drawing directly to the 3d canvas is possible. Generally it is recommended to use proper scenenodes that draw automatically, instead of drawing directly.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Just like Initialize is called before “Rei” is ready to log in to a new region, &lt;strong&gt;Cleanup&lt;/strong&gt; is called every time a region is no longer needed, such as when logging out or when leaving a region by teleport. Cleanup is responsible of releasing resources that were allocated by Initialize (but not Initialise!)&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;RefController&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;This property is the entry point to &quot;Rei&quot;s core. Through this object it is possible to call into the public api of the viewer or to access javascript. &lt;strong&gt;Reference&lt;/strong&gt; must always be initialized from the viewer parameter passed in to Initialise()&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Communication with Javascript&lt;/h3&gt;

&lt;h5&gt;Plugin to Javascript: Dispatch&lt;/h5&gt;

&lt;p&gt;A plugin can call Reference.Viewer.Adapter.Dispatch(string action, string
message) when it wants to send a message to javascript. If a handler was added
to the javascript library for the particular action, this dispatch will be
processed by passing the message to the handler function. For future
compatibility it is recommended although not required that the message be
passed in json format.&lt;/p&gt;

&lt;h5&gt;Javascript to Plugin: Callback&lt;/h5&gt;

&lt;p&gt;The Adapter supplies a Callback delegate and a registry to handle calls from
Javascript. A plugin can register a callback method that it is interested in
receiving by calling&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Adapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RegisterCallback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;. It must pass the name of the method it wants to listen to and the method to
call when the event arrives. The way a Callback works is very much like
delegates work in the .NET framework.&lt;/p&gt;

&lt;p&gt;From the javascript side, one can use&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;method&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and all plugins that are listening to “method” will receive a callback to
their registered functions. For an example of Callbacks, you can see the
DoDamage and DoHeal from test.js and TestPlugin.cs&lt;/p&gt;

&lt;h5&gt;Plugin to Plugin: Message&lt;/h5&gt;

&lt;p&gt;It is also possible to send messages from one plugin to another, even without
being aware of the other plugin. The mechanism is very similar to Callbacks: a
plugin registers a message handler by calling&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Adapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RegisterMessage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;. The first parameter must be the name of the message to listen to and the
second one is a message handler delegate.&lt;/p&gt;

&lt;p&gt;A plugin can then raise a Message by calling&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Rerence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Adapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SendMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and all plugins that subscribed to the message being sent will receive it.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;alert-message block-message info&quot;&gt;
The contents of this post also appear on the github wiki for 3Di Viewer &quot;Rei&quot;. For
more up-to-date information, refer to
&lt;a href=&quot;http://wiki.github.com/3di/3di-viewer-rei/plugin-development&quot; class=&quot;btn&quot;&gt;REI PLUGINS WIKI&lt;/a&gt;
&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title>Irrlicht.NETCP and 3Di Rei on Linux</title>
      <link>http://zaki.asia/2009/11/05/irrlicht-netcp-rei-on-linux.html</link>
      <pubDate>Thu, 05 Nov 2009 12:49:06 -0800</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/11/05/irrlicht-netcp-rei-on-linux</guid>
      <description>&lt;div class=&quot;alert-message block-message info&quot;&gt;
I have started a cleaner code line which is now rebased to Irrlicht 1.7.1. Find the codes on
&lt;a href=&quot;http://github.com/zaki/irrlicht.net&quot; class=&quot;btn&quot;&gt;Github:Irrlicht.NET&lt;/a&gt;
&lt;/div&gt;


&lt;h3&gt;Irrlicht.NETCP&lt;/h3&gt;

&lt;p&gt;I've spent the last couple of weeks working towards rebasing the now abandoned
Irrlicht.NETCP to use the latest Irrlicht released: 1.6. There are multiple
reasons to do so, probably the most straightforward is to get the bugfixes or
some of the new features, like the new light manager. However the less direct
reason to do the rebase is that it includes Mac support out of the box - and
now that I have a macbook sitting on my desk at work (albeit, temporarily),
that is something of very high interest for me. In my dreamland, OpenGL ES
support (for the iPhone) would work without much work too - hey, I can dream,
can't I.&lt;/p&gt;

&lt;p&gt;So, for this rebase, I've started a new repo on github, that I hope will soon
become the official repository for 3Di Viewer &quot;Rei&quot;, and maybe even for users
of Irrlicht.NETCP (if any are still left, but who knows, maybe this can spark
some new interest). The repository starts with a clean Irrlicht 1.6 SDK and
gradually adds the fixes and features that are necessary for Rei (but of
course those are fixes and features that would probably come up in other
development as well).&lt;/p&gt;

&lt;p&gt;On top of the improvements to Irrlicht, there is one huge patch, that makes
the IrrlichtW wrapper compatible with 1.6. This mostly consists of type
changes in the method interfaces and other minor details, but the patch itself
is pretty monstrous, as many things changed at the same time. It is only after
this collective patch, that the .NETCP library is usable again (it won't even
compile before this fix, so be careful with the history).&lt;/p&gt;

&lt;p&gt;Later, IrrlichtML fixes were added. ML stands for multilingual and these
changes are required even though things finally started  moving away from c8*
to proper strings and io::paths in the core, stuff like IME support was not
included and the unicode support is still horrible to say the least.&lt;/p&gt;

&lt;h3&gt;Getting Irrlicht.NETCP&lt;/h3&gt;

&lt;p&gt;If you want to give the new Irrlicht.NETCP libraries a try, head to github:
&lt;a href=&quot;http://github.com/zaki/irrlicht.netcp&quot;&gt;http://github.com/zaki/irrlicht.netcp&lt;/a&gt;
and check out the sources (either using git, or click on download in github).
For the impatient, I've also uploaded binary files for 32-bit windows (Release
mode).&lt;/p&gt;

&lt;p&gt;To compile the libraries yourself, you will have to compile three components:
Irrlicht SDK, IrrlichtW and Irrlicht.NET, in basically this order. To compile
Irrlicht SDK, go to Irrlicht SDKsourceIrrlicht and open Irrlicht9.0.sln in
Visual Studio 2008 and build. IrrlichtW's solution is found in IrrlichtW,
named IrrlichtW.sln&lt;/p&gt;

&lt;p&gt;Irrlicht.NET uses Prebuild to create its solution files, so before you can
compile, the file runprebuild2008.bat needs to be run. That creates the
solution file Irrlicht.NET.sln, that can be opened and built in VS.&lt;/p&gt;

&lt;h3&gt;Rei and Irrlicht.NETCP&lt;/h3&gt;

&lt;p&gt;To use the new binaries with &quot;Rei&quot;, some minor changes need to be made to
Rei's source. I committed these changes to my github repository:
&lt;a href=&quot;http://github.com/zaki/3di-viewer-rei&quot;&gt;http://github.com/zaki/3di-viewer-rei&lt;/a&gt;, however the changes are not in the master branch, which I try to keep as
a clean integration copy (therefore there is a little time delay). Get the
Irrlicht 1.6 supporting sources from the 'linux' branch.&lt;/p&gt;

&lt;h3&gt;One more thing...&lt;/h3&gt;

&lt;p&gt;Ahem... did I just say 'linux' branch? Well, that's probably because I've also
started working on Rei linux support and so far things look quite bright (as
opposed to the MacOSX support, but maybe later about that). I managed to make
Rei run on my Ubuntu machine in standalone mode using Irrlicht.NETCP and mono.
There are still a ton of things that need fixing, but it's only a matter of
time before a consistent framerate is achieved - I had driver issues and
occasional performance problems, probably not unrelated. There are some
problems with JPEG2000 support that I didn't have time to look at yet and
haven't written shaders (OpenGL seems to hate HLSL shaders for some reason :),
but everything in its own time.&lt;/p&gt;

&lt;p&gt;So if you feel particularly adventurous, go ahead and grab the sources from
the 'linux' branch - Irrlicht.NETCP's master branch now includes linux support
-, compile them on your linux machine and do let me know how it works for you.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/3DiRei_onLinux.png&quot; width=&quot;660&quot; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Intelligent evolution</title>
      <link>http://zaki.asia/2009/09/16/intelligent-evolution.html</link>
      <pubDate>Wed, 16 Sep 2009 04:26:43 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/09/16/intelligent-evolution</guid>
      <description>&lt;p&gt;The two publications appeared practically at the same time and they started an
argument of epic proportions within the scientific community. Both scientists
claimed nothing less than having solved the mystery of the origin of life -
and not less important - of humankind. Two distinctly different, even
contradicting theories, two proofs. Both of them offering a complete solution:
from the proposed axioms, both of them explained the diversity -  the
development of the individual and the similarities between species not only
those currently existing but even those long extinct.&lt;/p&gt;

&lt;p&gt;Some questions did remain unanswered though. The two schools differed greatly
on their views on the mass extinctions during which time whole families of
species have disappeared leaving only a faint trace in the form of fossil
evidence: a skeleton here and there or an object we could connect to ancient -
primitive - species. The community was simply amazed when remains of a smaller
colony from a couple of thousands of years ago was unearthed, but even that
could not compare to what excitement spread through scientific journals when
fossils of a long disappeared ancient species were found in a rare excavation.
Scientists from both camps would throw themselves at the new samples, trying
to fit the new pieces of the puzzle to their theories.&lt;/p&gt;

&lt;p&gt;One group has claimed, that species evolved through a very coordinated, but
seemingly random process from other - usually more primitive - species.
Through time, organs that were more useful for survival have been - in a
manner - selected. It's as if there was an algorithm in nature that
experiments with randomly changing the variables, keeping results that it
deems good while terminating those it finds unworthy. This algorithm has been
present for millions if not billions of years (some even went as far as
proposing that the same process can be found before life itself appeared).
There was however a strange gap between humans of the long gone past and
humans of the present - as if only the right fossils that would bridge this
gap were hiding somewhere, waiting to be found one day.&lt;/p&gt;

&lt;p&gt;Followers of this theory - called evolutionists - found that pieces of evidence
fit their theory perfectly. They argued, that evolution of the present humans
from ancient human forms is completely possible, as the natural selection
process would experiment practically randomly, therefore given enough time,
ancestor  species could be significantly different from descendant species.
The other group also proposed a complete explanation, however their theory
immediately caused an uproar in the scientific community. They claimed that
present form humans have not appeared through a lengthy process of evolution,
rather, it was created through an intelligent design. Their theory proposed
that present day humans were created by an ancient, intelligent entity, or
even by the - in lack of a better word - consciousness of some ancient
species. Many would instantly distance themselves from members of this second
group and some even went as far as calling the professor that first published
this  theory an idiot. As the arguments started to spiral out of hand, finally
a well-known scientific association has organized a public forum for members
of these groups where they were given the chance to present their findings
and evidence. In the heated debate, followers of the school of evolution would
claim that intelligent design is unscientific, while proponents of intelligent
design would argue on the improbability of random evolution. A noted professor
of the second group was quoted to say:&lt;/p&gt;

&lt;p&gt;&quot;I firmly believe that humans were created by an ancient intelligent designer.
The probability of complex organs evolving at random is not in accordance with
nature. The probability of a complex structure evolving randomly is provably
smaller than the theoretically conceivable smallest probability in the
Universe. It is laughable to assume that the organ we know as our brains have
evolved at random from lesser life forms. I don't think it is even
theoretically possible that the our alleged ancestors' primitive
carbohydrate-based organs would spontaneously evolve into our immeasurably
complex silicon chips.&quot;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Slowly getting there...</title>
      <link>http://zaki.asia/2009/09/08/3di-openviewer-textures.html</link>
      <pubDate>Tue, 08 Sep 2009 01:20:37 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/09/08/3di-openviewer-textures</guid>
      <description>&lt;h4&gt;OSGRID IN 3DI OPENVIEWER&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/osgrid_textures.jpg&quot; width=&quot;660&quot; height=&quot;460&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;OSGRID IN HIPPO VIEWER&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/osgrid_hippo.jpg&quot; width=&quot;660&quot; height=&quot;460&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pretty close, but still not close enough. I guess, I'll need to take a deep,
hard look at PrimMesher too.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to install and use 3Di OpenViewer</title>
      <link>http://zaki.asia/2009/08/19/how-to-install-and-use-3di-openviewer.html</link>
      <pubDate>Wed, 19 Aug 2009 02:06:27 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/08/19/how-to-install-and-use-3di-openviewer</guid>
      <description>&lt;div class=&quot;alert-message block-message info&quot;&gt;
For updates about 3Di Viewer &quot;Rei&quot;'s features (particularly textures
and avatars), also see the post &lt;a href=&quot;/2009/12/21 /osgrid-in-rei&quot; class=&quot;btn&quot;&gt;
OsGrid in Rei&lt;/a&gt;&lt;/div&gt;


&lt;h2&gt;How to install 3Di OpenViewer?&lt;/h2&gt;

&lt;p&gt;First, please note, that the viewer is currently for Windows only and
3Di only supports Internet Explorer 6+ and Firefox 3.0 and 3.5 at this time.&lt;/p&gt;

&lt;h3&gt;Step 1.&lt;/h3&gt;

&lt;h6&gt;Internet Explorer&lt;/h6&gt;

&lt;p&gt;Go to &lt;a href=&quot;http://www.3di-opensim.com/openviewer/ie_install.html&quot;&gt;http://www.3di-opensim.com/openviewer/ie_install.html &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ActiveX bar will appear, click Install&lt;/p&gt;

&lt;h6&gt;Firefox&lt;/h6&gt;

&lt;p&gt;Go to &lt;a href=&quot;http://3di-opensim.com/openviewer/ff_install.html&quot;&gt;http://3di-opensim.com/openviewer/ff_install.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the orange button with the arrow to download and install the plugin.&lt;/p&gt;

&lt;h3&gt;Step 2.&lt;/h3&gt;

&lt;p&gt;The installer will appear.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/p_install06.jpg&quot; alt=&quot;3Di OpenViewer Installer screen 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The first screen is only an introduction. It asks you to close other
applications before clicking next. The left button says Next, the right one is
Cancel.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/p_install07.jpg&quot; alt=&quot;3Di OpenViewer Installer screen 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The second screen is the EULA. I won't try to translate it to english, you can
get a raw English version by pushing this through any online translation
service. The long and the short of it was summarized in these two sentences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No commercial use&lt;/li&gt;
&lt;li&gt;No reverse engineering&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The first radio button says Agree, the second says Disagree. Again the buttons
are Back, Next and Cancel in that order. I guess it is pretty difficult to
Agree with something you can't read (I always feel that way in Japan :) ).
There are no traps in there and as long as you don't use it to become a
millionaire celebrity without 3Di's consent, you should be alright. (If you
happen to be a millionaire celebrity already, you should definitely contact us
:) )&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/p_install08.jpg&quot; alt=&quot;3Di OpenViewer Installer screen 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The next screen has three buttons saying Back, Install and Cancel
respectively. After clicking Install, it will start the automatic install
process. When it finishes, you can click on the Finish button on the next
screen.&lt;/p&gt;

&lt;h2&gt;Is it possible to use 3Di OpenViewer in English?&lt;/h2&gt;

&lt;p&gt;This question is asked many times lately, so here's a short guide on how to do
it. Please do note, that this is sort of a pre-release thing, that might in
some places be a little rough around the edges. And if you find any leftover
Japanese text after the switch, do let me know.&lt;/p&gt;

&lt;p&gt;When you install the viewer, and open a page with the viewer embedded, it will
appear in default Japanese locale, but it is possible to change this to
English. There are two ways to do it: you can log in to an OpenSim grid with
the Japanese version and change the locale from the menu, or you could change
the configuration file to make the viewer appear in English from the first
login page. Either method you choose, you will have to start the viewer at
least once (to initialize the necessary directories and configuration files).&lt;/p&gt;

&lt;p&gt;Method 1 - Using the menu&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/openviewer_login_jp.jpg&quot; alt=&quot;3Di OpenViewer login Japanese&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Using the login screen, specify the
login URI, first name, last name and password in that order, then click on the
button to log in.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/openviewer_settings_jp.jpg&quot; alt=&quot;3Di OpenViewer settings Japanese&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After you log in, move the
cursor towards the upper right corner until the menu appears. Click on the
wrench icon to go to settings. The last selectbox on the first tab is the
locale, you should select the first option and press OK. A dialog will appear
telling you that the settings will be effective after you restart the viewer.
Do so, and the UI will appear in English now.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/openviewer_login_en.jpg&quot; alt=&quot;3Di OpenViewer login English&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Method 2 - Changing the configuration file&lt;/p&gt;

&lt;p&gt;After you start the viewer, the configuration file will be created in your
local settings directory. On XP, this will be in
&lt;code&gt;Documents and Settings/&amp;lt;username&amp;gt;/Local Settings/Application Data/3Di/OpenViewer/&lt;/code&gt;, while on
Vista and Win7, this will be in
&lt;code&gt;Users/&amp;lt;username&amp;gt;/AppData/LocalLow/3Di/OpenViewer&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open the file in configs/ called &lt;code&gt;OpenViewer.ini&lt;/code&gt; and change locale to en&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;locale = en
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Start the viewer again and it should be in English now.&lt;/p&gt;

&lt;h2&gt;Can I connect to OpenSim grids?&lt;/h2&gt;

&lt;p&gt;The short answer is 'yes'. The long answer is 'yes, but'. You can definitely
log in to OpenSim grids with the current release version and prims will
display. However textures and the avatar will not currently appear. The reason
for this is that assets are not downloaded through the region server. We are
working on a fully compatible version that we will release in the future, but
for the moment to get the full experience, unfortunately you will have to
connect to 3Di's servers. We are also preparing more demo servers, but I have
to ask for just a little more patience on that.&lt;/p&gt;

&lt;p&gt;If you try 3Di OpenViewer, your feedback is always appreciated.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>FreeSWITCH, OpenSim and the G722.1C codec</title>
      <link>http://zaki.asia/2009/05/18/freeswitch-opensim-and-the-g7221c-codec.html</link>
      <pubDate>Mon, 18 May 2009 17:48:53 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/05/18/freeswitch-opensim-and-the-g7221c-codec</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.talentraspel.de/&quot;&gt;Kai Ludwig&lt;/a&gt; has recently left a very valuable
comment (thank you, Kai):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Actually the new FreeSwitch siren14 codec has never been used with SLVoice!
Everybody having voicechat with OpenSim is using PCMU without knowing it.
&lt;small&gt;Kai Ludvig&lt;/small&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I didn't realize that at first either, but after he pointed this out,
I started looking for a way to enable siren14. I haven't really come
up with a way to use the SLVoice.exe included with the SecondLife viewer,
rather, I modified the
&lt;a href=&quot;http://github.com/zaki/slvoice&quot;&gt;voipforvw&lt;/a&gt; codes to support it.
Voice quality is now way better than the stock PCMU. &lt;img src=&quot;/images/voip/freeswitch_g7221c.jpg&quot; alt=&quot;Connecting to
FreeSWITCH with G722.1&quot; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to compile Voipforvw's SLVoice</title>
      <link>http://zaki.asia/2009/05/10/how-to-compile-voipforvws-slvoice.html</link>
      <pubDate>Sun, 10 May 2009 01:18:08 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/05/10/how-to-compile-voipforvws-slvoice</guid>
      <description>&lt;h2&gt;What is Voipforvw?&lt;/h2&gt;

&lt;p&gt;With the SecondLife viewer comes an executable named SLVoice.exe. This is the
piece of software that is responsible for the &quot;low level&quot; voice communication,
so while the viewer does the accounting (login information, UI), this part
does all the heavy lifting of contacting the voice servers and of course
translating the voice of the speaker to RTP packets and back.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://sourceforge.net/projects/voipforvw/&quot;&gt;voipforvw&lt;/a&gt;
(voip for virtual worlds) is a replacement for this executable.
The core of this application was originally developped by
&lt;a href=&quot;http://www.3di.jp/en/index.html&quot;&gt;3Di&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Why should I care about it?&lt;/h2&gt;

&lt;p&gt;The original SLVoice was developped for Linden Labs by a
company named &lt;a href=&quot;http://www.vivox.com/&quot;&gt;Vivox&lt;/a&gt; and has a proprietary license.
The good news is, that it is insanely high quality (it runs on a couple of
platforms and powers virtual worlds like SecondLife and games like EVE Online).
It also has 3D positional audio.&lt;/p&gt;

&lt;p&gt;The bad news is that it's proprietary to
the point that you are explicitly disallowed from using it for OpenSim.
The &lt;a href=&quot;http://www.vivox.com/open/faq.php&quot;&gt;FAQ&lt;/a&gt; on vivox's home page explicitly says:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;h4&gt;Can I distribute this to friends?&lt;/h4&gt;
&lt;strong&gt;No&lt;/strong&gt;, currently Vivox software and service is offered for individual, non-commercial use only.&lt;/p&gt;

&lt;p&gt;&lt;h4&gt;Can I use this outside of SecondLife&lt;/h4&gt;
&lt;strong&gt;No&lt;/strong&gt;, the currently offered software is only available for the Second Life Viewer open source community.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;What's the catch?&lt;/h2&gt;

&lt;p&gt;Well, unfortunately there &lt;em&gt;is&lt;/em&gt; a catch. The license of the SIP/RTP stack
used in vopforvw is GPL. This has a simple effect on the whole project, that
is, voipforvw automatically becomes GPL. Unfortunately currently there is no
good library that comes with a BSD-like license, the closest we can get is
LGPL. (If you happen to know of one, please do let me know in the comments).
While I'm a fan of C#, there is basically no free SIP/SDP library of any
license for C# either.&lt;/p&gt;

&lt;p&gt;Second, at the moment noone is maintaining the Linux version: in theory it
should compile just OK, but that is not something I'd personally guarantee. I
will try to look into that later.&lt;/p&gt;

&lt;h2&gt;But it's difficult to use.&lt;/h2&gt;

&lt;p&gt;I've heard this argument for quite some time: it is probably my failure to not do
much about it . Compiling the SLVoice replacement is not really that difficult. If
you have problems with building, take a look at the screencast below and see
if it can help fixing your problem. And of course, you can leave comments here&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please note:&lt;/strong&gt; trunk contains a version that only works with SLViewer versions
below 1.22 (1.19, 1.20 and 1.21 were tested). For 1.22, I started a branch named
sl_1.22 that contains an updated version that - in turn - only works with 1.22.
As I am not allowed to look at the viewer's source code, many thanks go to yk,
who described the major API changes to me. Unfortunately this also means, that I can't
guarantee that the 1.22 version works properly. At least I had success making conferences
work with that branch, but further testing will be needed for it to be integrated
back into trunk.&lt;/p&gt;

&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;640&quot; height=&quot;505&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/snEyl-hLhVo&amp;amp;hl=en&amp;amp;fs=1&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;640&quot; height=&quot;505&quot; src=&quot;http://www.youtube.com/v/snEyl-hLhVo&amp;amp;hl=en&amp;amp;fs=1&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;h2&gt;What will I need?&lt;/h2&gt;

&lt;p&gt;You will need voipforvw, that you can check out from sourceforge.net:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;svn co https://voipforvw.svn.sourceforge.net/svnroot/voipforvw voipforvw
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, you will need &lt;a href=&quot;http://www.boost.org/&quot;&gt;boost&lt;/a&gt;,
&lt;a href=&quot;http://curl.haxx.se/download.html&quot;&gt;curl&lt;/a&gt; and
&lt;a href=&quot;http://www.pjsip.org/download.htm&quot;&gt;pjsip&lt;/a&gt;. The versions that I was using are
1.39, 7.19.4 and 1.0.2 respectively. For PjSIP, 1.x series will currently not
work due to API changes.&lt;/p&gt;

&lt;p&gt;For compiling on Windows, you will also need the Platform SDK and DirectX SDK.
Voipforvw uses &lt;a href=&quot;http://www.cmake.org/cmake/resources/software.html&quot;&gt;CMake&lt;/a&gt; for
its configuration too.&lt;/p&gt;

&lt;h3&gt;Step 1. Compile dependencies&lt;/h3&gt;

&lt;p&gt;Set up the platform SDK and DirectX SDK folders in Visual Studio.&lt;/p&gt;

&lt;p&gt;Compile boost with bjam. To build bjam first, just run build.bat, which
creates bjam.exe; use that in the boost directory with the following
commandline:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bjam --toolset&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;msvc &lt;span class=&quot;nv&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;static runtime-link&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;static &lt;span class=&quot;nv&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;multi --with-thread stage
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To compile cURL, open the solution file, change the build type to Release and
set the Runtime Library to Multithreaded (&lt;code&gt;/MT&lt;/code&gt;). These changes are necessary,
because we will be using multiple boost state machines from a multithreaded
environment. Build only libcurl.&lt;/p&gt;

&lt;p&gt;PjSIP will need you to move the file &lt;code&gt;pjlib/include/pj/config_site_sample.h&lt;/code&gt;
into &lt;code&gt;config_site.h&lt;/code&gt; No changes are necessary to this file, the defaults will
work fine.&lt;/p&gt;

&lt;p&gt;Open  pjproject-vs8.sln (and convert it as needed) set it to Release and build
the solution.&lt;/p&gt;

&lt;h3&gt;Step 2: Configure and build voipforvw&lt;/h3&gt;

&lt;p&gt;Next, go to the voipforvw trunk and edit CMakeLists.txt You will need to
change the paths for &lt;code&gt;PJDIR&lt;/code&gt;, &lt;code&gt;CURLDIR&lt;/code&gt; and &lt;code&gt;BOOSTDIR&lt;/code&gt;. Don't use backslashes,
replace them with forward slashes. The &lt;code&gt;CURLLIBS&lt;/code&gt; variable needs to be changed
from curllib.lib to libcurl.lib.&lt;/p&gt;

&lt;p&gt;Open up CMake-gui and set the source directory to the voipforvw trunk. The
output directory can be the same. Hit Configure (it will probably complain
about backwards compatibility, but just ignore it and hit Configure again). If
configuring goes well, there will be no red lines in the config window. Hit
Generate, which will ask for the format of the solution file, choose the Visual
Studio version you have and click OK. This creates the main solution file.&lt;/p&gt;

&lt;p&gt;After opening this solution, there are three things you will need to check:
first, set the build type to Release. Next check that the Runtime Library is
Multithreaded (&lt;code&gt;/MT&lt;/code&gt;) to match the other libraries and finally, &lt;code&gt;LIBCMT&lt;/code&gt; will have
to be removed from the libraries (because it conflicts with &lt;code&gt;MSVCRT&lt;/code&gt;). Now you
can build SLVoice.exe that you can use as a replacement for the vivox
solution.&lt;/p&gt;

&lt;h3&gt;Debug&lt;/h3&gt;

&lt;p&gt;You probably noticed that we are building everything in Release mode. That's
fine as long as it works, but sometimes you will want to debug (hopefully less
often). In this case you will need to change the Runtime Library to &lt;code&gt;/MTd&lt;/code&gt; for
PjSIP and voipforvw. Then CMakeLists.txt needs to be updated to reflect this
by setting&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SET (PJTARGET i386-win32-vc8-debug)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where you remove the &lt;code&gt;LIBCMT&lt;/code&gt; library, now you will have to do the same thing
for both &lt;code&gt;LIBCMT&lt;/code&gt; and &lt;code&gt;LIBCMTD&lt;/code&gt; and you can build SLVoice.exe in debug mode.&lt;/p&gt;

&lt;p&gt;If you only need logging to see what's going on inside, you can change the
code:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// CHANGE FILE: main.h:37&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define LOG&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef LOG&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logfp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define VFVW_LOGINIT()     logfp = fopen(&amp;quot;test.log&amp;quot;, &amp;quot;a&amp;quot;)&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define VFVW_LOG(fmt, ...) fprintf(logfp, &amp;quot;[VFVW] %s:%d - &amp;quot;, __FILE__,__LINE__); \&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;                           fprintf(logfp, fmt, ## __VA_ARGS__); \&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;                           fprintf(logfp, &amp;quot;\r\n&amp;quot;); \&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;                           fflush(logfp)&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define VFVW_LOGINIT()     void()&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define VFVW_LOG(fmt, ...) void()&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;//CHANGE FILE main.cpp:15&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef LOG&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logfp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</description>
    </item>
    
    <item>
      <title>3Di OpenViewer Feature Focus: Login</title>
      <link>http://zaki.asia/2009/05/01/3di-openviewer-feature-focus-login.html</link>
      <pubDate>Fri, 01 May 2009 16:04:03 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/05/01/3di-openviewer-feature-focus-login</guid>
      <description>&lt;p&gt;3Di OpenViewer provides a number of ways to connect to a grid, let's look at
those in a little more detail.&lt;/p&gt;

&lt;h3&gt;Manual&lt;/h3&gt;

&lt;p&gt;Manual login is the normal way, that everyone using
SecondLife is already used to. This mode will show
a login box right within the application and will allow you to specify the
login URI, the first and last name and password. You can set the default
values with additional params as well.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;LoginMode&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;manual&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Optional--&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;ServerURI&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;http://1.2.3.4:10001&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;FirstName&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;first&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;last&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Password&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/manual_login.jpg&quot; alt=&quot;3Di OpenViewer manual login&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Click&lt;/h3&gt;

&lt;p&gt;Click login is great if you want to specify all the information for  the login
and not allow the user to change it in any way (for example dynamically
creating the login page based on already existing session information). In
this case, the user can only see an empty screen with no login box; when they
click on this screen, login starts automatically.&lt;/p&gt;

&lt;p&gt;Of course in click mode, you will have to specify all the login information
like above and possibly provide explanation somewhere on your site.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;LoginMode&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;img src=&quot;/images/3di-openviewer/hide_login.jpg&quot; alt=&quot;3Di OpenViewer click login&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Hide&lt;/h3&gt;

&lt;p&gt;Users can also use a JavaScript function to log in. Sometimes, it is better
not to allow users to specify any information, but at the same time, login
information can dynamically change at any time. In this case, you can set the
login mode to hide, which will not show the login box, but also not allow
login from within the application. Rather, it only allows external JavaScript logins.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;param&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;LoginMode&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hide&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To log in from JavaScript, use the following function:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;openviewerCtl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lastname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;server_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;login_location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For the JavaScript login method, it is also possible to specify the exact
location to log in to. The format is&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;// &amp;quot; uri:regionname&amp;amp;x&amp;amp;y&amp;amp;z&amp;quot;
     uri:region1&amp;amp;128&amp;amp;128&amp;amp;25
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</description>
    </item>
    
    <item>
      <title>FreeSWITCH module in OpenSim</title>
      <link>http://zaki.asia/2009/04/28/freeswitch-module-in-opensim.html</link>
      <pubDate>Tue, 28 Apr 2009 03:26:01 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/04/28/freeswitch-module-in-opensim</guid>
      <description>&lt;div class=&quot;alert-message block-message info&quot;&gt;
&lt;strong&gt;Update&lt;/strong&gt;: OpenSim has changed substantially since this post, so my explanation will probably not work anymore.
&lt;/div&gt;


&lt;p&gt;It seems that Linden Labs has finally removed the hardcoded vivox.com references
in 1.22 making third party voice chat work with the original slvoice.exe.&lt;/p&gt;

&lt;p&gt;At the same time Rob Smart from IBM stepped up the game and
provided a solution for FreeSWITCH that now also works without an SLVoice
replacement. I've also been looking at FreeSWITCH for a while and just when
I finally have some spare time to play around with it, this new module comes out:
and it's really awesome! First of all, it works without having to install kernel
modules or suffer the lack of proper SIP Session-Timer (RFC4028) implementations.&lt;/p&gt;

&lt;p&gt;There are three components needed for this setup.&lt;/p&gt;

&lt;h2&gt;OpenSim&lt;/h2&gt;

&lt;p&gt;Because the new FreeSWITCH module is experimental, it
is only found in trunk, and as usual, please note, that trunk is &lt;strong&gt;unstable
&lt;/strong&gt;it might have serious bugs, it can corrupt your data, or &lt;a href=&quot;https://lists.berlios.de/pipermail/opensim-%0Ausers/2009-April/001878.html&quot;&gt;eat your
children&lt;/a&gt;, especially if you do the unthinkable and try to
install it in a production environment, which you should never do. Ever! No
exceptions. If you are brave enough, you can proceed very carefully and try
out the trunk.&lt;/p&gt;

&lt;h2&gt;FreeSWITCH&lt;/h2&gt;

&lt;p&gt;I tried the Windows binary snapshot from
&lt;a href=&quot;http://wiki.freeswitch.org/wiki/Installation_Guide&quot;&gt;here&lt;/a&gt;: and it works
well. For configuration instructions take a look at the &lt;a href=&quot;http://opensimulator.org/wiki/Freeswitch_Module&quot;&gt;OpenSim wiki
page&lt;/a&gt;. Linux installation
instructions are also included there.&lt;/p&gt;

&lt;h2&gt;SecondLife Viewer&lt;/h2&gt;

&lt;p&gt;Only versions later than 1.22 are supported, so be sure to grab a newer version from Linden Labs.&lt;/p&gt;

&lt;h2&gt;Final touches&lt;/h2&gt;

&lt;p&gt;After setting up FreeSWITCH and OpenSim, connecting to the grid and enabling
voice chat by default nothing will happen.
Conference chat won't work with the default estate settings, because
parcel voice is disabled. In the video, I'm setting &quot;Use a private spatial
channel&quot;, but &quot;Use the estate spatial channel&quot; should work as well. Enable
voice, and it will work now. After this, conference and private chat features
will work. On my setup, I found that private chat is quite clear and easy to
understand, but the spatial conferences are way too low quality, but that might be
a configuration issue on my environment.&lt;/p&gt;

&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;640&quot; height=&quot;505&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/7k_xQQOcYDk&amp;amp;fmt=22&amp;amp;hl=en&amp;amp;fs=1&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6&amp;amp;hd=1&amp;amp;border=0&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;640&quot; height=&quot;505&quot; src=&quot;http://www.youtube.com/v/7k_xQQOcYDk&amp;amp;fmt=22&amp;amp;hl=en&amp;amp;fs=1&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6&amp;amp;hd=1&amp;amp;border=0&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>3Di OpenViewer</title>
      <link>http://zaki.asia/2009/04/24/3di-openviewer.html</link>
      <pubDate>Fri, 24 Apr 2009 03:31:19 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2009/04/24/3di-openviewer</guid>
      <description>&lt;p&gt;Disclaimer: I am a senior engineer working on multiple products - including
various OpenSim technologies and most recently 3Di OpenViewer - at Japan-based
3Di Inc. This is a personal blog, and my opinion does not necessarily always
represent that of my employer.&lt;/p&gt;

&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;425&quot; height=&quot;344&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/r_lbBw6wFRQ&amp;amp;hl=en&amp;amp;fs=1&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;344&quot; src=&quot;http://www.youtube.com/v/r_lbBw6wFRQ&amp;amp;hl=en&amp;amp;fs=1&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;3Di has &lt;a href=&quot;http://3di-opensim.com/demo-ec/index.html&quot;&gt;released&lt;/a&gt; (Japanese) its
virtual world viewer last week. It is an embedded viewer, that works directly
in a web browser; it connects to the virtual world server solution also
provided by 3Di, called &lt;a href=&quot;http://3di-%0Aopensim.com/product/feature/&quot;&gt;3Di OpenSim Enterprise 1.0&lt;/a&gt; (Japanese) that has quite a few addition on top
of the &lt;a href=&quot;http://opensimulator.org&quot;&gt;community version&lt;/a&gt;, utilizes much more than
just SL prims to create a nice looking environment even within the limitations
of the web-browser.&lt;/p&gt;

&lt;h2&gt;Open?!&lt;/h2&gt;

&lt;p&gt;Let's get the biggest question out of the way first: the virtual ink on the
press release hasn't even dried, but I was already asked where one could
download the source code. After all, it is called _Open_Viewer isn't it.&lt;/p&gt;

&lt;p&gt;The short answer is: it &lt;em&gt;will&lt;/em&gt; be released as open source at a later - not too
distant - stage. Personally I think that opening up the viewer will be crucial
for two simple reasons: first, the future of OpenSim depends on a viewer that
opensim developers can look at without running the risk of getting burned by
the license - and serious innovation requires some degree of control (I met
with &quot;we can't do that without changing the viewer&quot; so many times). Second,
tying back to the first reason, personally I think we are in a kind of a
deadlock with the SL protocol. It was never designed for the sort of things
the opensim community dreams about: rather, it is a very centralized, &quot;the
region server does everything&quot; sort of protocol, that needs a fertile testing
ground in the shape of a viewer that you can bend to your own will.&lt;/p&gt;

&lt;p&gt;When exactly can you get the source code? I don't really have the answer to
this question, as it is not nearly my decision. For now, just keep an eye on
this viewer because we are going to deliver some features that I hope will
show everyone that by changing the viewer, you can accomplish extraordinary
things.&lt;/p&gt;

&lt;h2&gt;Features&lt;/h2&gt;

&lt;p&gt;The main distinction is of course that this viewer runs directly inside the
browser. Now, does that mean, that it is forever constrained within the limits
of a solitary HTML page? Not really.Internally we sometimes use a standalone
version for testing, so technically there is nothing stopping someone to
&quot;liberate&quot; (as I'm sure many would call it so:) ) the viewer from the evil
browser. Our first target was IE only (boohoo, yes) and at the very least
people can start using it they way they are already used to after years of
experience with ye' olde series of tubes and, equally importantly, provide us
with feedback on the important questions (no, not about our plugin system or
our 3D engine). And the next stop is Firefox and Safari support.&lt;/p&gt;

&lt;p&gt;The viewer itself is operated with the mouse only. This makes it simple and
straightforward; on the other hand, there are not so many actions to do: you
can walk around, run about, sit down to objects or touch objects.  More
complicated actions like chat or teleporting are of course in a simplified
menu system. Our first priority is to make OpenSim - and virtual worlds in
general - accessible to a wide audience. This will hopefully help the
community indirectly as well as more and more people get used to using virtual
worlds, more businesses will join the ride. Of course we could have gone to
the other extreme and create a highly customizable meta-GUI system, but for
the uninitiated first-time virtual world user, that wouldn't really help.&lt;/p&gt;

&lt;p&gt;The SL Viewer supports prims, which is a great thing if you have a limited
bandwidth. Or if you push every single bit through your region server. But
realistically, getting professional content into SecondLife can pose a
challenge because of this. As realXtend has also realized this before, 3Di
OpenViewer also enables content providers to use their usual 3D content
created with most major 3D modelling software like 3DS Max or Maya with little
or no change. This should further lower the entry barrier to many CPs that
don't really have the time and resources to invest in creating prims for all
of their popular contents. If they can import their content as-is, the cost
goes down and at the same time customer satisfaction goes up. In turn, there
is an increase in virtual world penetration, that is good for 3Di as well as
the community. (Hopefully the trend to make virtual worlds popular and more
accessible can be seen here)&lt;/p&gt;

&lt;p&gt;The last new feature for today is the JavaScript API: we are providing ways
for a fair amount of intercommunication with a CP's HTML content and
OpenViewer.You want to create an e-commerce solution in OpenSim supporting
currency? Why go to the trouble of recreating your already existing EC in the
virtual world, when you can quite easily communicate between the 3D world and
the 2D world. The demo site is actually showing a mockup for an EC site that
doesn't require lengthy configurations and recompilation of OpenSim. No, it's
not an end-all-be-all, but it's a simple solution that one can use to quickly
start up a new business in the virtual worlds.&lt;/p&gt;

&lt;h2&gt;In closing&lt;/h2&gt;

&lt;p&gt;There might be two things apparent from this post: first, I tried to convey
why I think a new viewer, and specifically an in-browser viewer is good for
the community. Second, I never talked about technical details. This latter, I
am planning to ammend in a later post, but first I just wanted to make it
clear that 3Di OpenViewer is not a product in isolation, and although it is
only a first step towards a bright future for OpenSim and virtual worlds in
general, I believe that it will be a significant one. So please keep an eye on
the product, and do post any feedback you might have in the comments.&lt;/p&gt;

&lt;p&gt;&lt;object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&quot; width=&quot;425&quot; height=&quot;344&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;src&quot; value=&quot;http://www.youtube.com/v/3dlATmXQCtc&amp;amp;hl=en&amp;amp;fs=1&quot; /&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;embed type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;344&quot; src=&quot;http://www.youtube.com/v/3dlATmXQCtc&amp;amp;hl=en&amp;amp;fs=1&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Voice chat in OpenSim</title>
      <link>http://zaki.asia/2008/08/28/getting-voice-chat-in-opensim.html</link>
      <pubDate>Thu, 28 Aug 2008 22:07:49 -0700</pubDate>
      <author>dezso.zoltan@gmail.com (Zoltan Dezso)</author>
      <guid>http://zaki.asia/2008/08/28/getting-voice-chat-in-opensim</guid>
      <description>&lt;div class=&quot;alert-message block-message info&quot;&gt;
  The content of this post is outdated. To learn more about the new
  FreeSWITCH connector in OpenSim, go to&lt;br /&gt;
  &lt;a href=&quot;/2009/04/28/freeswitch-module-in-opensim/&quot; class=&quot;btn primary&quot;&gt;FreeSWITCH module in OpenSim&lt;/a&gt;
&lt;/div&gt;


&lt;hr /&gt;


&lt;h1&gt;Overview&lt;/h1&gt;

&lt;p&gt;If you want to set up voice chat for your grid, here is a rundown on what you
will need and how it works.&lt;/p&gt;

&lt;p&gt;OpenSim currently uses the Asterisk PBX server through a dynamic, MySQL-based
configuration that is updated by a &quot;frontend&quot; python script. This frontend
is invoked by an SLVoice replacement when a user REGISTERs to
the SIP channel configured for the region.&lt;/p&gt;

&lt;p&gt;For this, SLVoice requires two pieces of information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The address of the &quot;frontend&quot;&lt;/li&gt;
&lt;li&gt;The address of asterisk to register with&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The region server must provide the asterisk address to the viewer, which in turns
will pass it down to SLVoice. Similarly, the address of the frontend is set in
OpenSim.ini and registration happens via the AsteriskVoice module in
Region.Environment.Modules.Avatar.Voice&lt;/p&gt;

&lt;p&gt;However for private chats - by limitation of the SLViewer - SLVoice always receives
a hard-coded SIP URI that then needs to be changed to the real address. For flexibility
this URI is queried at runtime from an HTTP server (the address of which needs to be set
in slvoice.ini).&lt;/p&gt;

&lt;p&gt;After SLVoice has registered through the frontend, it can contact the Asterisk service
and start the real voice chat.&lt;/p&gt;

&lt;h1&gt;Installation&lt;/h1&gt;

&lt;h2&gt;Zaptel&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://downloads.digium.com/pub/telephony/zaptel/&quot;&gt;http://downloads.digium.com/pub/telephony/zaptel/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Zaptel is a kernel module that allows asterisk to use various telephony hardware, but for
our purposes it is only needed for the MeetMe conference application that depends on a hardware
timer. Because of this, the ztdummy kernel module is what we will need.&lt;/p&gt;

&lt;p&gt;Zaptel requires that you have&lt;/p&gt;

&lt;p&gt;&lt;em&gt;bison, bison-devel newt, newt-devel ncurses, ncurses-devel&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Installation is straightforward: &lt;em&gt;&lt;strong&gt;./configure; make; make install &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;(Note: You need to be root to install zaptel)&lt;/p&gt;

&lt;p&gt;After installation, make sure you run &lt;strong&gt;&lt;em&gt;modprobe ztdummy; modprobe zaptel&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Asterisk&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.asterisk.org/&quot;&gt;&lt;strong&gt;http://www.asterisk.org/&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you start, please make sure the following are installed:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;mysql, mysql-connector-odbc unixODBC-devel libtool-ltdl-devel kernel-devel&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The latest versions of Asterisk don't include the sources for the codec iLBC
anymore. If you want those supported, please run contrib/scripts/get_ilbc_source.sh&lt;/p&gt;

&lt;p&gt;It is advised that you run &lt;strong&gt;&lt;em&gt;make menuselect&lt;/em&gt;&lt;/strong&gt; and configure the modules
before you install asterisk. You will need &lt;code&gt;res_odbc&lt;/code&gt; to interface properly with
MySQL. Also make sure that &lt;code&gt;ztdummy&lt;/code&gt; and &lt;code&gt;app_meetme&lt;/code&gt; are marked for install. Then
&lt;strong&gt;&lt;em&gt;make; make install&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;OpenSim&lt;/h2&gt;

&lt;p&gt;Get OpenSim and apply [Patch 1689] (&lt;a href=&quot;http://opensimulator.org/mantis/view.php?id=1689&quot;&gt;http://opensimulator.org/mantis/view.php?
id=1689&lt;/a&gt;) to get private
chat working.&lt;/p&gt;

&lt;h3&gt;Asterisk Frontend&lt;/h3&gt;

&lt;p&gt;The current frontend requires Python2.5 with mysql support
(&lt;a href=&quot;http://sourceforge.net/projects/mysql-python&quot;&gt;http://sourceforge.net/projects/mysql-python&lt;/a&gt; if not included in the
distribution) The frontend can be found in &lt;strong&gt;&lt;em&gt;share/python/asterisk/&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;Configuration&lt;/h1&gt;

&lt;h2&gt;Asterisk&lt;/h2&gt;

&lt;p&gt;In MySQL, create a database and add an 'asterisk' user by&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;    &lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DATABASE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asterisk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;GRANT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asterisk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asterisk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDENTIFIED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;password&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The frontend will create the schema on first start.&lt;/p&gt;

&lt;p&gt;Set up ODBC:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/odbcinst.ini&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;&lt;span class=&quot;k&quot;&gt;[MySQL]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MySQL For Asterisk&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;Driver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/lib/libmyodbc3.so&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;Setup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/lib/libodbcmyS.so&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;FileUsage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;/etc/odbc.ini&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;  &lt;span class=&quot;k&quot;&gt;[asterisk]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Driver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MySQL&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;server address&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Database&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;asterisk&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3306&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;asterisk&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;*********&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Socket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Option&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Stmt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;/etc/asterisk/extconfig.conf&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;    sipusers =&amp;gt; odbc,asterisk,ast_sipfriends
    sippeers =&amp;gt; odbc,asterisk,ast_sipfriends
    extensions =&amp;gt; odbc,asterisk,extensions_table
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;/etc/asterisk/extensions.conf&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;  &lt;span class=&quot;k&quot;&gt;[avatare]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; Realtime/@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;/etc/asterisk/modules.conf&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;  &lt;span class=&quot;k&quot;&gt;[modules]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;autoload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; yes&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;noload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; pbx_gtkconsole.so&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; res_musiconhold.so&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;noload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; chan_alsa.so&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;preload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; res_odbc.so&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;preload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; res_config_odbc.so&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;/etc/asterisk/res_odbc.conf&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;  &lt;span class=&quot;k&quot;&gt;[asterisk]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; yes&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dsn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; asterisk&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; asterisk&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; *********&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pre_connect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Frontend&lt;/h2&gt;

&lt;p&gt;In asterisk-opensim.cfg, set&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;  &lt;span class=&quot;k&quot;&gt;[xmlrpc]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;baseurl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://&amp;lt;frontendhost&amp;gt;:&amp;lt;frontendport&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;[mysql]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;server&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;mysqlhost&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;asterisk&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;asterisk&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;************&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;debug&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;[mysql-templates]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tables&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;create-table.sql&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;create-user.sql&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;region&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;create-region.sql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;OpenSim&lt;/h2&gt;

&lt;p&gt;In OpenSim.ini, add the following section:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ini&quot;&gt;  &lt;span class=&quot;k&quot;&gt;[AsteriskVoice]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;sip_domain&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;asterisk address&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;conf_domain&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;asterisk address&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;asterisk_frontend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://&amp;lt;frontendhost&amp;gt;:&amp;lt;frontendport&amp;gt;/&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;asterisk_password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;**********&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;asterisk_timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3000&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;asterisk_salt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;paluempalum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;SLVoice&lt;/h2&gt;

&lt;p&gt;Create an HTML page that has a single line stating the SIP URI to be used for
private chats (same as &lt;code&gt;asterisk address&lt;/code&gt;) Set this page's address in
slvoice.ini and connect to the region. Voice chat should be working now.&lt;/p&gt;

&lt;h1&gt;What's next&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;There is an ongoing effort to refactor the frontend code. The resulting architecture will be much cleaner with fewer connections.&lt;/li&gt;
&lt;li&gt;The new VoiceServer in progress already includes support for SIP proxies like OpenSER, the SLVoice replacement will be updated shortly to add proxy support as well.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    

  </channel>
</rss>


