-
-
Save shved/dddf9b6ec986e279149e95e774249a9b 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