Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby 
型別檢查工具簡介

Ruby 
型別檢查工具簡介

於 Coscup 2022 發表。
https://johnlin.vc/coscup-2022/

Johnlin

July 31, 2022
Tweet

More Decks by Johnlin

Other Decks in Programming

Transcript

  1. ᮫ԙզ • John Lin • تᓣ Ruby & Swiftɻओ㭎Swift Taipei

    Meetupɻ • Twitter: @johnlinvc • Blog: https://johnlin.vc/ • Principle Solution Architect @ West Pharmaceutical Service (੢ࣜဌऱ)
  2. ڧྗ㐸࠽த • ୆๺ओཁੋ၏ᬭྍᢛ޻ۀ IoT ɻूᅶᚙలॏ৺೭Ұɻ • google "cake resume west"ɼ༗ෟ਋ࢿൣᅴɻ

    • ౤ཤ㑖త࣌㘸ੋ John Lin հ঺తɻိత࿩ referral bonus ෼㟬Ұ൒ɻ • Coscup ᩶ॿ঎
  3. Agenda • Ruby తܕผܥ౷ • ܕผᒾҰత޷႔ • Ruby ܕผᒾҰ޻۩తಛ৭ •

    Sorbet • Steep • ൺֱ Ruby తܕผᒾҰ޻۩ • Q&A
  4. Ruby తܕผܥ౷ • ڧܕผ Strong Type • ಈଶܕผ Dynamic Type

    • יࢠܕผ Duck typing • ॴ༗౦੢౎ੋ෺݅ Everything is object • ᄸҰ៺ঝ Single Inheritance • Mixin • nil
  5. ܕผ஫ᩄ (type annotation) • ࡏఔࣜᛰதՃ্Ḽղ҃ੋֹ֎తඪࣔɻ • ૾ੋ C++, Python ҃

    Typescript ౎ੋɻ class Foo sig{params(s: String).returns(String)} def bar(s) end end
  6. ܕผఆٛ䈕 V.S. ܕผ஫ᩄ (type annotation) • Matz: • ఔࣜෆधཁܕผඪࣔब။ಈɻtype annotation

    ҧ൓ྃ DRY(Don't Repeat Yourself) ݪଇɻ • ະိՊٕ଍ⴺਐ㑊ޙɼ༗Մೳ׬શෆधཁܕผఆٛ䈕ɻ
  7. Sorbet • ༝ Stripe ։ᚙɼ༻ C++ & Rubyሜతɻ • ᯩଶᒾҰ

    ˍ ಈଶᒾҰ • 㚎ݐޠݴ࢕෰ثڠఆ(Language Server Protocol, LSP) • ෆಉ౳ڃత઴ਐࣜᒾҰ • ಉ࣌ࢧԉ ܕผ஫ᩄ(Type Annotation) ᢛ RBI ܕผఆٛ䈕ɻ
  8. ෆಉ౳ڃత઴ਐࣜᒾҰ • ࡏ䈕Ҋ։಄Ճ্ਆحḼղ # typed: LEVEL बՄҎઃఆᒾҰత౳ڃ • # typed:

    ignore : ׬શࠌུɼՄҎෆੋ༗Ꮘతఔࣜᛰ • # typed: false ɿ ୞ᒾҰޠ๏ɼ༬ઃᆴɻ • # typed: trueɿᒾҰ༗ఆٛతܕผɼ • # typed: strict :ॴ༗తܕผ౎धཁ༗ఆٛɻ • # typed: strongɿbug ኷ଟɼෆཁ༻ɻ
  9. ܕผ஫ᩄ • ࢖༻ T:Sig module ိ၏ܕผ஫ᩄɻ • ܕผ஫ᩄޙతఔࣜᛰґવੋ߹๏త Ruby ఔࣜᛰɻ

    • ՄҎሣᏓᏐ၏ܕผ஫ᩄɻ extend T::Sig sig{params(n: Integer).returns(Integer)} def add1(n); n+1; end
  10. جຊܕผ • T.untyped • Ұൠܕผ • Boolean • Array &

    Hash • Nilable • Block & Proc & lambda
  11. Ұൠܕผ • 1 => Integer or Numeric • 3.14 =>

    Float or Numeric • "hello" => String • :world => Symbol
  12. Boolean • true => T::Boolean or TrueClass • false =>

    T::Boolean or FalseClass • T::Boolean => Union(TrueClass ,FalseClass)
  13. Array & Hash • [1,2,3] => T::Array[Integer] • %w{a b

    c} => T::Array[String] • {hello: "world"} => T::Hash[Symbol, String] • {"answer" => 42} => T::Hash[String, Integer]
  14. T.nilable • T.nilable(Integer) => Union(NilClass, Integer) • ENV["RAILS_ENV"] => T.nilable(String)

    • debug = T.must(ENV["DEBUG"]) => String 
 ೗Ռ DEBUG ෆଘࡏɼࣥߦظ။㋝ग़ྫ֎ • debug = ENV.fetch("DEBUG","") => String
  15. Block & Proc & lambda • proc {|n| n *

    2 } => T.proc.params(n: Integer).returns(Integer) • Proc.new{|n| n*2} => Proc
  16. ࿆ूܕผ T.any • ՄҎҝଖதҰछܕผ • T.nilable(X) => T.any(NilClass, X) sig

    {params(x: T.any(Integer,String)).void} def foo(x); end foo(10) foo("Hello, world")
  17. ަूܕผ T.all • ಉ࣌༗ Module1 & Module2 ၷݸ Mixin •

    {params(x: T.all(Module1, Module2)).void} def requires_both(x) x.method1 # ok x.method2 # also ok end
  18. ՄᏓ௕౓ჩᏐ • args ҰఆੋArray ॴҎ୞ཁඪࣔݩૉతܕผ • kwargs Ұఆੋ Keyҝ Symbol

    త Hash, ॴҎ୞ཁඪࣔValue తܕผɻ extend T::Sig sig{params(args: Int, kwargs: String).returns(String)} def foo(*args, **kwargs) "#{args.sum}" + kwargs.map{|k,v| "#{k}: #{v}"} end
  19. block ჩᏐ • ཁՃ &blk ࠽ೳඪࣔჩᏐతܕผɻᔒՃత࿩ block ။ඃᙛ੒ untyped sig

    {params(blk: T.proc.returns(Integer)).returns(Integer)} def foo(&blk) # <- yield end
  20. Void ճၚᆴ • Ruby Ӭԕ။ճၚ࠷ޙҰߦɻୠ༗࣌ީੋ䭘䭓ᆴɻ • ඪ্ void త࿩बՄҎආ໔ޡ༻ճၚᆴɻ sig

    {params(name: String).void} def greet(name) puts "Hello, #{name}!" end puts greet("Coscup") # ERROR !
  21. T.let • ઃఆᏓᏐత type • ෆ߹ཧత value ။༗ errorɻ x

    = T.let(10, Integer) y = T.let(10, String) # error
  22. T.cast • ՄҎڧ੍᫚ܕ੒ଖଞ typeɻ • ୠؐੋ။ᒾҰ A ౸ఈ༗ᔒ༗ foo ํ๏ɻ

    case label when 'a' T.cast(a_or_b, A).foo when 'b' T.cast(a_or_b, B).bar end
  23. T.bind • ೺ self ڧ੍᫚ܕ༻త • self ෆೳ༻ T.cast •

    ࡏ proc/block ཫ໘۰౸ instance_eval ࣌኷መ༻ T.bind(self, MyClass) self.method_on_my_class
  24. fl ow-sensitive • Sorbet ஌ಓࡏ if ཫ໘త x ෆՄೳੋ nilɼॴҎෆ။༗ܕผࡨ

    ޡɻ • if/unless, case, nil? , is_a? , ! , &&, || ౎။աᖤᎃෆՄೳత ܕผ x = T.let(1, T.nilable(Integer)) if x x + 1 # No Error end
  25. ҏἾ֥ূ • ௚઀ࣥߦ༻త script ཁ༻ if __FILE__ == $PROGRAM_NAME แىိɻ

    • RSpec ။༗Ұେථ TypeErrorɻՄҎશ෦ ignoreɻ • ኷ଟ Gem ౎ؐᔒ༗ Type De fi nitionɻ၏ग़։ݯߩᘔతେ޷ ࣌ػɻ
  26. Steep • by Soutaro Matsumoto ɼ༻ Ruby ሜతɻ • ൒׭ํతܕผᒾҰثɼʢҼҝ࿨

    RBS ੋಉҰݸ࡞ऀʣ • ᯩଶᒾҰɻ • ࢖༻ ᘐཱత RBS ܕผఆٛ䈕ɻ • gem install steep
  27. RBS ܕผఆٛ䈕 class Channel attr_reader name: String def initialize: (name:

    String) -> void def each_member: () { (User | Bot) -> void } -> void # `{` and `}` means block. | () -> Enumerator[User | Bot, void] # Method can be overloaded. end
  28. RBI vs RBS • RBI: ෆ୞ՄҎఆٛ typeɼؐՄҎሣܕผ၏ਐ֊ఆٛɻ • RBS: ՄҎ၏

    overloading • መࡍ্બ䬟ݸ౎ՄҎɼ༗޻۩(parlour) ՄҎ၏᫚׵ɻ