A simple loop
There's more than one way to skin a cat and the same is true for looping in Ruby. This is a silly post with a silly number of ways to
print the integers from 1 to 10.
If you're a BASIC-programmer and are getting your feet wet with Ruby, you might end up with something like this.
1 2 3 4 |
while i<=10 do puts i i+=1 end |
That and the following for-loop is not the usual Ruby way of looping.
1 2 3 |
for i in 1..10 puts i end |
Instead rubyists often iterates over ranges or arrays with each.
(1..10).each {|i| puts i } |
But for simple integer loops like this, we also have upto
1.upto(10) {|i| puts i } |
and times.
10.times {|i| puts i+1} |
Here's where I should've stopped but I can't help myself, I just have to show off with some Symbol#to_proc "magic".
(0..10).inject(&:p) |
The above works because p is an alias of puts and & converts the symbol :p to a proc that is called with the numbers in the range as parameters.
The alias p also gives us, what I think has to be, the shortest possible way.
p *1..10 |
You could argue that it's a bad thing that there are so many ways to do something as simple as this. But I see no big problem here, if any at all, even though these are hardly all possible ways to loop over integers in Ruby.
Blog comment spam taken to the next level? 8
Only days after starting this barely visited blog the comment spammers showed up. I activated Akismet and it solved my problem for a while. Over time the spamming got worse and although almost no spam actually showed up on the blog, my fear of false positives still forced me to remove the spam manually. Not my idea of fun.
I then activated a very simple hurdle. I demanded JavaScript to be able to post comments. Well, not really, what Typo really did was to expect the HTTP header X-Requested-With: XMLHttpRequest. That worked flawlessly for about three years. Just six weeks ago I noticed the first spambots including the needed header to pass through. Almost all posted stupid drug ads that Akismet easily identified as spam. The situation was still under control.
Yesterday something completely new happened. I got a comment on an old post about my admiration of Ira Glass and This American Life. The comment seemed believable enough and it passed the spam filter. Still, the link at the end undeniably identified it as spam. Then there was another, and another, and up until now a total of six spam comments in the new and more advanced format. I'm still not sure if these are scripted but it seems an awful lot of work if they are actually manually typed.
And also these on a post about infinite ranges in C#:
I'm kind of bothered with the ones both referring to content of the post and at the same time mentioning that it's not about programming like most of my posts are.
Are these human or machine made? A clever combination? Also, if you happen to be a spambot and actually answer this then I guess I will have to congratulate you for passing the Turing test.
PS. They spammed from 110.0.0.0 - 110.255.255.255 so if you happen to have problems with the same spammers and aren't worried about blocking the Philippines then you know what to do. DS.
JavaScript hash table keys
In JavaScript you can add properties to objects dynamically. You can access those properties both by object.foo and object['foo']. The later is commonly used to use JavaScript objects as hash tables (associative arrays).
While implementing a simplistic unique random number generator I happened to use keys(obj). Unfortunately keys(obj) is part of ECMAScript 5. See chapter 15.2.3.14 in ECMA-262. The web browsers of today mostly implements ECMAScript 3.
Here's an implementation of keys(obj) for ECMAScript 3 browsers (tested in Google Chrome, IE8 and Firefox 3.5). If the browser already has a keys function then nothing will be done.
1 2 3 4 5 6 7 8 9 |
if (typeof keys == "undefined") { var keys = function(obj) { props=[]; for (k in ht) if (ht.hasOwnProperty(k)) props.push(k); return props; } } |
The simplistic unique random number generator looks like this
1 2 3 4 5 6 |
function uniqueRndNumbers(min, max, quantity) { var ht={}, i=quantity; while ( i>0 || keys(ht).length<quantity) ht[Math.floor(Math.random()*(max-min+1))+min]=i--; return keys(ht); } |
This function has not undergone any serious testing. Also if the quantity is more than a fraction of (max-min) then another algorithm like the Fisher–Yates shuffle might be a better choice.
Ira Glass on Storytelling
When a new episode of This American Life is made available, that is the first thing I listen to. There are a lot of great podcasts out there but if I had to choose only one, I think I would go for This American Life (sorry RadioLab, I love you). Recently I learned that the host and producer of the show, Ira Glass, can be found on YouTube talking about storytelling. He covers how he thinks you should tell a story for a radio/TV show. I recognize how the show executes that narrative but it also doesn't take anything away from the fact it's excellent and that there are a lot of hard work and talent put into it.
C# implicit string conversion
I know how it works and I think I can see why but I'm still not very fond of how eager C# is to perform implicit string conversion.
Contrived example:
1 2 |
string s = -42 + '+' + "+" + -0.1 / -0.1 + "=" + (7 ^ 5) + " is " + true + " and not " + AddressFamily.Unknown; |
s will be set to "1+1=2 is True and not Unknown"
The answer is in white text above, select the text to see it.
A more real problem is something like this
string str = 1 + 2 + "!=" + 1 + 2; |
str will be set to "3!=12".
Edit 2010-02-08
This wouldn't be much of a problem if all objects in .NET always returned a decent string representation of their current state/value with ToString() but that's not the case. Instead "The default implementation returns the fully qualified name of the type of the Object.".
I don't like the inconsistency. It's way too late now but I think it would have been much better if only objects that really produces a human readable output of the data in the object should implement ToString(). If you want the name of the type of the Object there should be another way.