リテラルの %(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
*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 をアップデート
Redmine を svn up してアップデートしてみたが、 504 エラーが出た。
なにかと思ったら、先日Passengerのバージョンが上がったのを放置していたせいらしい。
Passenger をアップデートすると、apache module を再インストールする必要がある。
$ sudo passenger-install-apache2-module
$ sudo apache2ctrl restrat
これで so が生成されてOK・・・のはずだが、まだアクセスできない。
Passenger と関係ない場所は問題ないので、rails 関係のどれかが原因だと思うんだがなあ。
参考リンク
Redmine.JP | アップグレード
Redmine.JP | Apache上でRuby on Railsアプリケーションを動かす/Passenger(mod_rails for Apache)の利用
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
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 に出てきた除算関数
#!/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))