LoginSignup
6
6

More than 5 years have passed since last update.

遅延評価される文字列を作ってみた

Posted at

新しくオープンした日本語版stack overflowを見ていたらこんな質問がありました。
http://ja.stackoverflow.com/questions/1606/rubyで文字列の式展開を後から行うには

読んでいた所、文字列内での変数展開(#{hogehoge})を遅延評価するようにできるかな?と、気になったので、ちょっと試しに作ってみました。
本来の質問とは離れた気がするけど、気にしない。

使用例

str = LazyString.new 'Curent Time: #{Time.now}'
puts str # => Curent Time: 2014-12-16 22:56:02 +0900
sleep 1
puts str # => Curent Time: 2014-12-16 22:56:03 +0900

クラス定義

class LazyString
  def initialize str
    @str = str
  end

  def to_s
    eval %Q("#{@str}")
  end

  def to_str
    to_s
  end

  def inspect
    %Q("#{@str}")
  end

  def +(opponent)
    to_str + opponent.to_str
  end
end

問題点

Stringクラスを継承するとputs時にto_sが呼ばれなくなる

class LazyString < String
  def initialize str
    super
  end

  def to_s
    puts 'LazyString#to_s'
    'dummy'
  end
end

puts LazyString.new('test')
# => test
puts LazyString.new('test').to_s
# => LazyString#to_s
# => dummy

予想外。

Stringクラスを継承していないので、色々な演算子を定義する必要あり

とりあえず+だけ定義してみた。

str = LazyString.new 'Curent Time: #{Time.now}'
str + ' is fixed'
# => "Curent Time: 2014-12-16 23:09:40 +0900 fixed"

評価しない+も欲しくなってくる。

スコープはあくまでLazyString

str = LazyString.new 'Hello, #{name}'
name = 'Sheile'
puts str
# => NameError: undefined local variable or method `name' for "Hello, #{name}":LazyString

まとめ

副作用が大きいので、実際に何かに使うことは無さそうですがStringを継承した場合の予期せぬ挙動とかも見れたので、なかなか面白い挑戦でした。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6