→ 29 August 2010.
Tags:
ruby,
programming
I had cause to repurpose this immediate feedback formatter to work with the SpecDoc rspec formatter. So here’s a minimal version that just monkey-patches the SpecdocFormatter class to provide immediate feedback. As long as it’s included somewhere before rspec starts running, it should do its thing…
(view link)
…
Recursively Default Dictionaries
→ 01 September 2009.
Tags:
programming,
ruby,
python
Today I was asked if I knew how to make a recursively default dictionary (although not in so many words). What that means is that it’s a dictionary (or hash) which is defaulted to an empty version of itself for every item access. That way, you can throw data into a multi-dimensional dictionary without regard for whether keys already exist, like so:
h["a"]["b"]["c"] = 5
Without having to first initialise h[“a”] and h[“a”][“b”].
A dictionary with a default value of an empty hash sprang to mind, but after trying it out I realised that this only works for one level. Recursion was evidently required.
So, here’s the python solution:
from collections import defaultdict
new_dict = lambda: defaultdict(new_dict)
h = defaultdict(new_dict)
And the ruby, which seems overly noisy:
new_hash = lambda { |hash, key| hash[key] = Hash.new &new_hash }
h = Hash.new(&new_hash)
…
minor metaprogramming
→ 12 June 2009.
Tags:
programming,
ruby
Can anyone tell me why ruby’s instance_variable_set would possibly require the name of a variable to start with an “@”, rather than simply assuming it? It’s a ruddy instance variable, after all…
I can find no decent alternative to python’s setattr in ruby, which surprises me.
…
The joys of functional programming with side-effects
→ 01 June 2009.
Tags:
programming,
python,
ruby
Quick quiz: what will the following pieces of ostensibly identical python and ruby programs print out?

If you answered “1 2 3 4” or something similar, you’re half right. That’s what you’ll get from ruby.
Surprisingly, python will give you “4 4 4 4”. I'm not the first
to discover this, but that doesn’t make it
any less startling.
The “fix” in python is to replace the lambda line with q.append(lambda i=i: puts(i)), because default
function paramaters are evaluated at definition-time, not evaluation-time (another difference from ruby, potentially
even related?). It makes sense once it’s explained what’s going on, but it’s hardly obvious.
I don’t know enough about how closures are done to say that python is wrong, but it’s certainly less desirable and more surprising…
(for those keeping score, this makes ruby: 1, python: still heaps ;P)
P.S. I couldn’t resist mentioning the title of a proposed solution to this problem: For-loop variable scope: simultaneous possession and ingestion of cake
update: As matt just pointed out, the ruby port is different in that it uses i as an argument to a block. A more faithful translation would be:
for i in (0..9)
q << (lambda {puts i})
end
Which has exactly the same outcome as python.
So there you go. It turns out closures are confusing. Who knew? ;P
…
Entirely too much investigation into ruby's match operator
→ 02 May 2009.
Tags:
ruby,
programming
(how could a title like that not excite you! ;P)
So yesterday I had this weird regex issue in ruby. I wanted to get a regular expression containing a given string, but didn’t want to have to manually escape all the special characters. Regexp.escape to the rescue! It escapes all regex metacharacters in any given string, and returns it as a regex. In fact, the docs assure me:
For any string, Regexp.escape(str)=~str will be true.
But not so much in practice?
>> str = "123"
=> "123"
>> Regexp.escape(str)=~str
TypeError: type mismatch: String given
So, problem one: Regexp.escape is broken. It returns not a Regexp, but a string. Oddly enough it also seems to escape spaces and other innocuous characters, but at least you get the right result if you pump it through Regexp.compile(). However, that wasn’t my only discovery.
I mentioned this to Matt, and he couldn’t make much sense of it either. He noticed that the type error is specific to strings – if you use a number it just returns false:
>> 123 =~ 'foo'
=> false
Seems a bit odd, really. Fixnum doesn’t implement =~, nor does Integer.
So I went doc spelunking. I found implementations for =~ in the following three important classes:
Regexp: regexp =~ str: do a regex match, as you might expect
String: str =~ obj: Call obj =~ str (i.e swap the order of your operands). Not mentioned in the docs but clearly apparent in the source (and experimentation): raise a TypeError if both arguments are strings. Without this, matching one string to another would very quickly run out of stack space.
Object: obj =~ other_obj: return false
So the Regexp implementation is fine. The String implementation is a little odd. I guess it’s there to allow people to write matching statements either way, but it seems like a dangerous (and confusing) habit to condone.
But the Object implementation? Why??? What possible reason could one have for doing a match operation against two objects, neither of which implement any matching behaviour? This has the painful side effect of giving every single object I inspect a “=~” method which does nothing. No wonder Object.new() has over 120 methods on it *.
For comparison, python’s object only has 12 methods / attributes. And they’re all special names, so there’s no pollution of regular names going on.
So there you go, two spoonfuls of broken in the one discovery!
(this is ruby 1.8.6, if that matters)
* I exaggerate, over 120 methods on object are just what you get in a rails app. Vanilla ruby only has 41 by my count. but it’s still completely unnecessary, and adds noise to inflate that number
…
→ 28 April 2009.
Tags:
ruby,
programming
Pretty cool, I worry that such things can’t easily be done so cleanly in python…
(view link)
…
ruby - longing for some discipline
→ 21 March 2009.
Tags:
python,
ruby,
programming
More and more, I am wishing that there was some sort of strict mode I could enable in ruby to say “you know what? I'm careful with my code. Please don’t assume things behind my back”. And to be honest, this mode would pretty much be synonymous with “just do what python would do”
By default, python is strict. If you index a dict (hash) with a nonexistant key, you get a keyError. If you don’t want to have to deal with that, you can use the get method and provide a default for if the key doesn’t exist. In ruby, if you want to be strict about anything, you generally have to write your own checks to guard against the core library’s forgivingness. Forgivingness sounds nice at first, but goes completely against the idea of failing fast, and frequently delays the manifestation of bugs, making them that much harder to actually track down.
Two examples that I came across within minutes of each other the other day:
Struct.new(:a,:b,:c).new('a','b')
that should NOT go without an exception
"a|b||c".split("|")
=> ["a", "b", "", "c"]
good…. so now:
"a|b||".split("|")
=> ["a", "b"]
argh! what have you done to my third field?
…
Ruby class methods
→ 21 January 2009.
Tags:
programming,
ruby
Not a very exciting realisation, but an annoying one:
$ irb
>> class A
>> def self.meth; puts "class method!"; end
>> end
>> A.meth()
class method!
>> A.new().meth()
NoMethodError: undefined method `meth' for #<A:0x5ad160>
from (irb):11
ick…
(sadly enough, most of my posts tagged “ruby” would be equally well tagged as “things that suck in ruby”)
…
Ruby is friggin weird. And a little messed up.
→ 21 June 2008.
Tags:
programming,
ruby
(if you don’t read my blog for the geeky thrill of it, you may want to give this post a miss ;))
Follow my little IRB session, if you will:
>> nil or "val"
=> "val"
>> puts (nil or "val").inspect
=> "val"
>> x = nil || "val"
=> "val"
>> x
=> "val"
>> y = nil or "val"
=> "val"
(wait for it…)
>> y
=> nil
Seriously, ruby. What the crap?
Okay, so I just figured out what’s going on here. “or” works both as a logic operator and a conditional statement. Just like you can do:
x = something_dangerous() rescue "x failed!"
and
puts "x is greater than 10" if x > 10
It would seem you can also do
x = some_value or puts "i guess the assignment didn't evaluate to true"
Meaning that in my example above:
y = nil or "val"
Ruby evaluates it as:
(y = nil) or ("val")
(i.e. in the second set of brackets, y is not actually assigned to anything)
When I found out that the symbol-based ones bind tighter than the keywords, I winced a little and noted to myself never to rely on that, because it’s neither readable or obvious.
Now that I've stumbled upon this latest gem of knowledge, It just makes me cringe…
…
@ruby: You're Doing it Wrong.
→ 13 June 2008.
Tags:
programming,
ruby
Pay attention to the output types, kids:
>> { "key" => "val" }.reject { false }
=> {"key" => "val"}
looking good so far...
>> { "key" => "val" }.select { true }
=> [["key", "val"]]
eww... what?