Created
February 9, 2019 09:31
-
-
Save flash-gordon/4de40ea18cc38e33e54c4f9136b846a6 to your computer and use it in GitHub Desktop.
This shows that implementation of state effects doesn't require mutation. This example uses recursion that can be optimized after enabling TCO
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
require 'fiber' | |
class RunState | |
def call(fiber, state = {}, *xs) | |
result = fiber.resume(*xs) | |
if fiber.alive? | |
op, *args = result | |
case op | |
when :read | |
name = args[0] | |
call(fiber, state, state.fetch(name)) | |
when :write | |
name, value = args | |
call(fiber, state.merge(name => value)) | |
end | |
else | |
result | |
end | |
end | |
end | |
module State | |
def read(name) | |
Fiber.yield([:read, name]) | |
end | |
def write(name, value) | |
Fiber.yield([:write, name, value]) | |
end | |
end |
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
require_relative 'run_state' | |
def main | |
State.write(:foo, 1) | |
puts(State.read(:foo)) | |
State.write(:bar, "baz") | |
puts(State.read(:bar)) | |
"done" | |
end | |
run = RunState.new.freeze | |
fiber = Fiber.new { main } | |
puts run.(fiber) | |
__END__ | |
1 | |
baz | |
done |
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
RubyVM::InstructionSequence.compile_option = { | |
tailcall_optimization: true, | |
trace_instruction: false | |
} | |
require_relative 'run_state' | |
def deep_calc | |
State.write(:n, 0) | |
20000.times do | |
State.write(:n, State.read(:n) + 1) | |
end | |
State.read(:n) | |
end | |
run = RunState.new.freeze | |
fiber = Fiber.new { deep_calc } | |
puts run.(fiber) | |
__END__ | |
20000 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment