リテラルの %(percent) 記法

よく忘れる上にググりにくいのでメモっておく。
文字列や正規表現リテラルを簡潔に記述できる。

%(hoge #{foo} bar) # => "hoge Foo bar"
%Q(hoge #{foo} bar) # => "hoge Foo bar"
%q(hoge #{foo} bar) # => "hoge \#{foo} bar"
%x(echo hoge #{foo} bar) # => "hoge Foo bar\n"
%r(hoge #{foo} bar) # => /hoge Foo bar/
%w(hoge #{foo} bar) # => ["hoge", "\#{foo}", "bar"]
%W(hoge #{foo} bar) # => ["hoge", "Foo", "bar"]
%s(hoge #{foo} bar) # => :"hoge \#{foo} bar"
%Q(
hoge
-- #{foo}
bar

) # => "\nhoge\n-- Foo\nbar\n\n"
%w(hoge\ #{foo} bar) # => ["hoge \#{foo}", "bar"]

乱暴に分類すると

大文字は器が大きいので、式展開してくれると覚えるとよさそう。
%xと%rも、なんでもやってくれるよ!*1

詳しい説明は

るりまを読みましょう。下記リンクは ruby 1.8.7 用。
参考: リテラル

*1:結局、式展開しないのはq,w,sだけだった・・・

define_method ってなんぞや

railsのプラグインを覗いてたら、eval系メソッドがもっさり出てきてわけのわからないことになったので、色々復習。

まずはdefine_method。

インスタンスメソッド name を定義します。

ブロックを与えた場合、定義したメソッドの実行時にブロックがレシーバクラスのインスタンスの上で Object#instance_eval されます。

instance method Module#define_method

#!/usr/bin/env ruby
module Hoge
  def define (bar)
    define_method("#{bar}=") do |value|
      @val = value.reverse    
    end
    define_method("#{bar}") do 
      @val
    end
  end
end

class TestClass
  extend Hoge
  define :foo
end

test = TestClass.new
test.foo = "hoge"
puts test.foo # >> egoh

メソッド名通り、メソッドを定義する。
attr_accessor とかこういう実装なんだろうか。

ちなみにprivateメソッドなので、インスタンスからの呼び出しはできない

class ErrorTest
  include Hoge
end

err = ErrorTest.new
err.define :bar
err.bar = ''
# ~> -:4:in `define': undefined method `define_method' for #<ErrorTest:0x269d0> (NoMethodError)

なんかごにょごにょすると、インスタンスから渡した値でメソッドが作れそう。
まあ、今回はここまで。

Struct

Rubyにもstruct があるということを教えてもらったので、早速使ってみる。

Struct って?

いわゆる構造体。語弊はあるけれど、メソッドの無いクラスのようなものと理解している。
Rubyの場合、Struct.new でstruct型のサブクラスを作り、それをさらにnewすると構造体が生成される。

Struct.newで通常のclass定義を行い、その後にインスタンス作ってるような感じ。
1行で定義が書けてしまうのはいいなあ。

#!/usr/bin/env ruby
#-*-coding:utf-8-*-
hoge = Struct.new('Hoge', :foo, :bar, :baz)
p hoge # >> Struct::Hoge

baka = hoge.new('ほえほえ','はうはう', 'もげもげ')
p [baka.foo, baka.bar, baka.baz] # >> ["ほえほえ", "はうはう", "もげもげ"]
p baka # >> #<struct Struct::Hoge foo="ほえほえ", bar="はうはう", baz="もげもげ">

baka.each_pair do |k,v|
  p [k, v]
end
# >> [:foo, "ほえほえ"]
# >> [:bar, "はうはう"]
# >> [:baz, "もげもげ"]

使い道としては Hash のように複数の値を保持しておくのに便利。
Hashと違ってキーを間違えるとエラーになるので、エラー検出にもよい。

C#でstructure

Mono 2.4 がリリースされたらしいので、久しぶりにC#
でもやってみた。

using System;
using System.IO;

public struct Hoge {
  public string foo, bar, baz;

  public Hoge(string foo, string bar, string baz) {
    this.foo = foo;
    this.bar = bar;
    this.baz = baz;
  }
}

class TestRunner {
  public static void Main() {
    string s1 = "ほえほえ";
    string s2 = "hauhau";
    string s3 = "mogemoge";
    Hoge baka = new Hoge(s1, s2, s3);
    System.Console.WriteLine("foo = {0}, bar = {1}, baz = {2}", baka.foo, baka.bar, baka.baz);
  }
}
// => foo = ????????????, bar = hauhau, baz = mogemoge

Mac OSX の Terminal.app (UTF-8) で出力したら、日本語が文字化け。
あと、new Hoge() の引数にリテラルを直接入れたら怒られた。さすがにチェックが厳しい。

そんなわけで

数と名前の決まったデータを保持しておくなら、Hashより構造体の方がよさそうです。

Passenger をアップデート

Redminesvn up してアップデートしてみたが、 504 エラーが出た。
なにかと思ったら、先日Passengerのバージョンが上がったのを放置していたせいらしい。

Passenger をアップデートすると、apache module を再インストールする必要がある。

$ sudo passenger-install-apache2-module
$ sudo apache2ctrl restrat

これで so が生成されてOK・・・のはずだが、まだアクセスできない。
Passenger と関係ない場所は問題ないので、rails 関係のどれかが原因だと思うんだがなあ。

2009/03/30 追記

Passenger 利用部分に設定しているドメインのDDNSが更新されていないだけだった。
恥ずかしすぎる。

Project Euler - Problem 2

1分間でなんてとても解けません。

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

#!/usr/bin/env ruby
def fib(n)
  return 0 if n < 1
  return 1 if n == 1
  fib(n-1) + fib(n-2)
end

limit = 4 * 10 ** 6

a = (1..40).inject(0) do |sum, i|
  result = fib(i)
  break sum if result > (limit)
  sum += result if result % 2 > 0
  sum
end
puts a


そもそも自分のフィボナッチ数列の知識が怪しかった。
問題を読み間違えていたため、だいぶ右往左往しながらゴールという感じ。
return とか break とか無しで、もう少し奇麗に書けないものかなあ。

Project Euler - Problem 3

素因数分解 - Wikipedia

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

Ruby には便利なライブラリがありますね。
singleton method Integer.prime_division

#!/usr/bin/env ruby
require 'mathn'
p 13195.prime_division
p 600851475143.prime_division
# >> [[5, 1], [7, 1], [13, 1], [29, 1]]
# >> [[71, 1], [839, 1], [1471, 1], [6857, 1]]

さすがにつまらないので

自分でも書いてみる。一番簡単な試し割り。

#!/usr/bin/env ruby
prime_div = lambda{|num|
  res = []
  (3..Math::sqrt(num)).step(2) do |i|
    if num % i == 0
      res << i if prime_div.call(i).size == 0
    end
  end
  res
}
p prime_div.call 600851475143
# >> [71, 839, 1471, 6857]

他のアルゴリズムでも書いてみたいが、まずは次に進もう。

ついでにカリー化

カリー化 - Wikipedia

複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。

クロージャよりもさっぱりだよ!!

サンプル

書いてみたはいいけどいまいち良さが理解できていない。
Wikipedia に出てきた除算関数

#!/usr/bin/env ruby
def div x
  return lambda{|y| x / y}
end

d1 = div 10
puts d1.call 2
# >> 5

Ruby1.9

ラムダらむだ

#!/opt/local/bin/ruby1.9
def div x
  return ->(y){ x / y }
end

d1 = div 10
puts d1.(2)

さらに悪のりしてみる

λ

#!/opt/local/bin/ruby1.9
div = ->(x){ ->(y){ x / y } }
puts div.(10).(2)

なははは。きもい!
なんか楽しくなってきた。

参考: Ruby 1.9の新しいλ式の文法がキモい件 - ’(rubikitch wanna be (a . lisper))