Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
多相型、推論、Ruby
Soutaro Matsumoto
March 20, 2017
4
6.1k
多相型、推論、Ruby
大江戸Ruby会議06
https://asakusarb.github.io/oedo06/
Soutaro Matsumoto
March 20, 2017
Tweet
Share
More Decks by Soutaro Matsumoto
See All by Soutaro Matsumoto
IDE Development with Ruby
soutaro
3
750
Ruby 3の新機能としての静的型検査の開発
soutaro
2
4.6k
An Introduction to Static Typing in Ruby 3
soutaro
3
240
The State of Ruby 3 Typing
soutaro
0
620
Ruby3 is a typed language
soutaro
0
240
Ruby Hack Challenge Holiday #8
soutaro
0
380
型なし言語のための型
soutaro
7
8.1k
An introduction to typed Ruby programming
soutaro
2
19k
Ruby with types
soutaro
1
200
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
337
17k
How To Stay Up To Date on Web Technology
chriscoyier
780
250k
10 Git Anti Patterns You Should be Aware of
lemiorhan
638
52k
Learning to Love Humans: Emotional Interface Design
aarron
261
37k
The Invisible Customer
myddelton
110
11k
Stop Working from a Prison Cell
hatefulcrawdad
261
17k
Clear Off the Table
cherdarchuk
79
280k
Intergalactic Javascript Robots from Outer Space
tanoku
261
25k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
655
120k
Facilitating Awesome Meetings
lara
29
4k
Git: the NoSQL Database
bkeepers
PRO
415
59k
jQuery: Nuts, Bolts and Bling
dougneiner
56
6.4k
Transcript
ଟ૬ܕɺ ਪɺ Ruby দຊफଠ @soutaro
None
None
ܕॻ͖ͨ͘ͳ͍
ܕॻ͖ͨ͘ͳ͍ Duck Typingʹͳ͍ͬͯͯཉ͍͠
ܕॻ͖ͨ͘ͳ͍ Duck Typingʹͳ͍ͬͯͯཉ͍͠ ܕਪ
ܕॻ͖ͨ͘ͳ͍ Duck Typingʹͳ͍ͬͯͯཉ͍͠ ܕਪ typo͙Β͍࣮ߦ͠ͳͯ͘ൃݟ͍ͨ͠
ܕॻ͖ͨ͘ͳ͍ Duck Typingʹͳ͍ͬͯͯཉ͍͠ ܕਪ typo͙Β͍࣮ߦ͠ͳͯ͘ൃݟ͍ͨ͠ ܕઈରʹॻ͖ͨ͘ͳ͍
ܕॻ͖ͨ͘ͳ͍ Duck Typingʹͳ͍ͬͯͯཉ͍͠ ܕਪ typo͙Β͍࣮ߦ͠ͳͯ͘ൃݟ͍ͨ͠ ܕઈରʹॻ͖ͨ͘ͳ͍ Gradual Typing
ͳΜ͔ྑ͍ײ͡ʹܕ͕͍ͭͨ Ruby͕ཉ͍͠ ܕॻ͖ͨ͘ͳ͍ Duck Typingʹͳ͍ͬͯͯཉ͍͠ ܕਪ typo͙Β͍࣮ߦ͠ͳͯ͘ൃݟ͍ͨ͠ ܕઈରʹॻ͖ͨ͘ͳ͍ Gradual Typing
զʑ͕ཉ͍͠ͷ ͳΜ͔ྑ͍ײ͡ʹܕ͕͍ͭͨRuby͕ཉ͍͠ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby
ଟ૬ܕ w ύϥϝʔλଟ૬Parametric Polymorphism w ෦ܕଟ૬Subtyping Polymorphism w ΞυϗοΫଟ૬Ad-hoc Polymorphism
จ຺ʹԠͯ͡ɺҰఆͷ੍ݶͷݩͰɺ ࣜʹ͍Ζ͍ΖͳܕΛ༩͑Δ
෦ܕଟ૬ w ෦ܕ “String is a Object” interface X {
void f(Object x); } X x = …; x.f("Ruby"); x.f(new ArrayList());
෦ܕଟ૬ w ෦ܕ “String is a Object” interface X {
void f(Object x); } X x = …; x.f("Ruby"); x.f(new ArrayList()); ҾͷܕString
෦ܕଟ૬ w ෦ܕ “String is a Object” interface X {
void f(Object x); } X x = …; x.f("Ruby"); x.f(new ArrayList()); ҾͷܕString ҾͷܕArrayList
໊લతɾߏత w ໊લతNominal ΫϥεఆٛͰએݴͯ͠෦ܕؔΛఆٛ w ߏతStructual ϝιουఆٛͷแؚؔͰ෦ܕؔΛఆٛʢΑΓ ॊೈʣ
ܕਪ w ʢશͳʣܕਪ w ϩʔΧϧܕਪ
ʢશͳʣܕਪ [Milner, 1978] w શ͘ܕΛॻ͔ͳͯ͘ྑ͍ ʢܕਪͷશੑCompletenessʣ w ϓϩάϥϛϯάݴޠͷ੍͕େ͖͍ʢMLʣ # let
has_even_leaf tree = exists_leaf (fun n -> n mod 2 = 0) tree;; val has_even_leaf : tree -> bool = <fun>
ϩʔΧϧܕਪ [Pierce, 1997] w ϩʔΧϧมͷܕॻ͔ͳͯ͘ྑ͍ ϝιουͱ͔ͷܕॻ͘ɻ w ͍ΖΜͳϓϩάϥϛϯάݴޠʹಋೖͰ͖Δ ʢScala/Swift/C#/C++ʣ func
greet(person: String) -> String { let greeting = "Hello, " + person + "!" return greeting }
ϩʔΧϧܕਪ [Pierce, 1997] w ϩʔΧϧมͷܕॻ͔ͳͯ͘ྑ͍ ϝιουͱ͔ͷܕॻ͘ɻ w ͍ΖΜͳϓϩάϥϛϯάݴޠʹಋೖͰ͖Δ ʢScala/Swift/C#/C++ʣ func
greet(person: String) -> String { let greeting = "Hello, " + person + "!" return greeting } greetingͷܕਪ͞ΕΔ
ϩʔΧϧܕਪ [Pierce, 1997] w ϩʔΧϧมͷܕॻ͔ͳͯ͘ྑ͍ ϝιουͱ͔ͷܕॻ͘ɻ w ͍ΖΜͳϓϩάϥϛϯάݴޠʹಋೖͰ͖Δ ʢScala/Swift/C#/C++ʣ func
greet(person: String) -> String { let greeting = "Hello, " + person + "!" return greeting } greetingͷܕਪ͞ΕΔ ؔͷܕॻ͘
զʑ͕ཉ͍͠ͷ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby ͳΜ͔ྑ͍ײ͡ʹܕ͕͍ͭͨRuby͕ཉ͍͠
OCamlͳΜ͔͍ۙͷͰ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby # let f x
= print_string x#to_s;; val f : < to_s : string; .. > -> unit = <fun>
OCamlͳΜ͔͍ۙͷͰ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby # let f x
= print_string x#to_s;; val f : < to_s : string; .. > -> unit = <fun> #Ͱϝιουݺͼग़͠
OCamlͳΜ͔͍ۙͷͰ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby # let f x
= print_string x#to_s;; val f : < to_s : string; .. > -> unit = <fun> to_sͱ͍͏ϝιου͕͋ΕͳΜͰ͍͍ #Ͱϝιουݺͼग़͠
OCamlͰμϝͳͱ͜Ζ w OCamlΦϒδΣΫτͷपΓͰܕΛॻ͘ඞཁ͕ ͋Δ w OCamlͰॻ͚ͳ͍ϝιου w Array#map String#split
զʑ͕ཉ͍͠ͷ w ·ʔແཧ ͳʹ͔ΛఘΊͳ͍ͱ͍͚ͳ͍ɻ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby
զʑ͕ཉ͍͠ͷ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby
զʑ͕ཉ͍͠ͷ RubyͷػೳΛ੍ݶ͍ͯͬͯ͠ɺܕਪͰ͖ ΔΑ͏ʹͳΒͳ͍͔ʁʁ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby
eval w ແཧ w evalͷฦΓͷܕanyΈ͍ͨͳܕʹͯ͠͠·͑ ͍͍ͷͰʢGradual Typing [Siek and Taha,
2006]ʣ eval(gets)
ActiveRecord w DBʹଓ͠ͳ͍ͱΞτϦϏϡʔτ͕Θ͔Βͳ͍ w anyͰͳΜͱ͔͠Α͏ class Person < ApplicationRecord belongs_to
:group has_many :contacts end
ϝλϓϩάϥϛϯά define_method(:name=) do |x| @attributes[:name] = x end
ϝλϓϩάϥϛϯά class Location attr_reader :line attr_reader :column end
require w require͕࣮ߦ͞ΕΔॠؒ·ͰͲͷϓϩάϥϜ͕ಡ· ΕΔ͔Θ͔Βͳ͍ w requireϝιουͳͷͰɺ࠶ఆٛͰ͖Δ͠ɺͲ͜ ʹͰॻ͚Δ͠ɺҾʹ͕ࣜॻ͚Δ w $LOAD_PATH͋ΔΑʂ w
requireΛߏจʹͯ͠จࣈྻ͔͠ड͚औΕͳ͍ˍτο ϓϨϕϧʹ͔͠ॻ͚ͳ͍Α͏ʹ͢Εྑ͍ͷͰ
RubyGems ⚰Bundler
RubyΛ੍ݶͯ͠͏·͍͔͘ͳ͍ w ଞʹ͕͋Γɺݱ࣮తͳ੍ݶ͕ݟ͚ͭΒΕͳ͍ ʢࠓޙɺݟ͔ͭΔ͔͠Εͳ͍ʣ w ܕΛॻ͔ͳ͍લఏͰɺҰճanyʹࣦΘΕͨܕใ ΛऔΓ͢ํ๏͕ͳ͍
զʑ͕ཉ͍͠ͷ ύϥϝʔλଟ૬ ߏతͳ෦ܕଟ૬ શͳܕਪ Ruby
͝ఏҊ w ߏతͳ෦ܕଟ૬ ϩʔΧϧܕਪ Gradual Typing w ʢΘΓͱʣDuck TypingͰ͖ΔͷͰخ͍͠ w
ॻ͔ͳͯ͘ྑ͍ܕॻ͔ͳ͍ w ܕ͕ॻ͍ͯͳ͍ͱ͖ࠓͷRubyͱಉ͡ w ܕͷͨΊͷݴޠRubyͱผ requireͱ͔ΦʔϓϯΫϥεͱ͔ϝλϓϩάϥϛϯάͱ ͔ߟ͑ͳ͍ɻ
͍͍ͩͨTypeScript
# group.rbi interface String def gsub: (Regexp, String) -> String
end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … }
# group.rbi interface String def gsub: (Regexp, String) -> String
end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … } ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ
# group.rbi interface String def gsub: (Regexp, String) -> String
end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … } ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ
# group.rbi interface String def gsub: (Regexp, String) -> String
end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … } ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ ܕऍ ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ
# group.rbi interface String def gsub: (Regexp, String) -> String
end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … } ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ ܕऍ ӈลͷܕ͕Θ͔ΔͷͰɺܕऍෆཁ ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ
# group.rbi interface String def gsub: (Regexp, String) -> String
end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … } ผͷϑΝΠϧͰɺΠϯλʔϑΣΠεΛએݴ͢Δ ܕऍ ӈลͷܕ͕Θ͔ΔͷͰɺܕऍෆཁ person.emailͷܕ͕StringͩͱΘ ͔ΔͷͰɺmap͕ͳ͍͜ͱ͕Θ͔Δ ΠϯλϑΣʔεʹϝιουͱܕΛએݴ͢Δ
ܕऍ͕ͳ͚Ε͜Ε·ͰͷRubyͱಉ͡ group = Group.create!(name: name) person = group.people.new escaped =
person.email.map {|x| … }
ܕऍ͕ͳ͚Ε͜Ε·ͰͷRubyͱಉ͡ group = Group.create!(name: name) person = group.people.new escaped =
person.email.map {|x| … } ܕऍ͕ͳ͍ͷͰશ෦anyʹͳΔԿݕࠪ͠ͳ͍
ܕऍ͕ͳ͚Ε͜Ε·ͰͷRubyͱಉ͡ group = Group.create!(name: name) person = group.people.new escaped =
person.email.map {|x| … } map͕ແ͍͜ͱ࣮ߦ࣌ʹൃ֮ ܕऍ͕ͳ͍ͷͰશ෦anyʹͳΔԿݕࠪ͠ͳ͍
# group.rbi interface String def gsub: (Regexp, String) -> String
... end interface IGroup def people: ActiveRecord.Association<IPerson> end interface IPerson def email: String end # foo_controller.rb group: IGroup = Group.create!(name: name) person = group.people.new escaped = person.email.map {|x| … }
– RubyͷMatz lܕઈରॻ͖ͨ͘ͳ͍z
w Group.create!ͷܕ͕GroupʹͳΔͷΘ͔Βͳ͍ͷʁ Groupͷܕ͕Θ͔ΔͱࢥͬͯΔͷʁʁ w ܕΛҰͭॻ͍͍ͯͳ͍ͱͳʹΘ͔Βͳ͍ͷʁʁ ϦςϥϧͳΜ͔Θ͔Δͣɻҙ֎ͱ͍Ζ͍Ζݟ͔ͭΔͷͰɻ w ΫϥεఆٛʹܕΛॻ͚ͳ͍ͷʁΦʔϓϯΫϥεͲ͏ͳΔͷʁ ࠓޙͷ՝ɻΦʔϓϯΫϥεͱ0CKFDUJWF$ͷ$BUFHPSZͳΜ͔ ͍ۙؾ͕͢Δɻ
w ࣮ͳ͍ͷʁ Α͘ݟΔͱɺʢܕऍΛίϝϯτͱ͔Ͱॻ͘͜ͱʹ͢Εʣ͙͢ ʹ࣮Ͱ͖Δͳ͜Εʜʜ