Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
多相型、推論、Ruby
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Soutaro Matsumoto
March 20, 2017
7.4k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
多相型、推論、Ruby
大江戸Ruby会議06
https://asakusarb.github.io/oedo06/
Soutaro Matsumoto
March 20, 2017
More Decks by Soutaro Matsumoto
See All by Soutaro Matsumoto
Making the RBS Parser Faster
soutaro
0
910
API for docs
soutaro
4
3.5k
Rubyの標準添付ライブラリを開発する
soutaro
2
240
Embedding it into Ruby code
soutaro
4
27k
Parsing RBS
soutaro
0
2k
Ruby programming with types in action
soutaro
4
1k
IDE Development with Ruby
soutaro
4
1.2k
Ruby 3の新機能としての静的型検査の開発
soutaro
4
7.9k
An Introduction to Static Typing in Ruby 3
soutaro
3
490
Featured
See All Featured
Abbi's Birthday
coloredviolet
2
8.1k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
610
Optimizing for Happiness
mojombo
378
71k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
740
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
290
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
310
Accessibility Awareness
sabderemane
1
140
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
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 ࣮ͳ͍ͷʁ Α͘ݟΔͱɺʢܕऍΛίϝϯτͱ͔Ͱॻ͘͜ͱʹ͢Εʣ͙͢ ʹ࣮Ͱ͖Δͳ͜Εʜʜ