Last active
October 27, 2017 22:00
-
-
Save JAMSUPREME/a131da3ff48ed4805709c599d6ec0118 to your computer and use it in GitHub Desktop.
pipey
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pipey | |
def <<(next_pipey) | |
if self.result.is_a?(EmptyPipe) | |
next_pipey.call | |
else | |
next_pipey.call(self.result) | |
end | |
end | |
# For self.execute | |
def execute(*args) | |
self.new.execute(*args) | |
end | |
# For self.pipe | |
def pipe(*args) | |
self.new.pipe(*args) | |
end | |
def self.included(klass) | |
klass.class_eval do | |
# Create result attribute | |
attr_accessor :result | |
# When including Pipey, also extend it (to give Pluggy syntax) | |
extend Pipey | |
# Immediate execution | |
# def execute(*args) | |
define_method('execute') do |*args| | |
@result = self.run(*args) | |
return self | |
end | |
# Deferred execution | |
# def pipe(*args) | |
define_method('pipe') do |*args| | |
# Create a proc that takes splat args | |
# Must merge the args it received with the args it will get passed during evaluation | |
->(*proc_args) { | |
proc_args += args | |
@result = self.run(*proc_args) | |
return self | |
} | |
end | |
end | |
end | |
end | |
# Empty pipe helper to avoid forcing use of execute | |
class EmptyPipe | |
include Pipey | |
def execute | |
@result = self | |
self | |
end | |
end | |
# Value pipe helper to make the base of a chain simpler | |
class ValuePipe | |
include Pipey | |
def execute(value) | |
@result = value | |
self | |
end | |
end | |
class IncrementNumber | |
include Pipey | |
def run(*args) | |
base_number = args.empty? ? 0 : args[0] | |
base_number + 1 | |
end | |
end | |
class MultiplyBy | |
include Pipey | |
def run(*args) | |
raise 'Need 2 args to multiply' if args.length != 2 | |
base_number = args[0] | |
multiplier = args[1] | |
base_number * multiplier | |
end | |
end | |
# First item in a chain must be an execute | |
# because we cannot "<<" on a Proc | |
# puts (IncrementNumber.pipe(1) << | |
# IncrementNumber.pipe << | |
# MultiplyBy.pipe(5)).result | |
# But we can mitigate with EmptyPipe | |
puts (EmptyPipe.execute << | |
IncrementNumber.pipe(1) << | |
IncrementNumber.pipe << | |
MultiplyBy.pipe(5)).result | |
# Or a ValuePipe | |
puts (ValuePipe.execute(1) << | |
IncrementNumber.pipe << | |
MultiplyBy.pipe(5)).result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pipey | |
def <<(next_pipey) | |
next_pipey.call(self.result) | |
end | |
# For self.execute | |
def execute(*args) | |
self.new.execute(*args) | |
end | |
# When including Pipey, also extend it (to give Pluggy syntax) | |
def self.included(klass) | |
klass.class_eval do | |
attr_accessor :result | |
extend Pipey # TODO | |
define_method('execute') do |*args| | |
unless args.empty? | |
@result = self.run(*args) | |
return self | |
end | |
->(*args) { | |
@result = self.run(*args) | |
return self | |
} | |
end | |
end | |
end | |
end | |
class IncrementNumber | |
include Pipey | |
# Might later call this "call" or "execute" | |
def run(*args) | |
base_number = args.empty? ? 0 : args[0] | |
base_number + 1 | |
end | |
end | |
puts (IncrementNumber.execute(1) << | |
IncrementNumber.execute << | |
IncrementNumber.execute).result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pipey | |
# a pipey has a custom "into" | |
def >>(next_pipey) | |
puts "Result is #{@result} and next pipey is #{next_pipey}" | |
# next_pipey.execute(@result) | |
end | |
def execute | |
raise StandardError 'A pipey must implement execute' | |
end | |
end | |
class Incrementer | |
include Pipey | |
def execute(input) | |
puts input + 1 | |
@result = input + 1 | |
end | |
class << self | |
def execute(input) | |
puts input + 1 | |
@result = input + 1 | |
end | |
end | |
end | |
p1 = Incrementer.new | |
p2 = Incrementer.new | |
p1 >> p2 | |
# p1.execute(1) | |
# p1.execute(1) >> p2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Later TODO | |
# https://www.rubypigeon.com/posts/a-review-of-immutability-in-ruby/ | |
# make things immutable | |
module Pipey | |
def <<(next_pipey) | |
puts "piped" | |
next_pipey.call(self.result) | |
end | |
end | |
class Incrementer | |
attr_accessor :result | |
include Pipey | |
def execute(*args) | |
unless args.empty? | |
@result = args[0] + 1 | |
puts @result | |
return self | |
end | |
->(input) { | |
puts input + 1 | |
@result = input + 1 | |
return self | |
} | |
end | |
end | |
p1 = Incrementer.new | |
p2 = Incrementer.new | |
p1.execute(1) << p2.execute << p2.execute << p2.execute |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pipey | |
def <<(next_pipey) | |
next_pipey.call(self.result) | |
end | |
end | |
class Incrementer | |
attr_accessor :result | |
include Pipey | |
extend Pipey | |
def execute(*args) | |
unless args.empty? | |
@result = args[0] + 1 | |
return self | |
end | |
->(input) { | |
@result = input + 1 | |
return self | |
} | |
end | |
class << self | |
def execute(*args) | |
Incrementer.new.execute(*args) | |
end | |
end | |
end | |
puts (Incrementer.execute(1) << | |
Incrementer.execute << | |
Incrementer.execute << | |
Incrementer.execute).result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pipey | |
def <<(next_pipey) | |
puts 'piped' | |
next_pipey.call(self.result) | |
end | |
# For self.execute | |
def execute(*args) | |
self.new.execute(*args) | |
end | |
# For self.pipe | |
def pipe(*args) | |
self.new.pipe(*args) | |
end | |
def self.included(klass) | |
klass.class_eval do | |
# Create result attribute | |
attr_accessor :result | |
# When including Pipey, also extend it (to give Pluggy syntax) | |
extend Pipey | |
# Immediate execution | |
# def execute(*args) | |
define_method('execute') do |*args| | |
@result = self.run(*args) | |
return self | |
end | |
# Deferred execution | |
# def pipe(*args) | |
define_method('pipe') do |*args| | |
# Create a proc that takes splat args | |
# Must merge the args it received with the args it will get passed during evaluation | |
->(*proc_args) { | |
proc_args += args | |
@result = self.run(*proc_args) | |
return self | |
} | |
end | |
end | |
end | |
end | |
class IncrementNumber | |
include Pipey | |
def run(*args) | |
puts 'incremented' | |
base_number = args.empty? ? 0 : args[0] | |
base_number + 1 | |
end | |
end | |
class MultiplyBy | |
include Pipey | |
def run(*args) | |
raise 'Need 2 args to multiply' if args.length != 2 | |
puts 'multiplied' | |
base_number = args[0] | |
multiplier = args[1] | |
base_number * multiplier | |
end | |
end | |
puts (IncrementNumber.execute(1) << | |
IncrementNumber.pipe << | |
MultiplyBy.pipe(5)).result | |
# First item in a chain must be an execute | |
# because we cannot "<<" on a Proc | |
# puts (IncrementNumber.pipe(1) << | |
# IncrementNumber.pipe << | |
# MultiplyBy.pipe(5)).result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment