Rubyに型があると便利か

77897395d9b84463bd474a69b922b2ec?s=47 ksss
May 28, 2016

 Rubyに型があると便利か

2016/5/28 東京Ruby会議11 3rd session

77897395d9b84463bd474a69b922b2ec?s=128

ksss

May 28, 2016
Tweet

Transcript

  1. 5.

    ܕ

  2. 6.
  3. 10.

    String === "hello" #=> true String === 123 #=> false

    String === nil #=> false RubyͰClassνΣοΫ
  4. 15.

    Struct͓͞Β͍ User = Struct.new( :name, :age, :type, ) user =

    User.new( "ksss", 29, "normal", ) user.name #=> "ksss"
  5. 16.

    TypeStruct User = TypeStruct.new( name: String, age: Integer, type: /\A(genius|normal)\z/

    ) user = User.new( name: "ksss", age: 29, type: "normal" ) user.name #=> "ksss"
  6. 23.
  7. 25.

    Second Issue { "object": { "object_id" 123, "contents": [ {

    "content_id": 234, "items": [ { "type": "image", "image_id": 10, "position": { "x": 100, "y": 200, } }, { "type": "text", "font_id": 20, "position": { "x": 300, "y": 400, } "option": {} }]}]}}
  8. 26.

    Second Issue json["object"]["contents"].each do |content| content["items"].each do |item| case item["type"]

    when "image" image_id = item["image_id"] x = item["position"]["x"] # ... when "text" # ... end end end
  9. 27.

    Second Issue json.fetch("object").fetch("contents").each do |content| content.fetch("items").each do |item| case item.fetch("type")

    when "image" image_id = item.fetch("image_id") x = item.fetch("position").fetch("x") # ... when "text" # ... end end end
  10. 30.

    Golang JSON type Point struct { X int `json:"x"` Y

    int `json:"y"` } type Line struct { P1 Point `json:"p1"` P2 Point `json:"p2"` } func main() { const input = `{"p1":{"x":10,"y":20},"p2":{"x":30,"y":40}}` var line Line json.NewDecoder(strings.NewReader(input)).Decode(&line) fmt.Println(line.P2.Y) //=> 40 }
  11. 31.

    Crystal JSON class Point JSON.mapping({ x: Int64, y: Int64, })

    end class Line JSON.mapping({ p1: Point, p2: Point, }) end input = %({"p1":{"x":10,"y":20},"p2":{"x":30,"y":40}}) line = Line.from_json(input) puts line.p2.y #=> 40
  12. 34.

    TypeStruct.from_hash Point = TypeStruct.new( x: Integer, y: Integer, ) Line

    = TypeStruct.new( p1: Point, p2: Point, ) input = %({"p1":{"x":10,"y":20}, "p2":{"x":30,"y":40}}) line = Line.from_hash(JSON(input)) puts line.p2.y #=> 40
  13. 35.

    { "object": { "object_id" 123, "contents": [ { "content_id": 234,

    "items": [ { "type": "image", "image_id": 10, "position": { "x": 100, "y": 200, } }, { "type": "text", "font_id": 20, "position": { "x": 300, "y": 400, } "option": {} }]}]}} TypeStruct
  14. 36.

    TypeStruct Position = TypeStruct.new( x: Numeric, y: Numeric, ) Text

    = TypeStruct.new( font_id: Integer, position: Position, option: Option, ) Image = TypeStruct.new( image_id: Integer, position: Position, ) Content = TypeStruct.new( content_id: Integer, items: ArrayOf(Image | Text), ) Obj = TypeStruct.new( object_id: Integer, contents: ArrayOf(Content), )
  15. 37.

    TypeStruct json.object.contents.each do |content| content.items.each do |item| case item when

    Image image_id = item.image_id x = item.position.x # ... when Text # ... end end end
  16. 43.
  17. 44.

    ArrayOf Encount = TypeStruct.new( enemies: ArrayOf(Slime) ) encount = Encount.from_hash(

    enemies: [ {"slime": "A"}, {"slime": "B"}, {"slime": "C"} ] ) encount.enemies #=> [#<Slime A>, #<Slime B>, #<Slime C>]
  18. 45.

    ArrayOf class ArrayOf def initialize(type) @type = type end def

    ===(ary) ary.all? { |o| @type === o } end end
  19. 49.

    Golang & Crystal class Encount JSON.mapping({ enemies: Hash(String, Slime) })

    end type Encount struct { Enemies map[string]Slime }
  20. 50.
  21. 51.

    HashOf Encount = TypeStruct.new( enemies: HashOf(String, Slime) ) encount =

    Encount.from_hash( enemies: { "1" => {"slime": "A"}, "2" => {"slime": "B"}, "3" => {"slime": "C"} } ) encount.enemies.each do |index, slime|
  22. 52.

    HashOf class HashOf def initialize(key_type, value_type) @key_type = key_type @value_type

    = value_type end def ===(h) h.all? do |k, v| @key_type === k && @value_type === v end end end
  23. 54.

    Golang & Crystal type Figure struct { Show bool }

    class Figure JSON.mapping({ show: Bool }) end
  24. 55.

    include Boolean? module Boolean end class TrueClass include Boolean end

    class FalseClass include Boolean end Boolean === true #=> true Boolean === false #=> true Boolean === Object.new #=> false
  25. 56.

    Null type Canvas struct { item: Item } class Canvas

    item: { type: Item, nilable: true } end
  26. 58.

  27. 59.
  28. 60.

    Union class Union def initialize(*classes) @classes = classes end def

    ===(obj) @classes.any? { |c| c === obj } end end
  29. 62.

    Union Integer | String # 123 or "hi" TrueClass |

    FalseClass # true or false ArrayOf(Item) | NilClass # [Item] or nil ArrayOf(Slime | Drakee | Golem) # [Slime or Drakee or Golem]
  30. 65.
  31. 66.

    Interface class Interface def initialize(*methods) @methods = methods end def

    ===(other) @methods.all? do |m| other.respond_to?(m) end end end
  32. 67.

    Interface Reader = Interface.new(:read) Writer = Interface.new(:write) Stream = TypeStruct.new(

    input: Reader, output: Writer, ) Stream.new(input: $stdin, output: StringIO.new)
  33. 69.
  34. 76.
  35. 77.
  36. 82.