Skip to content

Instantly share code, notes, and snippets.

@seanchas116
Last active December 22, 2015 09:09
Show Gist options
  • Save seanchas116/6450058 to your computer and use it in GitHub Desktop.
Save seanchas116/6450058 to your computer and use it in GitHub Desktop.
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