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

Rubyに型があると便利か

ksss
May 28, 2016

 Rubyに型があると便利か

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

ksss

May 28, 2016
Tweet

More Decks by ksss

Other Decks in Programming

Transcript

  1. ܕ

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

    String === nil #=> false RubyͰClassνΣοΫ
  3. Struct͓͞Β͍ User = Struct.new( :name, :age, :type, ) user =

    User.new( "ksss", 29, "normal", ) user.name #=> "ksss"
  4. 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"
  5. 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": {} }]}]}}
  6. 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
  7. 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
  8. 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 }
  9. 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
  10. 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
  11. { "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
  12. 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), )
  13. 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
  14. 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>]
  15. ArrayOf class ArrayOf def initialize(type) @type = type end def

    ===(ary) ary.all? { |o| @type === o } end end
  16. Golang & Crystal class Encount JSON.mapping({ enemies: Hash(String, Slime) })

    end type Encount struct { Enemies map[string]Slime }
  17. 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|
  18. 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
  19. Golang & Crystal type Figure struct { Show bool }

    class Figure JSON.mapping({ show: Bool }) end
  20. 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
  21. Null type Canvas struct { item: Item } class Canvas

    item: { type: Item, nilable: true } end
  22. Union class Union def initialize(*classes) @classes = classes end def

    ===(obj) @classes.any? { |c| c === obj } end end
  23. 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]
  24. Interface class Interface def initialize(*methods) @methods = methods end def

    ===(other) @methods.all? do |m| other.respond_to?(m) end end end
  25. Interface Reader = Interface.new(:read) Writer = Interface.new(:write) Stream = TypeStruct.new(

    input: Reader, output: Writer, ) Stream.new(input: $stdin, output: StringIO.new)