stitcher 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +9 -0
 - data/.rspec +2 -0
 - data/.travis.yml +3 -0
 - data/Gemfile +4 -0
 - data/README.md +107 -0
 - data/Rakefile +7 -0
 - data/bin/console +14 -0
 - data/bin/setup +7 -0
 - data/docs/matome.md +57 -0
 - data/docs/stitcher.md +208 -0
 - data/docs/type.md +212 -0
 - data/docs/typed.md +15 -0
 - data/example/core_ex.rb +23 -0
 - data/example/register.rb +33 -0
 - data/example/simple.rb +66 -0
 - data/example/type.rb +24 -0
 - data/lib/stitcher.rb +40 -0
 - data/lib/stitcher/accessor.rb +21 -0
 - data/lib/stitcher/concepts.rb +6 -0
 - data/lib/stitcher/core.rb +31 -0
 - data/lib/stitcher/core_ext.rb +7 -0
 - data/lib/stitcher/define_method.rb +52 -0
 - data/lib/stitcher/operators.rb +37 -0
 - data/lib/stitcher/register.rb +31 -0
 - data/lib/stitcher/require.rb +27 -0
 - data/lib/stitcher/stitch.rb +22 -0
 - data/lib/stitcher/type.rb +107 -0
 - data/lib/stitcher/type/core_ext.rb +11 -0
 - data/lib/stitcher/variadic_argument.rb +12 -0
 - data/lib/stitcher/version.rb +3 -0
 - data/stitcher.gemspec +25 -0
 - metadata +117 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 60b567e6e0cac2f1dacd168e411da63d097eeb68
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 137483e2bf3e741fe861ff1ea2b4c7c0604b9be0
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 879f602d5e7456953ac1b0b16d98dd7346f6e2ac4f216702bc88600f7d64d939f7bbe1ad5c1299ccc9ddc951281b756d3605e917d7919e68a480e2c60bc1815a
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 883c44327d337921e864614153f874f92b5c90eba6a5eb01ac542fd1a1bbf776a6056c865b9649b4f1dd99040bc0ede011031ba0dc5ee88f4dc1957e47e7949f
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,107 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            [](https://travis-ci.org/osyo-manga/gem-stitcher)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Stitcher
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/stitcher`. To experiment with that code, run `bin/console` for an interactive prompt.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            TODO: Delete this and the text above, and describe your gem
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 14 
     | 
    
         
            +
            gem 'stitcher'
         
     | 
| 
      
 15 
     | 
    
         
            +
            ```
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                $ bundle
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                $ gem install stitcher
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 28 
     | 
    
         
            +
            require "stitcher"
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            # Using stitcher library.
         
     | 
| 
      
 31 
     | 
    
         
            +
            using Stitcher
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            class X
         
     | 
| 
      
 34 
     | 
    
         
            +
            	# Define accessor with variable type(Class).
         
     | 
| 
      
 35 
     | 
    
         
            +
            	stitcher_accessor name: String, age: Integer
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            	def set name, age
         
     | 
| 
      
 38 
     | 
    
         
            +
            		self.name = name
         
     | 
| 
      
 39 
     | 
    
         
            +
            		self.age  = age
         
     | 
| 
      
 40 
     | 
    
         
            +
            	end
         
     | 
| 
      
 41 
     | 
    
         
            +
            	# Register set method with Argument types(Classes).
         
     | 
| 
      
 42 
     | 
    
         
            +
            	stitch :set, [String, Integer]
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            	# Register for next define method.
         
     | 
| 
      
 45 
     | 
    
         
            +
            	stitcher_require [Hash]
         
     | 
| 
      
 46 
     | 
    
         
            +
            	def set hash
         
     | 
| 
      
 47 
     | 
    
         
            +
            		set hash[:name], hash[:age]
         
     | 
| 
      
 48 
     | 
    
         
            +
            	end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            	# Define "set" method with Argument types.
         
     | 
| 
      
 51 
     | 
    
         
            +
            	# set(Integer, String)
         
     | 
| 
      
 52 
     | 
    
         
            +
            	stitcher_define_method(:set, age: Integer, name: String){
         
     | 
| 
      
 53 
     | 
    
         
            +
            		self.name = name
         
     | 
| 
      
 54 
     | 
    
         
            +
            		self.age  = age
         
     | 
| 
      
 55 
     | 
    
         
            +
            	}
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            	# Other define method
         
     | 
| 
      
 58 
     | 
    
         
            +
            	stitch.set(ary: [String, Integer]){
         
     | 
| 
      
 59 
     | 
    
         
            +
            		set *ary
         
     | 
| 
      
 60 
     | 
    
         
            +
            	}
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            	def print
         
     | 
| 
      
 63 
     | 
    
         
            +
            		p "name:#{name} age:#{age}"
         
     | 
| 
      
 64 
     | 
    
         
            +
            	end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            	# Require format with block object.
         
     | 
| 
      
 67 
     | 
    
         
            +
            	stitcher_require [String] & Stitcher::Concepts.blockable
         
     | 
| 
      
 68 
     | 
    
         
            +
            	def print fmt
         
     | 
| 
      
 69 
     | 
    
         
            +
            		printf(fmt, *yield(name, age))
         
     | 
| 
      
 70 
     | 
    
         
            +
            	end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            x = X.new
         
     | 
| 
      
 74 
     | 
    
         
            +
            x.name = "homu"
         
     | 
| 
      
 75 
     | 
    
         
            +
            x.age  = 14
         
     | 
| 
      
 76 
     | 
    
         
            +
            # x.age = 14.0		# Error: No match method.
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            x.set "mami", 15
         
     | 
| 
      
 79 
     | 
    
         
            +
            x.print
         
     | 
| 
      
 80 
     | 
    
         
            +
            # => "name:mami age:15"
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            x.set({ name: "saya", age: 14 })
         
     | 
| 
      
 83 
     | 
    
         
            +
            x.print
         
     | 
| 
      
 84 
     | 
    
         
            +
            # => "name:saya age:14"
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            x.set 14, "mado"
         
     | 
| 
      
 87 
     | 
    
         
            +
            x.print("%s-%s\n"){ |name, age| [name, age] }
         
     | 
| 
      
 88 
     | 
    
         
            +
            # => mado-14
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            x.set ["homu", 14]
         
     | 
| 
      
 91 
     | 
    
         
            +
            x.print("%s-%s\n"){ |name, age| [age, name] }
         
     | 
| 
      
 92 
     | 
    
         
            +
            # => 14-homu
         
     | 
| 
      
 93 
     | 
    
         
            +
            ```
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            ## Development
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            1. Fork it ( https://github.com/osyo-manga/gem-stitcher )
         
     | 
| 
      
 104 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 105 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         
     | 
| 
      
 106 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 107 
     | 
    
         
            +
            5. Create a new Pull Request
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/console
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "bundler/setup"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "stitcher"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # You can add fixtures and/or initialization code here to make experimenting
         
     | 
| 
      
 7 
     | 
    
         
            +
            # with your gem easier. You can also use a different console, if you like.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # (If you use this, don't forget to add pry to your Gemfile!)
         
     | 
| 
      
 10 
     | 
    
         
            +
            # require "pry"
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Pry.start
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            require "irb"
         
     | 
| 
      
 14 
     | 
    
         
            +
            IRB.start
         
     | 
    
        data/bin/setup
    ADDED
    
    
    
        data/docs/matome.md
    ADDED
    
    | 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Stitcher
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## 目的
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * メソッドの多重定義をする
         
     | 
| 
      
 6 
     | 
    
         
            +
             * 引数によって呼び出すメソッドを切り替える
         
     | 
| 
      
 7 
     | 
    
         
            +
            * メソッドの引数に対しての制限を設ける
         
     | 
| 
      
 8 
     | 
    
         
            +
             * 引数に対する型チェック
         
     | 
| 
      
 9 
     | 
    
         
            +
             * 引数に対するコンセプトチェック
         
     | 
| 
      
 10 
     | 
    
         
            +
            * モンキーパッチで定義するメソッドを制限したい
         
     | 
| 
      
 11 
     | 
    
         
            +
             * 引数が○○○の場合でのみモンキーパッチのメソッドを呼び出す等
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            ## 動作イメージ
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 17 
     | 
    
         
            +
            class X
         
     | 
| 
      
 18 
     | 
    
         
            +
            	include Stitcher
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            	def plus a, b
         
     | 
| 
      
 21 
     | 
    
         
            +
            		p "plus(a.to_i, b.to_i)"
         
     | 
| 
      
 22 
     | 
    
         
            +
            		a.to_i + b.to_i
         
     | 
| 
      
 23 
     | 
    
         
            +
            	end
         
     | 
| 
      
 24 
     | 
    
         
            +
            	# #plus を呼び出すコンセプトを設定する
         
     | 
| 
      
 25 
     | 
    
         
            +
            	# 引数がそれぞれ #to_i を呼び出せればこのメソッドを呼び出す
         
     | 
| 
      
 26 
     | 
    
         
            +
            	concept :plus do |a, b|
         
     | 
| 
      
 27 
     | 
    
         
            +
            		a.respond_to?(:to_i) && b.respond_to?(:to_i)
         
     | 
| 
      
 28 
     | 
    
         
            +
            	end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            	# concept 設定後に別のメソッドを定義し直す事ができる
         
     | 
| 
      
 31 
     | 
    
         
            +
            	def plus a, b
         
     | 
| 
      
 32 
     | 
    
         
            +
            		p "plus(a + b)"
         
     | 
| 
      
 33 
     | 
    
         
            +
            		a + b
         
     | 
| 
      
 34 
     | 
    
         
            +
            	end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            	# 再定義したメソッドに対しても条件を設定できる
         
     | 
| 
      
 37 
     | 
    
         
            +
            	# こっちは両方共 Numeric だった場合に呼び出す
         
     | 
| 
      
 38 
     | 
    
         
            +
            	concept :plus do |a, b|
         
     | 
| 
      
 39 
     | 
    
         
            +
            		a.class <= Numeric && b.class <= Numeric
         
     | 
| 
      
 40 
     | 
    
         
            +
            	end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            X.new.plus "1", "2"
         
     | 
| 
      
 44 
     | 
    
         
            +
            # => 最初に定義したメソッドが呼ばれる
         
     | 
| 
      
 45 
     | 
    
         
            +
            X.new.plus 1, 2
         
     | 
| 
      
 46 
     | 
    
         
            +
            # => あとで定義したメソッドが呼ばれる
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            X.new.plus X, X
         
     | 
| 
      
 49 
     | 
    
         
            +
            # => どれにも該当しないのでエラー
         
     | 
| 
      
 50 
     | 
    
         
            +
            ```
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            ## 考えること
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            * 呼び出すことができるメソッドが複数あった場合どうするか
         
     | 
| 
      
 56 
     | 
    
         
            +
            * 呼び出すメソッドの優先順位
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
    
        data/docs/stitcher.md
    ADDED
    
    | 
         @@ -0,0 +1,208 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Stitcher
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## これは何?
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            定義する(定義した)メソッドに対して引数のシグネチャを設定するライブラリです。
         
     | 
| 
      
 6 
     | 
    
         
            +
            シグネチャを指定することにより、静的型付け言語のようなメソッドの多重定義を行うことを目的としています、
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ## 導入
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            #### install
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 14 
     | 
    
         
            +
            $ gem install stitcher
         
     | 
| 
      
 15 
     | 
    
         
            +
            ```
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            #### require
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 20 
     | 
    
         
            +
            require "stitcher"
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            using Stitcher
         
     | 
| 
      
 23 
     | 
    
         
            +
            ```
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ## 使い方
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            #### シグネチャの設定
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            `stitcher` は定義したメソッドか、次に定義するメソッドに対してシグネチャを設定することで使用します。
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 32 
     | 
    
         
            +
            require "stitcher"
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            # using することで Module クラスに Stitcher の機能が mixin される
         
     | 
| 
      
 35 
     | 
    
         
            +
            using Stitcher
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            class Counter
         
     | 
| 
      
 39 
     | 
    
         
            +
            	attr_reader :value
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            	def initialize value
         
     | 
| 
      
 42 
     | 
    
         
            +
            		@value = value
         
     | 
| 
      
 43 
     | 
    
         
            +
            	end
         
     | 
| 
      
 44 
     | 
    
         
            +
            	# 既存のメソッドに対して引数のシグネチャを設定する
         
     | 
| 
      
 45 
     | 
    
         
            +
            	# #initialize メソッドに対して Fixnum クラスのインスタンスのみ受け取るようにする
         
     | 
| 
      
 46 
     | 
    
         
            +
            	stitcher_register :initialize, [Fixnum]
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            	# stitcher_register を使用することで次に定義するメソッドに対しての
         
     | 
| 
      
 49 
     | 
    
         
            +
            	# シグネチャを設定することもできる
         
     | 
| 
      
 50 
     | 
    
         
            +
            	# stitcher_register の第二引数と stitcher_require の第一引数は同じである
         
     | 
| 
      
 51 
     | 
    
         
            +
            	stitcher_require [Fixnum]
         
     | 
| 
      
 52 
     | 
    
         
            +
            	# add メソッドは Fixnum のインスタンスのみ受け付ける
         
     | 
| 
      
 53 
     | 
    
         
            +
            	def add value
         
     | 
| 
      
 54 
     | 
    
         
            +
            		@value += value
         
     | 
| 
      
 55 
     | 
    
         
            +
            	end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            	# また、違うシグネチャを設定することにより複数のメソッドを定義する事ができる
         
     | 
| 
      
 58 
     | 
    
         
            +
            	stitcher_require [String]
         
     | 
| 
      
 59 
     | 
    
         
            +
            	def add str
         
     | 
| 
      
 60 
     | 
    
         
            +
            		@value += str.to_i
         
     | 
| 
      
 61 
     | 
    
         
            +
            	end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            count = Counter.new 0		# OK
         
     | 
| 
      
 65 
     | 
    
         
            +
            # count = Counter.new ""	# Error: Fixnum クラスのインスタンスではない
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            count.add 10				# OK
         
     | 
| 
      
 68 
     | 
    
         
            +
            count.add "12"				# OK
         
     | 
| 
      
 69 
     | 
    
         
            +
            # count.add 0.42			# Error
         
     | 
| 
      
 70 
     | 
    
         
            +
            p count.value
         
     | 
| 
      
 71 
     | 
    
         
            +
            # => 22
         
     | 
| 
      
 72 
     | 
    
         
            +
            ```
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 75 
     | 
    
         
            +
            using Stitcher
         
     | 
| 
      
 76 
     | 
    
         
            +
            ```
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            まず、`using` を使用して、特定の範囲でのみ Stitcher を使用することを定義します。  
         
     | 
| 
      
 79 
     | 
    
         
            +
            この時に `Module` クラス内に Stitcher の機能が `mixin` され、いくつかのクラス拡張が適用されます。  
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 82 
     | 
    
         
            +
            def initialize value
         
     | 
| 
      
 83 
     | 
    
         
            +
                @value = value
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
      
 85 
     | 
    
         
            +
            stitcher_register :initialize, [Fixnum]
         
     | 
| 
      
 86 
     | 
    
         
            +
            ```
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            `.stitcher_register` を使用して既存のメソッドに対してシグネチャを設定します。  
         
     | 
| 
      
 89 
     | 
    
         
            +
            この時に設定するシグネチャは各引数に対するリストになります。  
         
     | 
| 
      
 90 
     | 
    
         
            +
            また、各シグネチャと実引数の要素は `#===` を用いて比較が行われ、このメソッドが真を返せばシグネチャにマッチしたと認識されます。 
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 93 
     | 
    
         
            +
            stitcher_require [Fixnum]
         
     | 
| 
      
 94 
     | 
    
         
            +
            def add value
         
     | 
| 
      
 95 
     | 
    
         
            +
                @value += value
         
     | 
| 
      
 96 
     | 
    
         
            +
            end
         
     | 
| 
      
 97 
     | 
    
         
            +
            ```
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            `.stitcher_require` を使用して、次に定義されるメソッドに対してのシグネチャを設定します。  
         
     | 
| 
      
 100 
     | 
    
         
            +
            設定するシグネチャは `.stitcher_register` と同じです。 
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 103 
     | 
    
         
            +
            stitcher_require [String]
         
     | 
| 
      
 104 
     | 
    
         
            +
            def add str
         
     | 
| 
      
 105 
     | 
    
         
            +
                @value += str.to_i
         
     | 
| 
      
 106 
     | 
    
         
            +
            end
         
     | 
| 
      
 107 
     | 
    
         
            +
            ```
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            違うシグネチャを設定することで静的型付け言語のような多重定義を行うことができます。  
         
     | 
| 
      
 110 
     | 
    
         
            +
            これにより『引数のクラス』によって簡単に処理を分岐することができます。
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            #### シグネチャの設定
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            各引数のシグネチャは `#===` が定義されてるオブジェクトであればなんでも設定する事ができます。  
         
     | 
| 
      
 115 
     | 
    
         
            +
            これは Ruby の `case` 文と似ています。
         
     | 
| 
      
 116 
     | 
    
         
            +
            例えば、`Class` 以外にも `Proc` や `Regexp` などを渡すことができます。
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 119 
     | 
    
         
            +
            class Http
         
     | 
| 
      
 120 
     | 
    
         
            +
            	stitcher_require [/^https?/]
         
     | 
| 
      
 121 
     | 
    
         
            +
            	def post url
         
     | 
| 
      
 122 
     | 
    
         
            +
            		# ...
         
     | 
| 
      
 123 
     | 
    
         
            +
            	end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
            	stitcher_require [ proc { |hash| (Hash === hash && hash.key?(:url)) } ]
         
     | 
| 
      
 126 
     | 
    
         
            +
            	def post hash
         
     | 
| 
      
 127 
     | 
    
         
            +
            		post hash[:url]
         
     | 
| 
      
 128 
     | 
    
         
            +
            	end
         
     | 
| 
      
 129 
     | 
    
         
            +
            end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            http = Http.new
         
     | 
| 
      
 132 
     | 
    
         
            +
            http.post "http://docs.ruby-lang.org/"				# OK
         
     | 
| 
      
 133 
     | 
    
         
            +
            http.post({ url: "http://docs.ruby-lang.org/" })	# OK
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            http.post "ftp://docs.ruby-lang.org/"				# Error
         
     | 
| 
      
 136 
     | 
    
         
            +
            http.post({ uri: "http://docs.ruby-lang.org/" })	# Error
         
     | 
| 
      
 137 
     | 
    
         
            +
            ```
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            このようにしてより厳密な引数に対する要求を設定することができます。  
         
     | 
| 
      
 140 
     | 
    
         
            +
            また、`Class` や `Proc`、`Regexp` は `&` や `|` で結合することもできます。
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 143 
     | 
    
         
            +
            # Hash であることと Proc の条件を満たすことを要求する
         
     | 
| 
      
 144 
     | 
    
         
            +
            stitcher_require [Hash & proc { |hash| (hash.key?(:url)) } ]
         
     | 
| 
      
 145 
     | 
    
         
            +
            def post hash
         
     | 
| 
      
 146 
     | 
    
         
            +
                post hash[:url]
         
     | 
| 
      
 147 
     | 
    
         
            +
            end
         
     | 
| 
      
 148 
     | 
    
         
            +
            ```
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
            #### 多重定義字に呼び出されるメソッドの優先順位
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
            Stitcehr を利用してメソッドを多重定義した場合に呼び出されるメソッドの優先順位は __下から順に優先順位が高くなります。__  
         
     | 
| 
      
 153 
     | 
    
         
            +
            例えば、次のような定義の場合、
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 156 
     | 
    
         
            +
            require "stitcher"
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            using Stitcher
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            class X
         
     | 
| 
      
 161 
     | 
    
         
            +
            	stitcher_require [Fixnum]
         
     | 
| 
      
 162 
     | 
    
         
            +
            	def func value
         
     | 
| 
      
 163 
     | 
    
         
            +
            		"Fixnum"
         
     | 
| 
      
 164 
     | 
    
         
            +
            	end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
            	stitcher_require [Numeric]
         
     | 
| 
      
 167 
     | 
    
         
            +
            	def func value
         
     | 
| 
      
 168 
     | 
    
         
            +
            		"Numeric"
         
     | 
| 
      
 169 
     | 
    
         
            +
            	end
         
     | 
| 
      
 170 
     | 
    
         
            +
            end
         
     | 
| 
      
 171 
     | 
    
         
            +
            ```
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
            あとから定義されている `func(Numeric)` の方が優先順位が高くなり、
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
            ```
         
     | 
| 
      
 176 
     | 
    
         
            +
            x = X.new
         
     | 
| 
      
 177 
     | 
    
         
            +
            x.func 10     # Numeric === 10 # => true
         
     | 
| 
      
 178 
     | 
    
         
            +
            ```
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
            というような呼び出しの場合は、`Numeric#===` がどちらも真となるため、`func(Fixnum)` ではなくて `func(Numeric)` が呼び出されます。  
         
     | 
| 
      
 181 
     | 
    
         
            +
            これは次のように `Fixnum` にマッチしないようにすることで回避することは可能です。
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 184 
     | 
    
         
            +
            require "stitcher"
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
            using Stitcher
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
            class X
         
     | 
| 
      
 189 
     | 
    
         
            +
            	stitcher_require [Fixnum]
         
     | 
| 
      
 190 
     | 
    
         
            +
            	def func value
         
     | 
| 
      
 191 
     | 
    
         
            +
            		"Fixnum"
         
     | 
| 
      
 192 
     | 
    
         
            +
            	end
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
            	# Numeric であり、Fixnum 以外にマッチする場合のシグネチャ
         
     | 
| 
      
 195 
     | 
    
         
            +
            	stitcher_require [Numeric & !Fixnum]
         
     | 
| 
      
 196 
     | 
    
         
            +
            	def func value
         
     | 
| 
      
 197 
     | 
    
         
            +
            		"Numeric"
         
     | 
| 
      
 198 
     | 
    
         
            +
            	end
         
     | 
| 
      
 199 
     | 
    
         
            +
            end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
            x = X.new
         
     | 
| 
      
 202 
     | 
    
         
            +
            p x.func 10
         
     | 
| 
      
 203 
     | 
    
         
            +
            # => "Fixnum"
         
     | 
| 
      
 204 
     | 
    
         
            +
            p x.func 0.42
         
     | 
| 
      
 205 
     | 
    
         
            +
            # => "Numeric"
         
     | 
| 
      
 206 
     | 
    
         
            +
            ```
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
    
        data/docs/type.md
    ADDED
    
    | 
         @@ -0,0 +1,212 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Ruby の型
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## やりたいこと
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * Ruby で型を定義する
         
     | 
| 
      
 6 
     | 
    
         
            +
             * 現状は Class = 型とする
         
     | 
| 
      
 7 
     | 
    
         
            +
            * 型チェックを行う仕組み
         
     | 
| 
      
 8 
     | 
    
         
            +
            * ジェネリックプログラミングや Variant 型(Haskell の Either みたいなの?)の定義
         
     | 
| 
      
 9 
     | 
    
         
            +
             * C++ の template みたいなのもほしい
         
     | 
| 
      
 10 
     | 
    
         
            +
            * 型によって処理を切り替える装置
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## 動作イメージ
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            #### 型の定義
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 17 
     | 
    
         
            +
            # To type
         
     | 
| 
      
 18 
     | 
    
         
            +
            1.type  # => Fixnum
         
     | 
| 
      
 19 
     | 
    
         
            +
            "".type # => String
         
     | 
| 
      
 20 
     | 
    
         
            +
            String.type # == String
         
     | 
| 
      
 21 
     | 
    
         
            +
            ```
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 24 
     | 
    
         
            +
            # Variant type
         
     | 
| 
      
 25 
     | 
    
         
            +
            (String | Fixnum) # => String or Fixnum
         
     | 
| 
      
 26 
     | 
    
         
            +
            (String | Fixnum | Hash) # => String or Fixnum or Hahs
         
     | 
| 
      
 27 
     | 
    
         
            +
            ```
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 30 
     | 
    
         
            +
            # Super class type
         
     | 
| 
      
 31 
     | 
    
         
            +
            +Numeric # => Numeric is super class type
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            # No type
         
     | 
| 
      
 34 
     | 
    
         
            +
            !Numerci # => Not Numeric type
         
     | 
| 
      
 35 
     | 
    
         
            +
            ```
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            ##### 型の比較
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 40 
     | 
    
         
            +
            1.type == Fixnum  # => true
         
     | 
| 
      
 41 
     | 
    
         
            +
            1.type == String  # => false
         
     | 
| 
      
 42 
     | 
    
         
            +
            1.type <= Numeric # => true
         
     | 
| 
      
 43 
     | 
    
         
            +
            1.type == Numeric # => false
         
     | 
| 
      
 44 
     | 
    
         
            +
            ```
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 47 
     | 
    
         
            +
            # Type1 | Type2 => Variant type
         
     | 
| 
      
 48 
     | 
    
         
            +
            (String | Fixnum) == 1  # true
         
     | 
| 
      
 49 
     | 
    
         
            +
            (String | Fixnum) == "" # true
         
     | 
| 
      
 50 
     | 
    
         
            +
            (String | Fixnum) == {} # false
         
     | 
| 
      
 51 
     | 
    
         
            +
            ```
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            #### 型変数の定義
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 57 
     | 
    
         
            +
            let :name, String
         
     | 
| 
      
 58 
     | 
    
         
            +
            self.name = "" # OK
         
     | 
| 
      
 59 
     | 
    
         
            +
            self.name = 42 # Error
         
     | 
| 
      
 60 
     | 
    
         
            +
            ```
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 64 
     | 
    
         
            +
            let :data, String | Numeric # Variant 型
         
     | 
| 
      
 65 
     | 
    
         
            +
            self.data = "" # OK
         
     | 
| 
      
 66 
     | 
    
         
            +
            self.data = 42 # OK
         
     | 
| 
      
 67 
     | 
    
         
            +
            self.data = {} # Error
         
     | 
| 
      
 68 
     | 
    
         
            +
            ```
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 72 
     | 
    
         
            +
            let :bool, True | False # Variant 型
         
     | 
| 
      
 73 
     | 
    
         
            +
            self.bool = true  # OK
         
     | 
| 
      
 74 
     | 
    
         
            +
            self.bool = false # OK
         
     | 
| 
      
 75 
     | 
    
         
            +
            self.bool = nil # Error
         
     | 
| 
      
 76 
     | 
    
         
            +
            ```
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 80 
     | 
    
         
            +
            class X
         
     | 
| 
      
 81 
     | 
    
         
            +
              let name: String, age: Numeric
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
      
 83 
     | 
    
         
            +
            x = X.new
         
     | 
| 
      
 84 
     | 
    
         
            +
            x.name = "homu" # OK
         
     | 
| 
      
 85 
     | 
    
         
            +
            x.age = 13 # OK
         
     | 
| 
      
 86 
     | 
    
         
            +
            x.name 13 # Error
         
     | 
| 
      
 87 
     | 
    
         
            +
            ```
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            ## 悩み
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            型同士の比較をどうするか考える
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            1.type # => Fixnum
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            1.type ==  Numeric # => Fixnum ==  Numeric
         
     | 
| 
      
 96 
     | 
    
         
            +
            1.type <=  Numeric # => Fixnum <=  Numeric
         
     | 
| 
      
 97 
     | 
    
         
            +
            1.type === Numeric # => Fixnum === Numeric
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            1.type ==  +Numeric # => Fixnum == Numeric
         
     | 
| 
      
 100 
     | 
    
         
            +
            1.type <=  +Numeric # => Fixnum <= Numeric
         
     | 
| 
      
 101 
     | 
    
         
            +
            1.type === +Numeric # => Fixnum <= Numeric
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            1.type ==  !Numeric # => Fixnum == Numeric
         
     | 
| 
      
 104 
     | 
    
         
            +
            1.type !=  !Numeric # => Fixnum != Numeric
         
     | 
| 
      
 105 
     | 
    
         
            +
            1.type === !Numeric # => Fixnum != Numeric
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            class A
         
     | 
| 
      
 112 
     | 
    
         
            +
            	def == rhs
         
     | 
| 
      
 113 
     | 
    
         
            +
            		p "A#== #{rhs.class}"
         
     | 
| 
      
 114 
     | 
    
         
            +
            	end
         
     | 
| 
      
 115 
     | 
    
         
            +
            end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            class B
         
     | 
| 
      
 118 
     | 
    
         
            +
            	def == rhs
         
     | 
| 
      
 119 
     | 
    
         
            +
            		p "B#== #{rhs.class}"
         
     | 
| 
      
 120 
     | 
    
         
            +
            	end
         
     | 
| 
      
 121 
     | 
    
         
            +
            end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
            class A
         
     | 
| 
      
 124 
     | 
    
         
            +
            	prepend(Module.new do
         
     | 
| 
      
 125 
     | 
    
         
            +
            		define_method(:==) do |rhs|
         
     | 
| 
      
 126 
     | 
    
         
            +
            			rhs.class == B ? rhs == self : super(rhs)
         
     | 
| 
      
 127 
     | 
    
         
            +
            		end
         
     | 
| 
      
 128 
     | 
    
         
            +
            	end)
         
     | 
| 
      
 129 
     | 
    
         
            +
            end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            class C
         
     | 
| 
      
 133 
     | 
    
         
            +
            	
         
     | 
| 
      
 134 
     | 
    
         
            +
            end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            A.new == B.new
         
     | 
| 
      
 137 
     | 
    
         
            +
            A.new == C.new
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            class A
         
     | 
| 
      
 142 
     | 
    
         
            +
            	def == rhs
         
     | 
| 
      
 143 
     | 
    
         
            +
            		if rhs.respond_to? :callable_equal
         
     | 
| 
      
 144 
     | 
    
         
            +
            			rhs.callable_equal(self)
         
     | 
| 
      
 145 
     | 
    
         
            +
            		else
         
     | 
| 
      
 146 
     | 
    
         
            +
            			p "A#== #{rhs.class}"
         
     | 
| 
      
 147 
     | 
    
         
            +
            		end
         
     | 
| 
      
 148 
     | 
    
         
            +
            	end
         
     | 
| 
      
 149 
     | 
    
         
            +
            end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
            class B
         
     | 
| 
      
 152 
     | 
    
         
            +
            	def callable_equal rhs
         
     | 
| 
      
 153 
     | 
    
         
            +
            		p "B#== #{rhs.class}"
         
     | 
| 
      
 154 
     | 
    
         
            +
            	end
         
     | 
| 
      
 155 
     | 
    
         
            +
            end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
            class C
         
     | 
| 
      
 158 
     | 
    
         
            +
            	
         
     | 
| 
      
 159 
     | 
    
         
            +
            end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
            A.new == B.new
         
     | 
| 
      
 162 
     | 
    
         
            +
            A.new == C.new
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
            class A
         
     | 
| 
      
 167 
     | 
    
         
            +
            	def == rhs
         
     | 
| 
      
 168 
     | 
    
         
            +
            		p "A#== #{rhs.class}"
         
     | 
| 
      
 169 
     | 
    
         
            +
            	end
         
     | 
| 
      
 170 
     | 
    
         
            +
            end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
            class B
         
     | 
| 
      
 173 
     | 
    
         
            +
            	def == rhs
         
     | 
| 
      
 174 
     | 
    
         
            +
            		p "B#== #{rhs.class}"
         
     | 
| 
      
 175 
     | 
    
         
            +
            	end
         
     | 
| 
      
 176 
     | 
    
         
            +
            end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            class A
         
     | 
| 
      
 179 
     | 
    
         
            +
            	prepend(Module.new do
         
     | 
| 
      
 180 
     | 
    
         
            +
            		define_method(:==) do |rhs|
         
     | 
| 
      
 181 
     | 
    
         
            +
            			rhs.class == B ? rhs == self : super(rhs)
         
     | 
| 
      
 182 
     | 
    
         
            +
            		end
         
     | 
| 
      
 183 
     | 
    
         
            +
            	end)
         
     | 
| 
      
 184 
     | 
    
         
            +
            end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
            class C
         
     | 
| 
      
 188 
     | 
    
         
            +
            	
         
     | 
| 
      
 189 
     | 
    
         
            +
            end
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
            class D
         
     | 
| 
      
 192 
     | 
    
         
            +
            	def == rhs
         
     | 
| 
      
 193 
     | 
    
         
            +
            		p "D#== #{rhs.class}"
         
     | 
| 
      
 194 
     | 
    
         
            +
            	end
         
     | 
| 
      
 195 
     | 
    
         
            +
            end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
            class A
         
     | 
| 
      
 198 
     | 
    
         
            +
            	prepend(Module.new do
         
     | 
| 
      
 199 
     | 
    
         
            +
            		define_method(:==) do |rhs|
         
     | 
| 
      
 200 
     | 
    
         
            +
            			rhs.class == D ? rhs == self : super(rhs)
         
     | 
| 
      
 201 
     | 
    
         
            +
            		end
         
     | 
| 
      
 202 
     | 
    
         
            +
            	end)
         
     | 
| 
      
 203 
     | 
    
         
            +
            end
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
            A.new == Object.new
         
     | 
| 
      
 207 
     | 
    
         
            +
            A.new == A.new
         
     | 
| 
      
 208 
     | 
    
         
            +
            A.new == B.new
         
     | 
| 
      
 209 
     | 
    
         
            +
            A.new == C.new
         
     | 
| 
      
 210 
     | 
    
         
            +
            A.new == D.new
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
             
     |