Skip to content

Instantly share code, notes, and snippets.

@fulcanelly
Last active January 6, 2022 03:48
Show Gist options
  • Save fulcanelly/fb48263f895bf7ffe1223eba05870eeb to your computer and use it in GitHub Desktop.
Save fulcanelly/fb48263f895bf7ffe1223eba05870eeb to your computer and use it in GitHub Desktop.
The ruby fibers somehow similar to haskell's free monads
class FiberDSL
def expect regex
Fiber.yield({regex:})
end
def reply text
Fiber.yield({reply: text})
end
end
class STest < FiberDSL
def expect_num
expect /\d+/
end
def run
reply "enter a: "
expect_num => a
reply "enter b: "
expect_num => b
reply "result is #{a + b}"
end
end
def start_fiber
Fiber.new do
STest.new.run
end
end
def run_with_stdio(fiber)
getnum = proc do |rex|
res = gets
unless res.match? rex
print "wrong fomrat, enter #{rex.inspect}: "
redo
end
res.to_i
end
while fiber.alive?
res = case fiber.resume res
in {regex: rex}
getnum.(rex)
in {reply: text}
print text
else
end
end
end
def run_test(fiber)
test = [
"enter a: ",
3,
"enter b: ",
4,
"result is 7"
]
while fiber.alive?
test.shift => one
case fiber.resume one
in {regex: rex}
puts "* provide #{one}"
in {reply: text}
puts "> expect: #{one.inspect}"
puts "> got #{text.inspect}"
else
puts "^ end"
end
end
end
[
:run_with_stdio,
:run_test
]
.lazy
.map do method _1 end
.each do
_1.(start_fiber)
puts "\n\n"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment