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.

September 26, 2008

What’s in a name?

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

Randall Munroe of XKCD fame has said on multiple occasions that he chose the name XKCD mostly at random, considering only that it’s an unpronounceable combination of letters that hadn’t been previously used in any significant way. I’m not so sure. I’m apparently not the first one to realize this, but if you take A=1, B=2, and so on, adding up the values of XKCD gives 42.

I figured this out while I was playing around with Reg Braithwaite’s wonderful String#to_proc library. Here’s the code I used.

[?x,?k,?c,?d].map(&'_-96').fold(&'+')

In short, this generates an array of the ascii values for the letters x, k, c, and d, converts them from a=97 to a=1, then sums them. Unlike Symbol#to_proc, which is standard in recent versions of ruby, String#to_proc substitutes underscores with the current value.

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.