https://github.com/maxpleaner/inverse_methods
pass_to and chain_to methods using debug_inspector
https://github.com/maxpleaner/inverse_methods
ruby ruby-extension ruby-gem
Last synced: 6 months ago
JSON representation
pass_to and chain_to methods using debug_inspector
- Host: GitHub
- URL: https://github.com/maxpleaner/inverse_methods
- Owner: MaxPleaner
- Created: 2017-01-05T09:19:52.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2017-06-26T17:40:06.000Z (almost 9 years ago)
- Last Synced: 2025-03-06T06:22:31.475Z (about 1 year ago)
- Topics: ruby, ruby-extension, ruby-gem
- Language: Ruby
- Homepage:
- Size: 8.79 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
### Install
`gem install inverse_methods`
`require 'inverse_methods'`
## Accessing methods
There is a single module `InverseMethods` which can be included where it's needed or patched on `Object` for global access.
To load it globally, use `Object.include InverseMethods`. Or use a more specific scope such as `MyClass.include InverseMethods` or `MyClass.extend InverseMethods`.
It can be used as a refinement: `using InverseMethods`.
### Explanation
Two methods which can be added on Object:
Both use `debug_inspector` to do some stuff with Ruby that wouldn't otherwise be possible.
`pass_to` is kind of like a reverse tap. It still works as a "tap" (it returns the caller) but takes arguments differently:
foo = []
1.pass_to %i{ foo.push foo.push }
# => 1
puts foo # => [1,1]
The caller is being passed as an argument (serialized using `Marshal.dump`), and the symbols in the list are methods which it is passed to. They are evaluated in the caller context, which is why the local variable `foo` can be referenced.
The method names passed to `pass_to` are not chained. This is why `[1,1]` was returned instead of `[1, [...]]` (the three dots being a recursive reference). The `foo.push 1` calls happen independently of one another.
The above example, if modified like so, wouldn't work:
foo = []
1.pass_to [:foo.push, :foo.push]
puts foo
The reason is that `:foo.push` is a `SyntaxError`. It needs to be written as `:"foo.push"`, which the `%i{ array.of symbols }` shorthand would do automatically.
The second method is `chain_to`, which is perhaps the 'functional programming' alternative to `pass_to` (and `tap`, which it's based on). It works similarly:
foo = []
[1].chain_to %i{[2].concat [3].concat}
puts foo # => [3,2,1]
Only the first symbol (`:"[2].concat"`) gets the original argument, `[1]`, passed when evaluated. The next symbol `:"[3].concat"` gets the first evaluation's result (`[2, 1]`) passed.