Sunday, July 20, 2014

Ruby Metaprogramming: class_eval

Lately I've been looking into ways of DRY-ing up ruby classes. One of the first, and perhaps most scarily powerful, is the class_eval method.

What does it do?

class_eval takes in a block or a string and executes it at the class-level. It's that simple!

Is it useful?

Yeah, it's scary useful. Here's an example where I define a bunch of similar methods on a class:

class Person
  ['age', 'name', 'favorite_color'].each do |attribute|
    ['with', 'and'].each do |prefix|
      class_eval %Q(
        def #{prefix}_#{attribute}(value)
          @#{attribute} = value
          self
        end
      )
    end
  end

  def to_s
    "Name: #@name, Age: #@age, Favorite Color: #@favorite_color"
  end
end

me = Person.new.
  with_name('Michael').
  and_age(22).
  and_favorite_color('Blue')

puts me.to_s # => Name: Michael, Age: 22, Favorite Color: Blue

This short little example used class_eval to define 6 methods on the person class: with_age, and_age, with_name, and_name, with_favorite_color and and_favorite_color! Pretty cool, huh?

Thursday, July 3, 2014

Go(lang): Use a Function to Modify a struct via Reflection

I just started learning Go recently and I must say, it's been a lot of fun. The first real difficulty I've had with the language has been trying to use reflection to set a field on a struct, inside of a function. I found some decent examples, but none that were quite fitting, so I thought I'd share my solution here.

So, just for the fun of it, let's say we have a struct that we know will "always" have a field Brewery:

type Beer struct {
    Brewery string
}

Note that Brewery is public (sorry for the term, my non-Go experience is showing).

Now let's say we want to create a function that always sets the Brewery to "Dogfish Head", but we want it to operate on the general interface and use reflection (for whatever reason):
import "reflect"

func breweryToDFH(thing interface{}) {
    reflect.ValueOf(thing).
        Elem().
        FieldByName("Brewery").
        SetString("Dogfish Head")
}

Finally, to call it, a pointer must be used, e.g.

beer := Beer{}
breweryToDFH(&beer)

And that's all! As one coming from the dynamicity of Ruby, this seems kind of roundabout. So if you know a way to simplify, please feel free to comment. Also, there is a good deal of error handling that should be done here, so for that, I will defer to a stackoverflow post.

Happy "Go-ing"!