Archive for Ruby


Notes from clerb meeting on Thursday, July 17th

DimpleDough provided a great location for this month’s Cleveland Ruby Users Group and they even shelled out for dinner. We heard a really good talk about about ruby and F#.

The ruby material covered some neat corners of the language like the method_missing method, which operates like python’s getattr. Here’s a toy example of how it can be used:

irb(main):005:0> class C
irb(main):006:1> def foo
irb(main):007:2> 1
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> c = C.new
=> #<C:0xb7ce4da4>
irb(main):011:0> c.foo
=> 1
irb(main):012:0> class C
irb(main):013:1> def method_missing(m, *args)
irb(main):014:2> puts "you tried to call a method #{m}"
irb(main):015:2> end
irb(main):016:1> end
=> nil
irb(main):017:0> c.baz
you tried to call a method baz
=> nil
irb(main):018:0>

Incidentally, note how I added a new method to class C after I originally defined it. That’s a cute trick in ruby. I can imagine a lot of nasty misuses of that, but I think the “we’re all consenting adults” rule should apply. And when a class has dozens of methods, it might be helpful to divide them across different files.

We talked about currying as well, in the context of F#. I tend to use currying in this scenario:

  • I recognize that two separate functions could be refactored to be a single function with a whole bunch more parameters;
  • I remake the original functions as curried versions of the new super function.

In other words, if I already have two methods, like paint_it_red(it) and paint_it_green(it), it’s trivial to realize I could write a paint_it_some_color(it, color) and then replace the original paint_it_red with a curried version.

I found this really useful when it isn’t just a single parameter I’m fixing to a constant value, but maybe a whole bunch.

Apparently, Ruby will add currying support in 1.9. I tried to see if I could “fake it” in the irb interpreter, but I just made a mess:

irb(main):036:0> def f(a, b)
irb(main):037:1> a + b
irb(main):038:1> end
=> nil

Nothing interesting so far. f adds its two parameters. So now I’m going to try to make a new function that returns a version of function f with the first parameter a set to fixed value:

irb(main):046:0> def curried_f(a)
irb(main):047:1> def g(b)
irb(main):048:2> a+b
irb(main):049:2> end
irb(main):050:1> return g
irb(main):051:1> end
irb(main):053:0> curried_f(1)
ArgumentError: wrong number of arguments (0 for 1)
from (irb):50:in `g’
from (irb):50:in `curried_f’
from (irb):53
from :0

The problem (I think) stems from how in Ruby, if I just type the name of the function, the function gets called. So in line 50, when I’m trying to return a reference to the new function I just created, Ruby evaluates the result of calling g without giving it any parameters.

I bet I’m doing something very un-ruby-tastic with this approach. I’m probably supposed to leverage those anonymous blocks instead.

F# looks really interesting. It supports all those weird prolog/erlang/haskell-style features like single assignment, pattern matching, and optimal tail-call recursion, with the benefit of having access to the .NET libraries as well.

One of the best professors I studied under made a remark that in COBOL, you think for five minutes and then type for two hours, but in prolog, you think for two hours, and then type for five minutes. I agree. I have learned a lot of languages, but I haven’t gotten any smarter. I’m just learning how to map my thoughts into notation much more quickly.

I would love to have the time and reason to do a project with F#. I think I’ll start by installing mono and messing around.

Notes from Cleveland Ruby meeting on Thursday, Jan 25th

This post contains some python-related information, I promise.

Fun time. Corey Haines explained behavior-driven development and showed some examples using RSpec at last night’s Cleveland Ruby meetup.

As an aside, Corey said “powershell is what the unix command line will be when it grows up” and a thousand angels fell over dead when they heard this blasphemy.

The story-based tests in RSpec seem downright magic. You can write in an english-y syntax:

Given a = 1,
When
b.foo(a)
Then
b should return "Hurray"

Or something like that.

I like that RSpec supports a result called “Pending”. This guy writes a good explanation of how it works, and I agree with this remark:

It’s easy enough to rename a test method so it doesn’t execute, but before RSpec I’ve never worked with one where you can mark it as pending and it then reminds you that you still have work to come back too.

I figure that it would be straightforward to add this into nose. Maybe raise a special exception called PendingTest that gets caught differently.

I learned a neat way of using a mock object without having to pass it in as a parameter based on some code I saw last night.

Corey had a couponcontroller that operated on coupon objects. He made a mock coupon object to use with his tests for his couponcontroller. Then, in his test code, he monkeypatched the coupon module so that when somebody said “give me a coupon” he got a mock coupon instead.

I spent a few minutes trying something vaguely like that in python. I’m not sure I like it, but it gets the point across.

I have a file coupon.py:

# This is coupon.py.
 
class Coupon(object):
    "I'm the real coupon"
 
    def foo(self):
        print "This is the real coupon"
        return "foo"

And I have a file couponcontroller.py:

# This is couponcontroller.py.
 
from coupon import Coupon
 
def couponcontroller():
    c = Coupon()
    return c.foo()

In my test_couponcontroller.py, I want the couponcontroller to use my mock coupon, not the real one.

# This is test_couponcontroller.py.
 
import couponcontroller
 
class mockCoupon(object):
    "I'm not the real coupon."
    def foo(self):
        print "Congratulations. You're using a mock."
        return "foo"
 
def setup():
    # Mess with the module.
    couponcontroller.Coupon = mockCoupon
 
def test_couponcontroller():
    "couponcontroller should return a string 'foo'"
    assert couponcontroller.couponcontroller() == "foo"

It seems to work:

$ nosetests -s test_couponcontroller.py
couponcontroller should return a string 'foo' ... Congratulations. You're using a mock.
ok
 
----------------------------------------------------------------------
Ran 1 test in 0.003s
 
OK

In summary, there’s clearly a lot of smart people in the ruby community, even if they insist on using syntax like

@adder ||= Adder.new

Comments (3)