Isotopical Blog

A weblog by Chromium 53
October 5, 2008

Recursive Lambdas in Ruby

Author: burke - Categories: Uncategorized - Tags: , ,

Ruby has better support for lambdas than most “mainstream” languages, but it’s missing one important feature — a way to reference the lambda itself. Not being able to reference itself makes recursion using a lambda somewhat difficult. For example, say I wanted to define factorial using a recursive lambda. A lot of rubyists would suggest using self.

lambda{|n| n.zero? ? 1 : n * self.call(n-1)}

Unfortunately, self is evaluated in the context of the calling block, so it doesn’t return the lambda as you might hope; it returns main or whatever context you’re calling the lambda from, usually resulting in an error, or at least not what you were hoping for. The only way, as far as I can tell, to reference the lambda is by assigning it to a variable:

fac = lambda{|n| n.zero? ? 1 : n * fac.call(n-1)}

Again, this is not ideal. Not only does it pollute the calling context, it relies on the variable name it’s assigned to. It works, but it’s ugly. The only solution I’ve been able to come up with is to wrap it in another lambda:

# Ruby 1.8.7
lambda{|n| (fac=lambda{|n| n.zero? ? 1 : n * fac.call(n-1)}).call(n) }
# Ruby 1.9
->(n){(fac=->(n){n.zero? ? 1 : n * fac.(n-1)}).(n)}

This is better from a purity standpoint, but it’s still ugly code. I’ve heard talk of some way to reference the current block in upcoming versions of Ruby, but I haven’t been able to find any concrete information on the subject. If anyone has news, let me know.

Update 2008-10-06 20:42

Apparently what I was looking for here is the Y combinator. Nex3 does a far better job of explaining it than I could hope to, but here’s the code to make it happen:

def Y
  lambda { |f| f.call(f) }.call(
    lambda do |g|
      yield(lambda { |*n| g.call(g).call(*n) })
    end)
end

Y { |this| lambda { |n| n == 0 ? 1 : n * this.call(n - 1) } }.call(12) #=> 479001600

Thanks to sjs for pointing this out.

October 4, 2008

Ruby 1.9 and Lambda Calculus

Author: burke - Categories: Uncategorized - Tags: , ,

With Ruby 1.9 sneaking up on us, it’s probably time to start getting excited about new features, so here goes. Ruby 1.9 has a completely new syntax for lambdas that maps perfectly onto actual lambda calculus.

Crash course in lambda calculus: Generally speaking, expressions are specified as “(λ parameters. result) argument”, everything is left-associative, and functions are called like “f v”, where f is a function and v is a value (or a function…) Thus, the expression:

(λ f. f 3) (λ x. x + 2)

evaluates to 5, since the expression on the left consumes a function and calls it with the value 3, while the expression on the right returns its argument plus two. Note that referring to values and functions as two distinct concepts here is technically incorrect, but helps to explain what happens. To do the same thing in Ruby 1.8.7, one would write:

# Ruby 1.8.7
lambda{|f| f[3]}[lambda{|x| x+2}]

In Ruby 1.9, some new syntactic sugar has been added:

# Ruby 1.9
->(f){f.(3)}.(->(x){x+2})

The “->” is supposed to be read as a lambda (λ), since relying on unicode characters in code is generally bad news. Not only is this significantly less syntactic overhead than the equivalent code in 1.8.7, it feels less like an ugly hack and more like an acutally-supported feature.

# λ x. x
->(x){x}

I hope this new lambda syntax encourages more people to write ruby with a more functional style. At the moment, it’s certainly an underused ‘facet’ of ruby.

October 3, 2008

The Me Meme

Author: admin - Categories: Uncategorized

Take a picture of yourself right now.
Don’t change your clothes, don’t fix your hair…just take a picture. (should be super-easy with Photobooth)
Post that picture with NO editing.
Post these instructions with your picture.

blog.obiefernandez.com/content/2008/10/the-me-meme.html

September 30, 2008

[resolved] Datetime_select Virtual Attribute issue (Rails 2.1)

Author: stefan - Categories: Uncategorized

Apparently trying to assign a datetime_select as a virtual attribute in Rails doesn’t work correctly. Instead of rendering the following code, which I would assume is the correct behaviour:

team[member_attributes][][arrival(5i)]

It renders this:

Team[member_attributes][arrival(5i)]

For example, when creating a new team model, one can also create N new member models from the same form, where a member is associated with a team.


# teams/new.html.haml

-form_for([@team]) do |f|
  = link_to_function 'Add a Member' { |page| page.insert_html :bottom, :members, :partial => 'member', :object => Member.new }
  = f.submit

# teams/_member.html.haml

- fields_for 'team[member_attributes][]', member do |f|
= f.datetime_select  :arrival

# teams_controller.rb
def create
  @team = Team.new(params[:team])
  @members = @team.members
end

# models/team.rb

def member_attributes=(attributes)
  attributes.each do |a|
    members.build(a)
  end
end

When this form is submitted, the following error is thrown.

## Error
Status: 500 Internal Server Error
Conflicting types for parameter containers. Expected an instance of Hash but found an instance of Array. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value. (The parameters received were [{"attribute"=>""}].)

Walking through the code with the debugger, it turns out this snippet of code in the rails source may be the culprit:

#rails/actionpack/lib/action_view/helpers/form_helper.rb:508
if @object_name.sub!(/\[\]$/,'')
  if object ||= @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
    @auto_index = object.to_param
  else
    raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param:
    #{object.inspect}"
 end
end

It seems to explicitly remove empty [] tags on datetime_select. This seems to be more of a feature than a bug, so I tried to adapt my code to work with it, which resulted in:


# teams/new.html.haml

-form_for([@team]) do |f|

...

%p= link_to_function "Add a Member"; do |page|
  page.insert_html :bottom, :members, :partial =>'member', :object => Member.new
  = f.submit

# teams/_member.html.haml
- fields_for "team[member_attributes][bar]", member do |f|
  = f.datetime_select  :arrival
  # teams_controller.rb

def create
  @team = Team.new(params[:team])
  @members = @team.members
end

# models/team.rb

def member_attributes=(attributes)
  [attributes["fu"]].each do |a|
    members.build(a)
  end
end

As you can see, two small changes fixed the problem:

  1. fields_for “team[member_attributes][fu]” instead of an empty []
  2. in models/team.rb iterate over all the attributes inside attributes["fu"] instead of just iterating over attributes
August 29, 2008

The Konami Code

Author: burke - Categories: Uncategorized - Tags: ,

The jQuery Team recently updated their web site, causing quite a stir. The most interesting feature of the new site is that it responds to the decades-old Konami code. If you go to http://jquery.com and press “↑ ↑ ↓ ↓ ← → ← → B A”, you’re sent to John Resig’s javascript-based guitar hero clone. It’s actually fairly playable.

If you want to implement the Konami code on your website, just include this javascript (written by the jQuery team, not myself).

if ( window.addEventListener ) {
  var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
  window.addEventListener("keydown", function(e){
    kkeys.push( e.keyCode );
    if ( kkeys.toString().indexOf( konami ) >= 0 )
      window.location = "http://example.com/";
  }, true);
}

Essentially, every time a key is pressed, javascript appends it to an array, then checks the entire array for instances of the konami code. I’d have serious reservations about having this hanging around on any page with text entry, but it’s a fun easter egg for a front page.

Update 2008-09-01 02:24:

I’ve modified the code to use an array of 10 elements — the last 10 keys pressed — instead of every key pressed while on the current page. I don’t expect this code would ever have a noticeable impact on performance, whereas the other code could cause problems after the user had typed large amounts of text.

if ( window.addEventListener ) {
  var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
  window.addEventListener("keydown", function(e){
    kkeys.shift();
    kkeys[9] = e.keyCode;
    if ( kkeys.toString() == konami )
      window.location = "http://example.com";
  }, true);
}

Using a finite state machine would clearly be a significant performance boost in relative terms, as we’re still comparing strings in this version, but it would take a fair bit more code and nobody would ever notice the performance boost.

Update 2008-09-05 20:50

I reread this post today and realized a finite state machine would actually be painfully simple to implement here, so I’ve done just that. This is the most efficient way I can possibly imagine to listen for the code.

if ( window.addEventListener ) {
  var state = 0, konami = [38,38,40,40,37,39,37,39,66,65];
  window.addEventListener("keydown", function(e) {
    if ( e.keyCode == konami[state] ) state++;
    else state = 0;
    if ( state == 10 )
      window.location = "http://example.com";
  }, true);
}
August 12, 2008

Headache-free VirtualHost management with YAML

Author: burke - Categories: Uncategorized - Tags: , , , , ,

Apache VirtualHosts suck.

There, I said it. Apache’s configuration syntax is completely arcane and it’s impossible to avoid massive repetition of code, yet it’s far and away the best option available. It occurred to me the other day, while updating 20-some vhosts manually, that there has to be a better way.

Most of our vhosts fall into one of three categories, variations within which are almost completely limited to replacing the domain name in umpteen lines, so I wrote a templating system. It turned out to be very straightforward. There are two YAML files: one for templates, and one for data. There’s a script to trans-inter-combinify them into Apache VirtualHosts, and a modified apache initscript to run my generator every time Apache is started.

You can grab a copy of the code from the git repo. It’ll almost assuredly take a small amount of modification for your system.

git clone git://github.com/53cr/generate-vhosts.git

The data file, vhosts.yml, has an extremely concise syntax:

---
53cr.com:
  location: 53cr
redmine.53cr.com:
  type: rails
  railsenv: production
chromium53.com:
  type: alias
  redirect: 53cr.com

Templates are selected with the ‘type’ attibute, and specified in types.yml. Here’s a sample.

---
standard: |
  <VirtualHost *>
    ServerName    #{@domain}
    ServerAlias   www.#{@domain}
    DocumentRoot  /srv/http#{@location}#{@domain}/htdocs
    RewriteEngine on
    RewriteCond   %{HTTP_HOST} ^www\\.#{@domain.gsub('.','\.')}
    RewriteRule   (.*) http://#{@domain}$1 [R=301,L]
    #{@custom}
  </VirtualHost>

alias: |
  <VirtualHost *>
    ServerName        #{@domain}
    ServerAlias       www.#{@domain}
    RedirectPermanent / http://#{@redirect}/
  </VirtualHost>

There’s really not even a lot of magic to do here. It’s just a simple matter of reading in the vhosts.yml file and applying each item to the template it specifies. I just create a Vhost object, as seen below, from each item in vhosts.yml and concatenate them all into a file that apache reads in.

class Vhost

  def initialize(args)
    args.each do |k,v|
      instance_variable_set "@#{k}", v
    end
    @type ||= 'standard'

    # We need to wrap @location in slashes, but if it's root,
    # we get // or ///, so we collapse multiple /s to a single /
    @location = "/#{@location}/"
    @location.gsub!(/\/+/,'/')

    @types = YAML.load(open("#{CONFIG_PATH}/types.yml"))
  end

  def to_s
    if @types.has_key? @type
      eval("return \"#{@types[@type]}\"")
    end
  end

end

I also modified my apache initscript to run generate-vhosts each time it reads its configuration. Since Arch Linux initscripts aren’t exactly the pinnacle of portability within the Linux world, I won’t bother posting it here. If you really want a copy, let me know in the comments.