Skip to content

Instantly share code, notes, and snippets.

@thiagoa
Last active May 31, 2016
Embed
What would you like to do?
Crystal pipe working with module prefixes
# this was copied from https://carc.in/#/r/fg2
# thanks to @waterlink from this issue thread https://github.com/crystal-lang/crystal/issues/1388
module CrChainableMethods
module Pipe
macro pipe(ast)
{% uast = ast.stringify.gsub(/ >>/, ".pipe").id %}
{% pp uast %}
{% if uast.stringify != ast.stringify %}
pipe {{uast}}
{% else %}
{% if ast.name.id == "pipe".id %}
{% if ast.args.first.receiver.is_a?(Nop) %}
{{ast.args.first.name}}({{ast.receiver}}, {{ast.args.first.args.argify}})
{% else %}
{% receiver_name = ast.args.first.receiver.stringify.gsub(/\(.*\)/, "").id %}
pipe {{receiver_name}}({{ast.receiver}}, {{ast.args.first.receiver.args.argify}}).pipe {{ast.args.first.args.argify}}
{% end %}
{% else %}
{{ast}}
{% end %}
{% end %}
end
macro included
#FIXME this should be used as the last call in the chain if the previous call explicitly calls from a module such as:
# .>> Foo.method .>> unwrap
# Still don't know why the ast parsing works ok for just .>> method but fails for .>> Foo.method
def self.unwrap(foo)
foo
end
end
end
end
include CrChainableMethods::Pipe
module Foo
def self.split_words(phrase)
phrase.split(" ")
end
def self.append_message(words, message)
words + [message]
end
def self.join(words)
words.join(" - ")
end
end
module Bar
def self.add_something(words)
words + ["something"]
end
end
result = pipe "Hello World"
.>> Foo.split_words
.>> Foo.append_message("Bar")
.>> Bar.add_something
.>> Foo.join
.>> unwrap
puts result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment