Last active
August 29, 2015 14:23
-
-
Save kkismd/ce28dc1b16a774bf287c to your computer and use it in GitHub Desktop.
ScalaのOptionをRubyで説明してみる
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/env ruby | |
class Option | |
end | |
class Some < Option | |
include Enumerable | |
def initialize(a) | |
@a = a | |
end | |
def each | |
yield @a | |
end | |
def get_or_else(b) | |
@a | |
end | |
def or_else(b) | |
self | |
end | |
def map(&block) | |
self.class.new( yield @a ) | |
end | |
def flat_map(&block) | |
yield @a | |
end | |
def to_a | |
[@a] | |
end | |
end | |
class None < Option | |
include Enumerable | |
def each | |
# do nothing | |
end | |
def get_or_else(b) | |
b | |
end | |
def or_else(b) | |
b | |
end | |
def map(&block) | |
self | |
end | |
def flat_map(&block) | |
self | |
end | |
def to_a | |
[] | |
end | |
end | |
class Object | |
def some | |
Some.new(self) | |
end | |
end | |
def none | |
None.new | |
end | |
if __FILE__ == $0 | |
# or_else, get_or_elseの例 | |
# 名前欄にはfirst_nameとlast_nameどちらか設定されているほうを表示する | |
# どちらも設定されていなければ"名無しさん"と表示する | |
User = Struct.new(:first_name, :last_name) do | |
def display_name | |
self.first_name.or_else(self.last_name).get_or_else("名無しさん") | |
# Rubyだとこっちのほうが簡単 | |
# self.first_name || self.last_name || "名無しさん" | |
end | |
end | |
taro = User.new("Taro".some, "Yamada".some) | |
jiro = User.new(none, "Yamada".some) | |
saburo = User.new("Saburo".some, none) | |
shiro = User.new(none, none) | |
print "TARO: "; p taro.display_name | |
print "JIRO: "; p jiro.display_name | |
print "SABURO: "; p saburo.display_name | |
print "SHIRO: "; p shiro.display_name | |
# flat_mapを使った計算の連鎖の例 | |
a = 1.some | |
b = 2.some | |
c = 3.some | |
ans1 = a.flat_map {|i| | |
b.flat_map {|j| | |
c.map {|k| | |
i + j + k | |
} | |
} | |
} | |
print "ans1 is " | |
p ans1 | |
p ans1.get_or_else(-1) | |
# 途中で計算に失敗するとそこで打ち切られる(ぬるぽ安全) | |
a = 1.some | |
b = none | |
c = 3.some | |
ans2 = a.flat_map {|i| | |
b.flat_map {|j| | |
c.map {|k| | |
i + j + k | |
} | |
} | |
} | |
print "ans2 is " | |
p ans2 | |
p ans2.get_or_else(-1) | |
# Nullを含むカラムの扱い例 | |
Stock = Struct.new(:name, :category) | |
stocks = [ | |
Stock.new("stock1", "衣類".some), | |
Stock.new("stock2", "靴".some), | |
Stock.new("stock3", none), | |
Stock.new("stock4", "衣類".some), | |
] | |
category_names = stocks.flat_map{|stock| stock.category.to_a }.uniq.sort.join(",") | |
print "categoryの一覧は " | |
p category_names | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment