callable_tree 0.1.1 → 0.2.1
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 +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +2 -2
- data/README.md +137 -59
- data/callable_tree.gemspec +3 -3
- data/examples/{example2.rb → external-verbosify.rb} +0 -0
- data/examples/{example5.rb → hooks-call.rb} +1 -0
- data/examples/{example3.rb → identity.rb} +0 -0
- data/examples/internal-broadcast.rb +31 -0
- data/examples/internal-compose.rb +31 -0
- data/examples/{example1.rb → internal-seek.rb} +0 -0
- data/examples/{example4.rb → logging.rb} +0 -0
- data/lib/callable_tree.rb +3 -2
- data/lib/callable_tree/node.rb +6 -2
- data/lib/callable_tree/node/external.rb +27 -7
- data/lib/callable_tree/node/external/verbose.rb +4 -0
- data/lib/callable_tree/node/internal.rb +49 -17
- data/lib/callable_tree/node/internal/strategy/broadcast.rb +17 -0
- data/lib/callable_tree/node/internal/strategy/compose.rb +21 -0
- data/lib/callable_tree/node/internal/strategy/seek.rb +25 -0
- data/lib/callable_tree/version.rb +1 -1
- metadata +19 -17
- data/examples/example6.rb +0 -101
- data/lib/callable_tree/node/internal/broadcast.rb +0 -19
- data/lib/callable_tree/node/internal/seek.rb +0 -23
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 23417eaf997718c6d0e9b5fc52dea3fe4923ca9b426d9d41e57b5e27015d239a
         | 
| 4 | 
            +
              data.tar.gz: 34be74baf1014e41efbe0073fedfdf76dc02444c927bea2b089d9457842c04b8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 686e18552c5decad326d7bd0775a2be0b3726245edea1ccf2dbdf0ca3e264ec88883bf79cea5af873b074feff1b63e49b59522b5f3b7fc00e06122d494277cea
         | 
| 7 | 
            +
              data.tar.gz: 7db8a88a1bc19677f453237dd15137da05f3fdb2ddb25aeedd11df82e6afd7c769d3da3c61e9905c40285d35ea54059c6749b4f32a354fc542d7bd26fdd8992f
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,25 @@ | |
| 1 1 | 
             
            ## [Unreleased]
         | 
| 2 2 |  | 
| 3 | 
            +
            ## [0.2.1] - 2021-07-24
         | 
| 4 | 
            +
            - Add `CallableTree::Node::root?`.
         | 
| 5 | 
            +
            - Add `CallableTree::Node::Internal#seek!` that make destructive change.
         | 
| 6 | 
            +
            - Add `CallableTree::Node::Internal#broadcast!` that make destructive change.
         | 
| 7 | 
            +
            - Add `CallableTree::Node::Internal#compose!` that make destructive change.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## [0.2.0] - 2021-06-15
         | 
| 10 | 
            +
            - Change `CallableTree::Node::Internal#append` to return a new instance.
         | 
| 11 | 
            +
              To keep the same behavior as the older version, use `CallableTree::Node::External#append!` that make destructive change.
         | 
| 12 | 
            +
            - Remove `CallableTree::Node::Internal#<<`. Use `CallableTree::Node::External#append!` instead.
         | 
| 13 | 
            +
            - Change `CallableTree::Node::External#verbosify` to return a new instance.
         | 
| 14 | 
            +
              To keep the same behavior as the older version, use `CallableTree::Node::External#verbosify!` that make destructive change.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ## [0.1.3] - 2021-06-12
         | 
| 17 | 
            +
            - Minor improvements
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ## [0.1.2] - 2021-05-29
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            - Add `CallableTree::Node::Internal#compose` (experimental)
         | 
| 22 | 
            +
             | 
| 3 23 | 
             
            ## [0.1.1] - 2021-05-27
         | 
| 4 24 |  | 
| 5 25 | 
             
            - Add `CallableTree::Node::Internal#broadcast` (experimental)
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                callable_tree (0. | 
| 4 | 
            +
                callable_tree (0.2.1)
         | 
| 5 5 |  | 
| 6 6 | 
             
            GEM
         | 
| 7 7 | 
             
              remote: https://rubygems.org/
         | 
| 8 8 | 
             
              specs:
         | 
| 9 9 | 
             
                diff-lcs (1.4.4)
         | 
| 10 | 
            -
                rake (13.0. | 
| 10 | 
            +
                rake (13.0.6)
         | 
| 11 11 | 
             
                rspec (3.10.0)
         | 
| 12 12 | 
             
                  rspec-core (~> 3.10.0)
         | 
| 13 13 | 
             
                  rspec-expectations (~> 3.10.0)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -18,19 +18,22 @@ Or install it yourself as: | |
| 18 18 |  | 
| 19 19 | 
             
            ## Usage
         | 
| 20 20 |  | 
| 21 | 
            +
            Builds a tree by linking instances of the nodes. The `call` method of the node where the `match?` method returns a truthy value is called in a chain from the root node to the leaf node.
         | 
| 22 | 
            +
             | 
| 21 23 | 
             
            - `CallableTree::Node::Internal`
         | 
| 22 | 
            -
              - This `module` is used to define a node that can have child nodes.
         | 
| 24 | 
            +
              - This `module` is used to define a node that can have child nodes. An instance of this node has several strategies. The strategy can be changed by calling the method of the instance.
         | 
| 23 25 | 
             
            - `CallableTree::Node::External`
         | 
| 24 26 | 
             
              - This `module` is used to define a leaf node that cannot have child nodes.
         | 
| 25 27 | 
             
            - `CallableTree::Node::Root`
         | 
| 26 28 | 
             
              - This `class` includes `CallableTree::Node::Internal`. When there is no need to customize the internal node, use this `class`.
         | 
| 27 29 |  | 
| 28 | 
            -
            Builds a tree by linking instances of the nodes. The `call` method of the node where the `match?` method returns a truthy value is called in a chain from the root node to the leaf node.
         | 
| 29 | 
            -
            If the `call` method returns a value other than `nil`, the next sibling node does not be called. This behavior is changeable by overriding the `terminate?` method.
         | 
| 30 | 
            -
             | 
| 31 30 | 
             
            ### Basic
         | 
| 32 31 |  | 
| 33 | 
            -
            ` | 
| 32 | 
            +
            #### `CallableTree::Node::Internal#seek` (default)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            This strategy does not call the next sibling node if the `call` method of the current node returns a value other than `nil`. This behavior is changeable by overriding the `terminate?` method.
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            `examples/internal-seek.rb`:
         | 
| 34 37 | 
             
            ```ruby
         | 
| 35 38 | 
             
            module Node
         | 
| 36 39 | 
             
              module JSON
         | 
| @@ -123,16 +126,17 @@ module Node | |
| 123 126 | 
             
              end
         | 
| 124 127 | 
             
            end
         | 
| 125 128 |  | 
| 129 | 
            +
            # The `seek` method call can be omitted since it is the default strategy.
         | 
| 126 130 | 
             
            tree = CallableTree::Node::Root.new.append(
         | 
| 127 131 | 
             
              Node::JSON::Parser.new.append(
         | 
| 128 132 | 
             
                Node::JSON::Scraper.new(type: :animals),
         | 
| 129 133 | 
             
                Node::JSON::Scraper.new(type: :fruits)
         | 
| 130 | 
            -
              ),
         | 
| 134 | 
            +
              ),#.seek,
         | 
| 131 135 | 
             
              Node::XML::Parser.new.append(
         | 
| 132 136 | 
             
                Node::XML::Scraper.new(type: :animals),
         | 
| 133 137 | 
             
                Node::XML::Scraper.new(type: :fruits)
         | 
| 134 | 
            -
              )
         | 
| 135 | 
            -
            )
         | 
| 138 | 
            +
              )#.seek
         | 
| 139 | 
            +
            )#.seek
         | 
| 136 140 |  | 
| 137 141 | 
             
            Dir.glob(__dir__ + '/docs/*') do |file|
         | 
| 138 142 | 
             
              options = { foo: :bar }
         | 
| @@ -141,9 +145,9 @@ Dir.glob(__dir__ + '/docs/*') do |file| | |
| 141 145 | 
             
            end
         | 
| 142 146 | 
             
            ```
         | 
| 143 147 |  | 
| 144 | 
            -
            Run `examples/ | 
| 148 | 
            +
            Run `examples/internal-seek.rb`:
         | 
| 145 149 | 
             
            ```sh
         | 
| 146 | 
            -
            % ruby examples/ | 
| 150 | 
            +
            % ruby examples/internal-seek.rb
         | 
| 147 151 | 
             
            {"Dog"=>"🐶", "Cat"=>"🐱"}
         | 
| 148 152 | 
             
            ---
         | 
| 149 153 | 
             
            {"Dog"=>"🐶", "Cat"=>"🐱"}
         | 
| @@ -154,13 +158,121 @@ Run `examples/example1.rb`: | |
| 154 158 | 
             
            ---
         | 
| 155 159 | 
             
            ```
         | 
| 156 160 |  | 
| 161 | 
            +
            #### `CallableTree::Node::Internal#broadcast`
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            This strategy calls all child nodes of the internal node and ignores their `terminate?` methods, and then outputs their results as array.
         | 
| 164 | 
            +
             | 
| 165 | 
            +
            `examples/internal-broadcast.rb`:
         | 
| 166 | 
            +
            ```ruby
         | 
| 167 | 
            +
            module Node
         | 
| 168 | 
            +
              class LessThan
         | 
| 169 | 
            +
                include CallableTree::Node::Internal
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                def initialize(num)
         | 
| 172 | 
            +
                  @num = num
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                def match?(input)
         | 
| 176 | 
            +
                  super && input < @num
         | 
| 177 | 
            +
                end
         | 
| 178 | 
            +
              end
         | 
| 179 | 
            +
            end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
            tree = CallableTree::Node::Root.new.append(
         | 
| 182 | 
            +
              Node::LessThan.new(5).append(
         | 
| 183 | 
            +
                lambda { |input, **| input * 2 }, # anonymous external node
         | 
| 184 | 
            +
                lambda { |input, **| input + 1 }  # anonymous external node
         | 
| 185 | 
            +
              ).broadcast,
         | 
| 186 | 
            +
              Node::LessThan.new(10).append(
         | 
| 187 | 
            +
                lambda { |input, **| input * 3 }, # anonymous external node
         | 
| 188 | 
            +
                lambda { |input, **| input - 1 }  # anonymous external node
         | 
| 189 | 
            +
              ).broadcast
         | 
| 190 | 
            +
            ).broadcast
         | 
| 191 | 
            +
             | 
| 192 | 
            +
            (0..10).each do |input|
         | 
| 193 | 
            +
              output = tree.call(input)
         | 
| 194 | 
            +
              puts "#{input} -> #{output}"
         | 
| 195 | 
            +
            end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            ```
         | 
| 198 | 
            +
             | 
| 199 | 
            +
            Run `examples/internal-broadcast.rb`:
         | 
| 200 | 
            +
            ```sh
         | 
| 201 | 
            +
            % ruby examples/internal-broadcast.rb
         | 
| 202 | 
            +
            0 -> [[0, 1], [0, -1]]
         | 
| 203 | 
            +
            1 -> [[2, 2], [3, 0]]
         | 
| 204 | 
            +
            2 -> [[4, 3], [6, 1]]
         | 
| 205 | 
            +
            3 -> [[6, 4], [9, 2]]
         | 
| 206 | 
            +
            4 -> [[8, 5], [12, 3]]
         | 
| 207 | 
            +
            5 -> [nil, [15, 4]]
         | 
| 208 | 
            +
            6 -> [nil, [18, 5]]
         | 
| 209 | 
            +
            7 -> [nil, [21, 6]]
         | 
| 210 | 
            +
            8 -> [nil, [24, 7]]
         | 
| 211 | 
            +
            9 -> [nil, [27, 8]]
         | 
| 212 | 
            +
            10 -> [nil, nil]
         | 
| 213 | 
            +
            ```
         | 
| 214 | 
            +
             | 
| 215 | 
            +
            #### `CallableTree::Node::Internal#compose`
         | 
| 216 | 
            +
             | 
| 217 | 
            +
            This strategy calls all child nodes of the internal node in order to input the output of the previous node to the next node and ignores their `terminate?` methods, and then outputs a single result.
         | 
| 218 | 
            +
             | 
| 219 | 
            +
            `examples/internal-compose.rb`:
         | 
| 220 | 
            +
            ```ruby
         | 
| 221 | 
            +
            module Node
         | 
| 222 | 
            +
              class LessThan
         | 
| 223 | 
            +
                include CallableTree::Node::Internal
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                def initialize(num)
         | 
| 226 | 
            +
                  @num = num
         | 
| 227 | 
            +
                end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                def match?(input)
         | 
| 230 | 
            +
                  super && input < @num
         | 
| 231 | 
            +
                end
         | 
| 232 | 
            +
              end
         | 
| 233 | 
            +
            end
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            tree = CallableTree::Node::Root.new.append(
         | 
| 236 | 
            +
              Node::LessThan.new(5).append(
         | 
| 237 | 
            +
                proc { |input| input * 2 }, # anonymous external node
         | 
| 238 | 
            +
                proc { |input| input + 1 }  # anonymous external node
         | 
| 239 | 
            +
              ).compose,
         | 
| 240 | 
            +
              Node::LessThan.new(10).append(
         | 
| 241 | 
            +
                proc { |input| input * 3 }, # anonymous external node
         | 
| 242 | 
            +
                proc { |input| input - 1 }  # anonymous external node
         | 
| 243 | 
            +
              ).compose
         | 
| 244 | 
            +
            ).compose
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            (0..10).each do |input|
         | 
| 247 | 
            +
              output = tree.call(input)
         | 
| 248 | 
            +
              puts "#{input} -> #{output}"
         | 
| 249 | 
            +
            end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
            ```
         | 
| 252 | 
            +
             | 
| 253 | 
            +
            Run `examples/internal-compose.rb`:
         | 
| 254 | 
            +
            ```sh
         | 
| 255 | 
            +
            % ruby examples/internal-compose.rb
         | 
| 256 | 
            +
            0 -> 2
         | 
| 257 | 
            +
            1 -> 8
         | 
| 258 | 
            +
            2 -> 14
         | 
| 259 | 
            +
            3 -> 20
         | 
| 260 | 
            +
            4 -> 26
         | 
| 261 | 
            +
            5 -> 14
         | 
| 262 | 
            +
            6 -> 17
         | 
| 263 | 
            +
            7 -> 20
         | 
| 264 | 
            +
            8 -> 23
         | 
| 265 | 
            +
            9 -> 26
         | 
| 266 | 
            +
            10 -> 10
         | 
| 267 | 
            +
            ```
         | 
| 268 | 
            +
             | 
| 157 269 | 
             
            ### Advanced
         | 
| 158 270 |  | 
| 159 271 | 
             
            #### `CallableTree::Node::External#verbosify`
         | 
| 160 272 |  | 
| 161 | 
            -
            If you want verbose  | 
| 273 | 
            +
            If you want verbose output results, call this method.
         | 
| 162 274 |  | 
| 163 | 
            -
            `examples/ | 
| 275 | 
            +
            `examples/external-verbosify.rb`:
         | 
| 164 276 | 
             
            ```ruby
         | 
| 165 277 | 
             
            ...
         | 
| 166 278 |  | 
| @@ -178,9 +290,9 @@ tree = CallableTree::Node::Root.new.append( | |
| 178 290 | 
             
            ...
         | 
| 179 291 | 
             
            ```
         | 
| 180 292 |  | 
| 181 | 
            -
            Run `examples/ | 
| 293 | 
            +
            Run `examples/external-verbosify.rb`:
         | 
| 182 294 | 
             
            ```sh
         | 
| 183 | 
            -
            % ruby examples/ | 
| 295 | 
            +
            % ruby examples/external-verbosify.rb
         | 
| 184 296 | 
             
            #<struct CallableTree::Node::External::Output
         | 
| 185 297 | 
             
             value={"Dog"=>"🐶", "Cat"=>"🐱"},
         | 
| 186 298 | 
             
             options={:foo=>:bar},
         | 
| @@ -208,9 +320,9 @@ You can work around it by overriding the `identity` method of the node. | |
| 208 320 |  | 
| 209 321 | 
             
            #### `CallableTree::Node#identity`
         | 
| 210 322 |  | 
| 211 | 
            -
            If you want to customize the node identity, override  | 
| 323 | 
            +
            If you want to customize the node identity, override this method.
         | 
| 212 324 |  | 
| 213 | 
            -
            `examples/ | 
| 325 | 
            +
            `examples/identity.rb`:
         | 
| 214 326 | 
             
            ```ruby
         | 
| 215 327 | 
             
            module Node
         | 
| 216 328 | 
             
              class Identity
         | 
| @@ -266,9 +378,9 @@ end | |
| 266 378 | 
             
            ...
         | 
| 267 379 | 
             
            ```
         | 
| 268 380 |  | 
| 269 | 
            -
            Run `examples/ | 
| 381 | 
            +
            Run `examples/identity.rb`:
         | 
| 270 382 | 
             
            ```sh
         | 
| 271 | 
            -
            % ruby examples/ | 
| 383 | 
            +
            % ruby examples/identity.rb
         | 
| 272 384 | 
             
            #<struct CallableTree::Node::External::Output
         | 
| 273 385 | 
             
             value={"Dog"=>"🐶", "Cat"=>"🐱"},
         | 
| 274 386 | 
             
             options={:foo=>:bar},
         | 
| @@ -315,7 +427,7 @@ Run `examples/example3.rb`: | |
| 315 427 |  | 
| 316 428 | 
             
            This is an example of logging.
         | 
| 317 429 |  | 
| 318 | 
            -
            `examples/ | 
| 430 | 
            +
            `examples/logging.rb`:
         | 
| 319 431 | 
             
            ```ruby
         | 
| 320 432 | 
             
            module Node
         | 
| 321 433 | 
             
              module Logging
         | 
| @@ -388,9 +500,9 @@ end | |
| 388 500 | 
             
            ...
         | 
| 389 501 | 
             
            ```
         | 
| 390 502 |  | 
| 391 | 
            -
            Run `examples/ | 
| 503 | 
            +
            Run `examples/logging.rb`:
         | 
| 392 504 | 
             
            ```sh
         | 
| 393 | 
            -
            % ruby examples/ | 
| 505 | 
            +
            % ruby examples/logging.rb
         | 
| 394 506 | 
             
            * Node::JSON::Parser: [matched: true]
         | 
| 395 507 | 
             
              * Node::JSON::Scraper(animals): [matched: true]
         | 
| 396 508 | 
             
                Input : {"animals"=>[{"name"=>"Dog", "emoji"=>"🐶"}, {"name"=>"Cat", "emoji"=>"🐱"}]}
         | 
| @@ -455,7 +567,7 @@ Run `examples/example4.rb`: | |
| 455 567 |  | 
| 456 568 | 
             
            #### `CallableTree::Node::Hooks::Call` (experimental)
         | 
| 457 569 |  | 
| 458 | 
            -
            `examples/ | 
| 570 | 
            +
            `examples/hooks-call.rb`:
         | 
| 459 571 | 
             
            ```ruby
         | 
| 460 572 | 
             
            module Node
         | 
| 461 573 | 
             
              class HooksSample
         | 
| @@ -470,6 +582,7 @@ Node::HooksSample.new | |
| 470 582 | 
             
                input + 1
         | 
| 471 583 | 
             
              end
         | 
| 472 584 | 
             
              .append(
         | 
| 585 | 
            +
                # anonymous external node
         | 
| 473 586 | 
             
                lambda do |input, **options|
         | 
| 474 587 | 
             
                  puts "external input: #{input}"
         | 
| 475 588 | 
             
                  input * 2
         | 
| @@ -492,9 +605,9 @@ Node::HooksSample.new | |
| 492 605 | 
             
              end
         | 
| 493 606 | 
             
            ```
         | 
| 494 607 |  | 
| 495 | 
            -
            Run `examples/ | 
| 608 | 
            +
            Run `examples/hooks-call.rb`:
         | 
| 496 609 | 
             
            ```sh
         | 
| 497 | 
            -
            % ruby examples/ | 
| 610 | 
            +
            % ruby examples/hooks-call.rb
         | 
| 498 611 | 
             
            before_call input: 1
         | 
| 499 612 | 
             
            external input: 2
         | 
| 500 613 | 
             
            around_call input: 2
         | 
| @@ -503,41 +616,6 @@ after_call output: 8 | |
| 503 616 | 
             
            result: 16
         | 
| 504 617 | 
             
            ```
         | 
| 505 618 |  | 
| 506 | 
            -
            #### `CallableTree::Node::Internal#broadcast` (experimental)
         | 
| 507 | 
            -
             | 
| 508 | 
            -
            If you want to call and output all child nodes of the internal node, call it. Broadcast strategy ignores the `terminate?` method of the child node.
         | 
| 509 | 
            -
             | 
| 510 | 
            -
            `examples/example6.rb`:
         | 
| 511 | 
            -
            ```ruby
         | 
| 512 | 
            -
            ...
         | 
| 513 | 
            -
             | 
| 514 | 
            -
            tree = CallableTree::Node::Root.new.append(
         | 
| 515 | 
            -
              Node::JSON::Parser.new.append(
         | 
| 516 | 
            -
                Node::JSON::Scraper.new(type: :animals),
         | 
| 517 | 
            -
                Node::JSON::Scraper.new(type: :fruits)
         | 
| 518 | 
            -
              ).broadcast,
         | 
| 519 | 
            -
              Node::XML::Parser.new.append(
         | 
| 520 | 
            -
                Node::XML::Scraper.new(type: :animals),
         | 
| 521 | 
            -
                Node::XML::Scraper.new(type: :fruits)
         | 
| 522 | 
            -
              ).broadcast
         | 
| 523 | 
            -
            )
         | 
| 524 | 
            -
             | 
| 525 | 
            -
            ...
         | 
| 526 | 
            -
            ```
         | 
| 527 | 
            -
             | 
| 528 | 
            -
            Run `examples/example6.rb`:
         | 
| 529 | 
            -
            ```sh
         | 
| 530 | 
            -
            % ruby examples/example6.rb
         | 
| 531 | 
            -
            [{"Dog"=>"🐶", "Cat"=>"🐱"}, nil]
         | 
| 532 | 
            -
            ---
         | 
| 533 | 
            -
            [{"Dog"=>"🐶", "Cat"=>"🐱"}, nil]
         | 
| 534 | 
            -
            ---
         | 
| 535 | 
            -
            [nil, {"Red Apple"=>"🍎", "Green Apple"=>"🍏"}]
         | 
| 536 | 
            -
            ---
         | 
| 537 | 
            -
            [nil, {"Red Apple"=>"🍎", "Green Apple"=>"🍏"}]
         | 
| 538 | 
            -
            ---
         | 
| 539 | 
            -
            ```
         | 
| 540 | 
            -
             | 
| 541 619 | 
             
            ## Contributing
         | 
| 542 620 |  | 
| 543 621 | 
             
            Bug reports and pull requests are welcome on GitHub at https://github.com/jsmmr/callable_tree.
         | 
    
        data/callable_tree.gemspec
    CHANGED
    
    | @@ -8,15 +8,15 @@ Gem::Specification.new do |spec| | |
| 8 8 | 
             
              spec.authors       = ['jsmmr']
         | 
| 9 9 | 
             
              spec.email         = ['jsmmr@icloud.com']
         | 
| 10 10 |  | 
| 11 | 
            -
              spec.summary       = 'Builds a tree by linking callable nodes. The nodes that match the  | 
| 12 | 
            -
              spec.description   = 'Builds a tree by linking callable nodes. The nodes that match the  | 
| 11 | 
            +
              spec.summary       = 'Builds a tree by linking callable nodes. The nodes that match the conditions are called in a chain from the root node to the leaf node. These are like nested `if` or `case` expressions.'
         | 
| 12 | 
            +
              spec.description   = 'Builds a tree by linking callable nodes. The nodes that match the conditions are called in a chain from the root node to the leaf node. These are like nested `if` or `case` expressions.'
         | 
| 13 13 | 
             
              spec.homepage      = 'https://github.com/jsmmr/ruby_callable_tree'
         | 
| 14 14 | 
             
              spec.license       = 'MIT'
         | 
| 15 15 | 
             
              spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
         | 
| 16 16 |  | 
| 17 17 | 
             
              spec.metadata['homepage_uri'] = spec.homepage
         | 
| 18 18 | 
             
              spec.metadata['source_code_uri'] = 'https://github.com/jsmmr/ruby_callable_tree'
         | 
| 19 | 
            -
              spec.metadata['changelog_uri'] =  | 
| 19 | 
            +
              spec.metadata['changelog_uri'] = "https://github.com/jsmmr/ruby_callable_tree/blob/v#{spec.version}/CHANGELOG.md"
         | 
| 20 20 |  | 
| 21 21 | 
             
              # Specify which files should be added to the gem when it is released.
         | 
| 22 22 | 
             
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require 'callable_tree'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Node
         | 
| 4 | 
            +
              class LessThan
         | 
| 5 | 
            +
                include CallableTree::Node::Internal
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(num)
         | 
| 8 | 
            +
                  @num = num
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def match?(input)
         | 
| 12 | 
            +
                  super && input < @num
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            tree = CallableTree::Node::Root.new.append(
         | 
| 18 | 
            +
              Node::LessThan.new(5).append(
         | 
| 19 | 
            +
                lambda { |input, **| input * 2 }, # anonymous external node
         | 
| 20 | 
            +
                lambda { |input, **| input + 1 }  # anonymous external node
         | 
| 21 | 
            +
              ).broadcast,
         | 
| 22 | 
            +
              Node::LessThan.new(10).append(
         | 
| 23 | 
            +
                lambda { |input, **| input * 3 }, # anonymous external node
         | 
| 24 | 
            +
                lambda { |input, **| input - 1 }  # anonymous external node
         | 
| 25 | 
            +
              ).broadcast
         | 
| 26 | 
            +
            ).broadcast
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            (0..10).each do |input|
         | 
| 29 | 
            +
              output = tree.call(input)
         | 
| 30 | 
            +
              puts "#{input} -> #{output}"
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require 'callable_tree'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Node
         | 
| 4 | 
            +
              class LessThan
         | 
| 5 | 
            +
                include CallableTree::Node::Internal
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(num)
         | 
| 8 | 
            +
                  @num = num
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def match?(input)
         | 
| 12 | 
            +
                  super && input < @num
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            tree = CallableTree::Node::Root.new.append(
         | 
| 18 | 
            +
              Node::LessThan.new(5).append(
         | 
| 19 | 
            +
                proc { |input| input * 2 }, # anonymous external node
         | 
| 20 | 
            +
                proc { |input| input + 1 }  # anonymous external node
         | 
| 21 | 
            +
              ).compose,
         | 
| 22 | 
            +
              Node::LessThan.new(10).append(
         | 
| 23 | 
            +
                proc { |input| input * 3 }, # anonymous external node
         | 
| 24 | 
            +
                proc { |input| input - 1 }  # anonymous external node
         | 
| 25 | 
            +
              ).compose
         | 
| 26 | 
            +
            ).compose
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            (0..10).each do |input|
         | 
| 29 | 
            +
              output = tree.call(input)
         | 
| 30 | 
            +
              puts "#{input} -> #{output}"
         | 
| 31 | 
            +
            end
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
    
        data/lib/callable_tree.rb
    CHANGED
    
    | @@ -8,8 +8,9 @@ require 'forwardable' | |
| 8 8 | 
             
            require_relative 'callable_tree/version'
         | 
| 9 9 | 
             
            require_relative 'callable_tree/node'
         | 
| 10 10 | 
             
            require_relative 'callable_tree/node/hooks/call'
         | 
| 11 | 
            -
            require_relative 'callable_tree/node/internal/broadcast'
         | 
| 12 | 
            -
            require_relative 'callable_tree/node/internal/seek'
         | 
| 11 | 
            +
            require_relative 'callable_tree/node/internal/strategy/broadcast'
         | 
| 12 | 
            +
            require_relative 'callable_tree/node/internal/strategy/seek'
         | 
| 13 | 
            +
            require_relative 'callable_tree/node/internal/strategy/compose'
         | 
| 13 14 | 
             
            require_relative 'callable_tree/node/external/verbose'
         | 
| 14 15 | 
             
            require_relative 'callable_tree/node/external'
         | 
| 15 16 | 
             
            require_relative 'callable_tree/node/internal'
         | 
    
        data/lib/callable_tree/node.rb
    CHANGED
    
    | @@ -4,12 +4,16 @@ module CallableTree | |
| 4 4 | 
             
              module Node
         | 
| 5 5 | 
             
                attr_reader :parent
         | 
| 6 6 |  | 
| 7 | 
            +
                def root?
         | 
| 8 | 
            +
                  parent.nil?
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 7 11 | 
             
                def ancestors
         | 
| 8 12 | 
             
                  ::Enumerator.new do |y|
         | 
| 9 13 | 
             
                    node = self
         | 
| 10 14 | 
             
                    loop do
         | 
| 11 15 | 
             
                      y << node
         | 
| 12 | 
            -
                      break unless node = node | 
| 16 | 
            +
                      break unless node = node.parent
         | 
| 13 17 | 
             
                    end
         | 
| 14 18 | 
             
                  end
         | 
| 15 19 | 
             
                end
         | 
| @@ -23,7 +27,7 @@ module CallableTree | |
| 23 27 | 
             
                end
         | 
| 24 28 |  | 
| 25 29 | 
             
                def depth
         | 
| 26 | 
            -
                   | 
| 30 | 
            +
                  root? ? 0 : parent.depth + 1
         | 
| 27 31 | 
             
                end
         | 
| 28 32 |  | 
| 29 33 | 
             
                def match?(_input = nil, **_options)
         | 
| @@ -9,38 +9,58 @@ module CallableTree | |
| 9 9 | 
             
                    Proxy.new(callable)
         | 
| 10 10 | 
             
                  end
         | 
| 11 11 |  | 
| 12 | 
            -
                  def  | 
| 13 | 
            -
                     | 
| 12 | 
            +
                  def proxified?
         | 
| 13 | 
            +
                    false
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 | 
            -
                  def  | 
| 17 | 
            -
                     | 
| 16 | 
            +
                  def verbosified?
         | 
| 17 | 
            +
                    false
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| 20 20 | 
             
                  def verbosify
         | 
| 21 | 
            +
                    clone.tap do |node|
         | 
| 22 | 
            +
                      node.extend Verbose
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def verbosify!
         | 
| 21 27 | 
             
                    extend Verbose
         | 
| 22 28 | 
             
                    self
         | 
| 23 29 | 
             
                  end
         | 
| 24 30 |  | 
| 25 31 | 
             
                  def identity
         | 
| 26 | 
            -
                    if  | 
| 27 | 
            -
                       | 
| 32 | 
            +
                    if proxified?
         | 
| 33 | 
            +
                      unproxify
         | 
| 28 34 | 
             
                    else
         | 
| 29 35 | 
             
                      self
         | 
| 30 36 | 
             
                    end
         | 
| 31 37 | 
             
                      .class
         | 
| 32 38 | 
             
                  end
         | 
| 33 39 |  | 
| 40 | 
            +
                  private
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def initialize_copy(_node)
         | 
| 43 | 
            +
                    super
         | 
| 44 | 
            +
                    self.parent = nil
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 34 47 | 
             
                  class Proxy
         | 
| 35 48 | 
             
                    extend ::Forwardable
         | 
| 36 49 | 
             
                    include External
         | 
| 37 50 |  | 
| 38 51 | 
             
                    def_delegators :@callable, :call
         | 
| 39 | 
            -
                    attr_reader :callable
         | 
| 40 52 |  | 
| 41 53 | 
             
                    def initialize(callable)
         | 
| 42 54 | 
             
                      @callable = callable
         | 
| 43 55 | 
             
                    end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    def proxified?
         | 
| 58 | 
            +
                      true
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    def unproxify
         | 
| 62 | 
            +
                      @callable
         | 
| 63 | 
            +
                    end
         | 
| 44 64 | 
             
                  end
         | 
| 45 65 |  | 
| 46 66 | 
             
                  private_constant :Proxy
         | 
| @@ -9,20 +9,17 @@ module CallableTree | |
| 9 9 | 
             
                    @children ||= []
         | 
| 10 10 | 
             
                  end
         | 
| 11 11 |  | 
| 12 | 
            -
                  def  | 
| 13 | 
            -
                     | 
| 14 | 
            -
                       | 
| 15 | 
            -
             | 
| 16 | 
            -
                      else
         | 
| 17 | 
            -
                        External.proxify(callable)
         | 
| 18 | 
            -
                      end
         | 
| 19 | 
            -
                      .tap { |node| node.send(:parent=, self) }
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                    self
         | 
| 12 | 
            +
                  def append(*callables)
         | 
| 13 | 
            +
                    clone.tap do |node|
         | 
| 14 | 
            +
                      node.append!(*callables)
         | 
| 15 | 
            +
                    end
         | 
| 22 16 | 
             
                  end
         | 
| 23 17 |  | 
| 24 | 
            -
                  def append(*callables)
         | 
| 25 | 
            -
                    callables | 
| 18 | 
            +
                  def append!(*callables)
         | 
| 19 | 
            +
                    callables
         | 
| 20 | 
            +
                      .map { |callable| nodeify(callable) }
         | 
| 21 | 
            +
                      .tap { |nodes| children.push(*nodes) } # Use Array#push for Ruby 2.4
         | 
| 22 | 
            +
             | 
| 26 23 | 
             
                    self
         | 
| 27 24 | 
             
                  end
         | 
| 28 25 |  | 
| @@ -35,35 +32,70 @@ module CallableTree | |
| 35 32 | 
             
                  end
         | 
| 36 33 |  | 
| 37 34 | 
             
                  def seek
         | 
| 38 | 
            -
                    if strategy.is_a?(Seek)
         | 
| 35 | 
            +
                    if strategy.is_a?(Strategy::Seek)
         | 
| 39 36 | 
             
                      self
         | 
| 40 37 | 
             
                    else
         | 
| 41 38 | 
             
                      clone.tap do |node|
         | 
| 42 | 
            -
                        node.send(:strategy=, Seek.new)
         | 
| 39 | 
            +
                        node.send(:strategy=, Strategy::Seek.new)
         | 
| 43 40 | 
             
                      end
         | 
| 44 41 | 
             
                    end
         | 
| 45 42 | 
             
                  end
         | 
| 46 43 |  | 
| 44 | 
            +
                  def seek!
         | 
| 45 | 
            +
                    self.strategy = Strategy::Seek.new unless strategy.is_a?(Strategy::Seek)
         | 
| 46 | 
            +
                    self
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 47 49 | 
             
                  def broadcast
         | 
| 48 | 
            -
                    if strategy.is_a?(Broadcast)
         | 
| 50 | 
            +
                    if strategy.is_a?(Strategy::Broadcast)
         | 
| 49 51 | 
             
                      self
         | 
| 50 52 | 
             
                    else
         | 
| 51 53 | 
             
                      clone.tap do |node|
         | 
| 52 | 
            -
                        node.send(:strategy=, Broadcast.new)
         | 
| 54 | 
            +
                        node.send(:strategy=, Strategy::Broadcast.new)
         | 
| 53 55 | 
             
                      end
         | 
| 54 56 | 
             
                    end
         | 
| 55 57 | 
             
                  end
         | 
| 56 58 |  | 
| 59 | 
            +
                  def broadcast!
         | 
| 60 | 
            +
                    self.strategy = Strategy::Broadcast.new unless strategy.is_a?(Strategy::Broadcast)
         | 
| 61 | 
            +
                    self
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  def compose
         | 
| 65 | 
            +
                    if strategy.is_a?(Strategy::Compose)
         | 
| 66 | 
            +
                      self
         | 
| 67 | 
            +
                    else
         | 
| 68 | 
            +
                      clone.tap do |node|
         | 
| 69 | 
            +
                        node.send(:strategy=, Strategy::Compose.new)
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  def compose!
         | 
| 75 | 
            +
                    self.strategy = Strategy::Compose.new unless strategy.is_a?(Strategy::Compose)
         | 
| 76 | 
            +
                    self
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 57 79 | 
             
                  private
         | 
| 58 80 |  | 
| 59 81 | 
             
                  attr_writer :children, :strategy
         | 
| 60 82 |  | 
| 83 | 
            +
                  def nodeify(callable)
         | 
| 84 | 
            +
                    if callable.is_a?(Node)
         | 
| 85 | 
            +
                      callable.clone
         | 
| 86 | 
            +
                    else
         | 
| 87 | 
            +
                      External.proxify(callable)
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                    .tap { |node| node.send(:parent=, self) }
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
             | 
| 61 92 | 
             
                  def strategy
         | 
| 62 | 
            -
                    @strategy ||= Seek.new
         | 
| 93 | 
            +
                    @strategy ||= Strategy::Seek.new
         | 
| 63 94 | 
             
                  end
         | 
| 64 95 |  | 
| 65 96 | 
             
                  def initialize_copy(_node)
         | 
| 66 97 | 
             
                    super
         | 
| 98 | 
            +
                    self.parent = nil
         | 
| 67 99 | 
             
                    self.children = children.map do |node|
         | 
| 68 100 | 
             
                      node.clone.tap { |new_node| new_node.send(:parent=, self) }
         | 
| 69 101 | 
             
                    end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CallableTree
         | 
| 4 | 
            +
              module Node
         | 
| 5 | 
            +
                module Internal
         | 
| 6 | 
            +
                  module Strategy
         | 
| 7 | 
            +
                    class Broadcast
         | 
| 8 | 
            +
                      def call(nodes, input:, options:)
         | 
| 9 | 
            +
                        nodes.map do |node|
         | 
| 10 | 
            +
                          node.call(input, **options) if node.match?(input, **options)
         | 
| 11 | 
            +
                        end
         | 
| 12 | 
            +
                      end
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CallableTree
         | 
| 4 | 
            +
              module Node
         | 
| 5 | 
            +
                module Internal
         | 
| 6 | 
            +
                  module Strategy
         | 
| 7 | 
            +
                    class Compose
         | 
| 8 | 
            +
                      def call(nodes, input:, options:)
         | 
| 9 | 
            +
                        nodes.reduce(input) do |input, node|
         | 
| 10 | 
            +
                          if node.match?(input, **options)
         | 
| 11 | 
            +
                            node.call(input, **options)
         | 
| 12 | 
            +
                          else
         | 
| 13 | 
            +
                            input
         | 
| 14 | 
            +
                          end
         | 
| 15 | 
            +
                        end
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CallableTree
         | 
| 4 | 
            +
              module Node
         | 
| 5 | 
            +
                module Internal
         | 
| 6 | 
            +
                  module Strategy
         | 
| 7 | 
            +
                    class Seek
         | 
| 8 | 
            +
                      def call(nodes, input:, options:)
         | 
| 9 | 
            +
                        nodes
         | 
| 10 | 
            +
                          .lazy
         | 
| 11 | 
            +
                          .select { |node| node.match?(input, **options) }
         | 
| 12 | 
            +
                          .map do |node|
         | 
| 13 | 
            +
                            output = node.call(input, **options)
         | 
| 14 | 
            +
                            terminated = node.terminate?(output, **options)
         | 
| 15 | 
            +
                            [output, terminated]
         | 
| 16 | 
            +
                          end
         | 
| 17 | 
            +
                          .select { |_output, terminated| terminated }
         | 
| 18 | 
            +
                          .map { |output, _terminated| output }
         | 
| 19 | 
            +
                          .first
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,18 +1,18 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: callable_tree
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - jsmmr
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-07-24 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 | 
            -
            description: Builds a tree by linking callable nodes. The nodes that match the  | 
| 14 | 
            -
               | 
| 15 | 
            -
               | 
| 13 | 
            +
            description: Builds a tree by linking callable nodes. The nodes that match the conditions
         | 
| 14 | 
            +
              are called in a chain from the root node to the leaf node. These are like nested
         | 
| 15 | 
            +
              `if` or `case` expressions.
         | 
| 16 16 | 
             
            email:
         | 
| 17 17 | 
             
            - jsmmr@icloud.com
         | 
| 18 18 | 
             
            executables: []
         | 
| @@ -36,20 +36,22 @@ files: | |
| 36 36 | 
             
            - examples/docs/animals.xml
         | 
| 37 37 | 
             
            - examples/docs/fruits.json
         | 
| 38 38 | 
             
            - examples/docs/fruits.xml
         | 
| 39 | 
            -
            - examples/ | 
| 40 | 
            -
            - examples/ | 
| 41 | 
            -
            - examples/ | 
| 42 | 
            -
            - examples/ | 
| 43 | 
            -
            - examples/ | 
| 44 | 
            -
            - examples/ | 
| 39 | 
            +
            - examples/external-verbosify.rb
         | 
| 40 | 
            +
            - examples/hooks-call.rb
         | 
| 41 | 
            +
            - examples/identity.rb
         | 
| 42 | 
            +
            - examples/internal-broadcast.rb
         | 
| 43 | 
            +
            - examples/internal-compose.rb
         | 
| 44 | 
            +
            - examples/internal-seek.rb
         | 
| 45 | 
            +
            - examples/logging.rb
         | 
| 45 46 | 
             
            - lib/callable_tree.rb
         | 
| 46 47 | 
             
            - lib/callable_tree/node.rb
         | 
| 47 48 | 
             
            - lib/callable_tree/node/external.rb
         | 
| 48 49 | 
             
            - lib/callable_tree/node/external/verbose.rb
         | 
| 49 50 | 
             
            - lib/callable_tree/node/hooks/call.rb
         | 
| 50 51 | 
             
            - lib/callable_tree/node/internal.rb
         | 
| 51 | 
            -
            - lib/callable_tree/node/internal/broadcast.rb
         | 
| 52 | 
            -
            - lib/callable_tree/node/internal/ | 
| 52 | 
            +
            - lib/callable_tree/node/internal/strategy/broadcast.rb
         | 
| 53 | 
            +
            - lib/callable_tree/node/internal/strategy/compose.rb
         | 
| 54 | 
            +
            - lib/callable_tree/node/internal/strategy/seek.rb
         | 
| 53 55 | 
             
            - lib/callable_tree/node/root.rb
         | 
| 54 56 | 
             
            - lib/callable_tree/version.rb
         | 
| 55 57 | 
             
            homepage: https://github.com/jsmmr/ruby_callable_tree
         | 
| @@ -58,7 +60,7 @@ licenses: | |
| 58 60 | 
             
            metadata:
         | 
| 59 61 | 
             
              homepage_uri: https://github.com/jsmmr/ruby_callable_tree
         | 
| 60 62 | 
             
              source_code_uri: https://github.com/jsmmr/ruby_callable_tree
         | 
| 61 | 
            -
              changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/ | 
| 63 | 
            +
              changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.2.1/CHANGELOG.md
         | 
| 62 64 | 
             
            post_install_message:
         | 
| 63 65 | 
             
            rdoc_options: []
         | 
| 64 66 | 
             
            require_paths:
         | 
| @@ -77,7 +79,7 @@ requirements: [] | |
| 77 79 | 
             
            rubygems_version: 3.2.16
         | 
| 78 80 | 
             
            signing_key:
         | 
| 79 81 | 
             
            specification_version: 4
         | 
| 80 | 
            -
            summary: Builds a tree by linking callable nodes. The nodes that match the  | 
| 81 | 
            -
               | 
| 82 | 
            -
               | 
| 82 | 
            +
            summary: Builds a tree by linking callable nodes. The nodes that match the conditions
         | 
| 83 | 
            +
              are called in a chain from the root node to the leaf node. These are like nested
         | 
| 84 | 
            +
              `if` or `case` expressions.
         | 
| 83 85 | 
             
            test_files: []
         | 
    
        data/examples/example6.rb
    DELETED
    
    | @@ -1,101 +0,0 @@ | |
| 1 | 
            -
            require 'callable_tree'
         | 
| 2 | 
            -
            require 'json'
         | 
| 3 | 
            -
            require 'rexml/document'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module Node
         | 
| 6 | 
            -
              module JSON
         | 
| 7 | 
            -
                class Parser
         | 
| 8 | 
            -
                  include CallableTree::Node::Internal
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  def match?(input, **options)
         | 
| 11 | 
            -
                    File.extname(input) == '.json'
         | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def call(input, **options)
         | 
| 15 | 
            -
                    File.open(input) do |file|
         | 
| 16 | 
            -
                      json = ::JSON.load(file)
         | 
| 17 | 
            -
                      super(json, **options)
         | 
| 18 | 
            -
                    end
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  def terminate?(_output, **)
         | 
| 22 | 
            -
                    true
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
                end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                class Scraper
         | 
| 27 | 
            -
                  include CallableTree::Node::External
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  def initialize(type:)
         | 
| 30 | 
            -
                    @type = type
         | 
| 31 | 
            -
                  end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  def match?(input, **options)
         | 
| 34 | 
            -
                    !!input[@type.to_s]
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  def call(input, **options)
         | 
| 38 | 
            -
                    input[@type.to_s]
         | 
| 39 | 
            -
                      .map { |element| [element['name'], element['emoji']] }
         | 
| 40 | 
            -
                      .to_h
         | 
| 41 | 
            -
                  end
         | 
| 42 | 
            -
                end
         | 
| 43 | 
            -
              end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
              module XML
         | 
| 46 | 
            -
                class Parser
         | 
| 47 | 
            -
                  include CallableTree::Node::Internal
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                  def match?(input, **options)
         | 
| 50 | 
            -
                    File.extname(input) == '.xml'
         | 
| 51 | 
            -
                  end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                  def call(input, **options)
         | 
| 54 | 
            -
                    File.open(input) do |file|
         | 
| 55 | 
            -
                      super(REXML::Document.new(file), **options)
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                  def terminate?(_output, **)
         | 
| 60 | 
            -
                    true
         | 
| 61 | 
            -
                  end
         | 
| 62 | 
            -
                end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                class Scraper
         | 
| 65 | 
            -
                  include CallableTree::Node::External
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                  def initialize(type:)
         | 
| 68 | 
            -
                    @type = type
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                  def match?(input, **options)
         | 
| 72 | 
            -
                    !input.get_elements("//#{@type}").empty?
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  def call(input, **options)
         | 
| 76 | 
            -
                    input
         | 
| 77 | 
            -
                      .get_elements("//#{@type}")
         | 
| 78 | 
            -
                      .first
         | 
| 79 | 
            -
                      .map { |element| [element['name'], element['emoji']] }
         | 
| 80 | 
            -
                      .to_h
         | 
| 81 | 
            -
                  end
         | 
| 82 | 
            -
                end
         | 
| 83 | 
            -
              end
         | 
| 84 | 
            -
            end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
            tree = CallableTree::Node::Root.new.append(
         | 
| 87 | 
            -
              Node::JSON::Parser.new.append(
         | 
| 88 | 
            -
                Node::JSON::Scraper.new(type: :animals),
         | 
| 89 | 
            -
                Node::JSON::Scraper.new(type: :fruits)
         | 
| 90 | 
            -
              ).broadcast,
         | 
| 91 | 
            -
              Node::XML::Parser.new.append(
         | 
| 92 | 
            -
                Node::XML::Scraper.new(type: :animals),
         | 
| 93 | 
            -
                Node::XML::Scraper.new(type: :fruits)
         | 
| 94 | 
            -
              ).broadcast
         | 
| 95 | 
            -
            )
         | 
| 96 | 
            -
             | 
| 97 | 
            -
            Dir.glob(__dir__ + '/docs/*') do |file|
         | 
| 98 | 
            -
              options = { foo: :bar }
         | 
| 99 | 
            -
              pp tree.call(file, **options)
         | 
| 100 | 
            -
              puts '---'
         | 
| 101 | 
            -
            end
         | 
| @@ -1,19 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module CallableTree
         | 
| 4 | 
            -
              module Node
         | 
| 5 | 
            -
                module Internal
         | 
| 6 | 
            -
                  class Broadcast
         | 
| 7 | 
            -
                    def call(nodes, input:, options:)
         | 
| 8 | 
            -
                      nodes.map do |node|
         | 
| 9 | 
            -
                        if node.match?(input, **options)
         | 
| 10 | 
            -
                          node.call(input, **options)
         | 
| 11 | 
            -
                        else
         | 
| 12 | 
            -
                          nil
         | 
| 13 | 
            -
                        end
         | 
| 14 | 
            -
                      end
         | 
| 15 | 
            -
                    end
         | 
| 16 | 
            -
                  end
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
              end
         | 
| 19 | 
            -
            end
         | 
| @@ -1,23 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module CallableTree
         | 
| 4 | 
            -
              module Node
         | 
| 5 | 
            -
                module Internal
         | 
| 6 | 
            -
                  class Seek
         | 
| 7 | 
            -
                    def call(nodes, input:, options:)
         | 
| 8 | 
            -
                      nodes
         | 
| 9 | 
            -
                        .lazy
         | 
| 10 | 
            -
                        .select { |node| node.match?(input, **options) }
         | 
| 11 | 
            -
                        .map do |node|
         | 
| 12 | 
            -
                          output = node.call(input, **options)
         | 
| 13 | 
            -
                          terminated = node.terminate?(output, **options)
         | 
| 14 | 
            -
                          [output, terminated]
         | 
| 15 | 
            -
                        end
         | 
| 16 | 
            -
                        .select { |_output, terminated| terminated }
         | 
| 17 | 
            -
                        .map { |output, _terminated| output }
         | 
| 18 | 
            -
                        .first
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
              end
         | 
| 23 | 
            -
            end
         |