Last active
December 22, 2015 09:09
-
-
Save seanchas116/6450058 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
class DoNotation | |
class DSL | |
def initialize(&block) | |
@first_lets = [] | |
@proc_sources = [] | |
@variables = Hash[] | |
# evaluate DSL | |
instance_eval(&block) | |
bind = lambda do |head_source, tail_sources, get_symbol, lets| | |
proc do |x| | |
if get_symbol | |
@variables[get_symbol] = x | |
end | |
lets.each do |let_item| | |
@variables[let_item.symbol] = instance_eval(&let_item.block) | |
end | |
monad = instance_eval(&head_source.block) | |
if tail_sources.length > 0 | |
inner_proc = bind.call(tail_sources.first, tail_sources[1..-1], head_source.symbol, head_source.lets) | |
monad.flat_map(&inner_proc) | |
else | |
monad | |
end | |
end | |
end | |
@outermost_proc = bind.call(@proc_sources.first, @proc_sources[1..-1], nil, @first_lets) | |
end | |
def get(symbol, &block) | |
if symbol | |
self.class.send(:define_method, symbol) { @variables[symbol] } | |
end | |
@proc_sources << Struct.new(:symbol, :block, :lets).new(symbol, block, []) | |
end | |
def just(&block) | |
self.get(nil, &block) | |
end | |
def let(symbol, &block) | |
self.class.send(:define_method, symbol) { @variables[symbol] } | |
item = Struct.new(:symbol, :block).new(symbol, block) | |
if @proc_sources.length > 0 | |
@proc_sources.last.lets << item | |
else | |
@first_lets << item | |
end | |
end | |
def get_value() | |
@outermost_proc.call | |
end | |
end | |
include Enumerable | |
def initialize(&block) | |
@dsl = DSL.new(&block) | |
end | |
def each(&block) | |
value = @dsl.get_value | |
value.each(&block) | |
end | |
end | |
def getLine | |
Enumerator.new { |y| | |
y << gets | |
}.lazy | |
end | |
def putStrLn(str) | |
Enumerator.new { |y| | |
puts str | |
y << nil | |
}.lazy | |
end | |
# this notation | |
main = DoNotation.new { | |
just { putStrLn "Enter something" } | |
get(:line) { getLine } | |
let(:output) { "You said #{line}" } | |
just { putStrLn output } | |
} | |
# equals to this | |
=begin | |
main = putStrLn("Enter something").flat_map do |x| | |
getLine.flat_map do |line| | |
output = "You said #{line}" | |
putStrLn output | |
end | |
end | |
=end | |
puts "Starting..." | |
main.force |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment