Calling Clojure From JRuby

Geplaatst door Michiel de Mare vr, 12 dec 2008 11:23:00 GMT

Clojure is a new functional programming language based on Lisp, running on the JVM. Even though Clojure is only a year old, there’s already a book being written about it.

Since this is a Ruby site, and Rails is still the best framework for web-apps regardless of language, I’ll demonstrate how to call Clojure functions from a JRuby Rails-app.

Lees verder...

Geplaatst in , , ,  | Tags ,  | 4 reacties

Our Daily Method #19: Time#method_missing

Geplaatst door Michiel de Mare wo, 05 maa 2008 13:43:00 GMT

Our stock of cool tricks is depleted, but inspiration still strikes once in a while.

Are you using strftime a lot? Do you like writing strfime? Have you ever spelled it as strtime? strf_time? Thought it was frmtstr?

And if you spell it right, you still have to type those stupid %-signs. All in all, room for improvement.


class Time
  def method_missing(name,*args)
    if name.to_s =~ /f_/
      c = args[0] || ' '
      x = name.to_s[2..-1].split(//).
          map {|f| f =~ /[a-z]/i ? "%"+f : c}.
          join
      strftime(x)
    else
      super
    end
  end
end

So, how does it work?

It handles every method starting with f_. What follows are the characters used within strftime: Y for 4-digit year, d for day of month, etc. Underscores are converted to spaces, or to the first argument, if you provide one.

Examples:


# standard lib
Time.now.strftime("%Y%j")       #=> "2008065" 
Time.now.strftime("s")          #=> "1204725800" 
Time.now.strftime("%d %m %Y")   #=> "05 03 2008" 
Time.now.strftime("%d-%m-%Y")   #=> "05-03-2008" 
Time.now.strftime("%d %b %Y")   #=> "05 Mar 2008" 

# new and improved
Time.now.f_Yj           #=> "2008065" 
Time.now.f_s            #=> "1204725800" 
Time.now.f_d_m_Y        #=> "05 03 2008" 
Time.now.f_d_m_Y('-')   #=> "05-03-2008" 
Time.now.f_d_b_Y        #=> "05 Mar 2008" 

Cool? Stupid? Why don’t you play with it ?

Geplaatst in ,  | 1 reactie

More Prevention of NoMethodErrors on nil

Geplaatst door Michiel de Mare wo, 05 maa 2008 06:24:00 GMT

What a sudden interest in avoiding NoMethodErrors on nil lately! I’ve just thought of another method. (Remember, you can solve any problem by adding a layer of indirection.)

Say you have Remco’s canonical example: person.name.upcase

Both person and person.name may be nil. So we usually write: person && person.name && person.name.upcase.

Now for the level of indirection. Remember rrss? I’ve introduced it last month. It stands for “returns result, same self”. Its definition is beyond trivial:

class Object
  def rrss
    yield self
  end
end
With rrss we can rewrite the original as: person.rrss {|p| p.name}.rrss {|n| n.upcase} Or with to_proc notation: person.rrss(&:name).rrss(&:upcase). We still need to check for nil though:

person.rrss {|p| p && p.name}.
       rrss {|n| n && n.upcase}

Doesn’t this last bit look like it’s in need of a bit of refactoring? Its lack of DRY-ness jumps right out of the page.

Lees verder...

Geplaatst in ,  | 7 reacties

Our Daily Method #18: NilClass#method_missing

Geplaatst door Remco van 't Veer vr, 29 feb 2008 07:40:00 GMT

Warning: only apply the following under parental guidance!

We know the whiny nil, as applied in Rails, but what about an obedient nil:


class NilClass
  def method_missing(*args)
    nil
  end
end

No more monkeying like:


person && person.name && person.name.upcase

Not DRY at all! Let’s use the obedient nil instead:


person.name.upcase

This concludes our last daily method. Ode to Michiel for providing a vast amount of nice tricks!

Geplaatst in , ,  | 5 reacties

Our Daily Method #17: Enumerable#make_index

Geplaatst door Michiel de Mare wo, 27 feb 2008 08:03:00 GMT

Do you know what I like so much about relational databases? And what I really miss in object-models? That databases make it so effortless to index data.

Imagine, you’ve got a huge pile of data, unordered, continually changing, but because your database keeps a few indexes, you can access any item you wish within a few milliseconds.

Wouldn’t it be fun if you could do that in Ruby? Especially the effortless part? It happens regularly that I’ve got an array with hundreds of items in which I have to search. That quicky gets slow, so I create a few hashes that I use as indexes. But what a difference with a real database!

Let make a first step in the right direction, and implement the make_index method.


module Enumerable
  def make_index(*names)
    Struct.new(*names).new(*names.map{|n| group_by(&n)})
  end
end

index = User.find(:all).make_index(:login, :id, :nickname)

index.login['mdemare'] => [<#User ...>]
index.nickname['Michiel'] => [<#User ...>]

I admit, not a huge improvement yet. But we’re getting there. For another time, indexes on more than one attribute, unique indexes and indexing attributes with a natural order. (index.created_at > Time.now.at_midnight)

Geplaatst in , ,  | geen reacties

Our Daily Method #16: Array#bsearch

Geplaatst door Michiel de Mare di, 26 feb 2008 08:00:00 GMT

Searching in arrays is pretty slow. Better use a hash.

But if the array is already sorted, you can use a binary search, which works by dividing the array in two and searching in the left orthe right part, until there’s only one element left.


class Array
  def bsearch(k)
    x,y = -1,size
    while y != x + 1 do
      m = (x + y) / 2
      if self[m] <= k
        x = m
      else
        y = m
      end
    end
    x >= 0 && self[x] == k && x
  end
end

Geplaatst in , ,  | geen reacties

A Hash Is A Function (Hash#to_proc)

Geplaatst door Michiel de Mare di, 26 feb 2008 00:42:00 GMT

Staring at the following code, I got an idea (inspired by Arc):

specialism_codes.map {|code| SPECIALISMS[code] }

Why do I have to create a block to map from a list of codes to a list of descriptions, when those codes and descriptions are all contained in a constant? Isn’t that what a Hash is, a mapping from a domain to a range? Isn’t that exactly the definition of a function in mathematics? Why then that block?

Anyway, I solved that pretty quickly:

class Hash
  def to_proc
    lambda {|x| self[x] }
  end
end

specialism_codes.map &SPECIALISMS

Geplaatst in ,  | geen reacties

Our Daily Method #15: Kernel#levenshtein

Geplaatst door Michiel de Mare ma, 25 feb 2008 08:00:00 GMT

Not in any way invented by us, but still extremely useful and not a part of the standard library: the Levenshtein Distance

What does it calculate? The number of characters to add, delete or switch to turn the first string into the second. Ideal for detecting typos.


# example: 
levenshtein('levenstine', 'levenshtein') # => 3
Or how about instead of a LIKE-clause? Not quite as fast (cough) but much more accurate.

# In the old days:
User.find(:all, 
    :conditions => ['name like ?', params[:name] + '%']])

# Now:
User.find(:all).
    sort_by {|u| levenshtein(params[:name], u.name)}.
    first

def levenshtein(s1, s2)
  d = {}
  (0..s1.size).each { |row| d[[row, 0]] = row }
  (0..s2.size).each { |col| d[[0, col]] = col }
  (1..s1.size).each do |i|
    (1..s2.size).each do |j|
      i1,j1 = i-1,j-1
      cost = s1[i1] != s2[j1] ? 1 : 0
      d[[i, j]] = [d[[i1, j1]] + cost,
                   d[[i1, j]] + 1,
                   d[[i, j1]] + 1].min
      if i1*j1 > 0 and s1[i1] == s2[j-2] and s1[i-2] == s2[j1]
        d[[i, j]] = [d[[i,j]] , d[[i-2, j-2]] + cost].min
      end
    end
  end
  d[[s1.size, s2.size]]
end

Geplaatst in , ,  | geen reacties

Breaking out of Rails MVC with Mongrel handlers

Geplaatst door Remco van 't Veer za, 23 feb 2008 11:21:00 GMT

Module View Controller is a nice concept but sometimes you need te be very creative to fit a problem in that mold. In such cases a more lowlevel approach can be much more effective. The case in ran into recently involves streaming audio from a Rails application. I wanted to recode and stream MP3 files over HTTP. There’s not much MVC about that, there’s nothing to view!

A memory refresher; what is Mongrel? Mongrel is a web server (mostly) written in Ruby. Ruby version 1.8 comes with a web server named WEBrick but its performance is very limited and not useable for public production web applications. Mongrel, on the other hand, is more like a hybrid between a greyhound and a poodle, fast and tough. The little beast is multi-threaded and can easily handle hundreds of concurrent requests.

Lees verder...

Geplaatst in ,  | 1 reactie

Our Daily Method #14: Time#warp

Geplaatst door Remco van 't Veer vr, 22 feb 2008 08:00:00 GMT

Time travel can be very convenient but unfortunately it isn’t very easy. Reality won’t allow it but we can bend the Time class!


class Time
  def self.now_with_warping
    @warptime || now_without_warping
  end

  class << self
    alias_method :now_without_warping, :now
    alias_method :now, :now_with_warping
  end

  def warp
    self.class.instance_variable_set('@warptime', self)
    yield
  ensure
    self.class.instance_variable_set('@warptime', nil)
  end
end
Now we can travel back to “Unix Epoch”:

Time.at(0).warp do
  puts "The current time is: #{Time.now}" 
end
Or just before the end of time as we know it:

Time.at(2 ** 31 - 1).warp do
  Time.now + 1
end

What’s the use? It makes testing time dependent code very easy!

Geplaatst in , ,  | geen reacties

Oudere artikelen: 1 2 3