Module: TCOMethod
- Defined in:
- lib/tco_method.rb,
lib/tco_method/mixin.rb,
lib/tco_method/version.rb,
lib/tco_method/method_info.rb,
lib/tco_method/block_with_tco.rb,
lib/tco_method/block_extractor.rb,
lib/tco_method/method_reevaluator.rb,
lib/tco_method/ambiguous_source_error.rb
Overview
The namespace for the TCOMethod gem. Home to private API methods employed by the Mixin module to provide tail call optimized behavior to extending Classes and Modules.
Defined Under Namespace
Modules: Mixin Classes: AmbiguousSourceError, BlockExtractor, BlockWithTCO, MethodInfo, MethodReevaluator
Constant Summary collapse
- ISEQ_OPTIONS =
Options that must be provided to RubyVM::InstructionSequence in order to compile code with tail call optimization enabled. Beyond simply enabling the ‘tailcall optimization` option, the `trace_instruction` option must also be disabled because the RubyVM doesn’t currently support ‘set_trace_func` for code that is compiled with tail call optimization.
{ tailcall_optimization: true, trace_instruction: false, }.freeze
- VERSION =
The version of the TCOMethod gem.
"0.2.0"
Class Method Summary collapse
-
.tco_eval(code, file = nil, path = nil, line = nil) ⇒ Object
Provides a mechanism for evaluating Strings of code with tail call optimization enabled.
-
.with_tco(&block) ⇒ Object
Allows for executing a block of code with tail call optimization enabled.
Class Method Details
.tco_eval(code, file = nil, path = nil, line = nil) ⇒ Object
Provides a mechanism for evaluating Strings of code with tail call optimization enabled.
28 29 30 31 |
# File 'lib/tco_method.rb', line 28 def self.tco_eval(code, file = nil, path = nil, line = nil) raise ArgumentError, "Invalid code string!" unless code.is_a?(String) RubyVM::InstructionSequence.new(code, file, path, line, ISEQ_OPTIONS).eval end |
.with_tco(&block) ⇒ Object
Allows for executing a block of code with tail call optimization enabled.
All code that is evaluated in the block will be evaluated with tail call optimization enabled, however here be dragons, so be warned of a few things:
-
Though it may not be obvious, any call to ‘require`, `load`, or similar
methods from within the block will be evaluated by another part of the VM and will not be tail call optimized. This applies for ‘tco_eval` as well.
-
The block will be evaluated with a different binding than the binding it
was defined in. That means that references to variables or other binding context will result in method errors. For example:
some_variable = "Hello, World!"
womp_womp = TCOMethod.with_tco { some_variable }
# => NameError: Undefined local variable or method 'some_variable'
-
Though this approach is some what nicer than working with strings of
code, it comes with the tradeoff that it relies on the the ‘method_source` gem to do the work of finding the source of the block. There are situations where `method_source` can’t accurately determine the source location of a block. That said, if you don’t format your code like a maniac, you should be fine.
60 61 62 63 |
# File 'lib/tco_method.rb', line 60 def self.with_tco(&block) raise ArgumentError, "Block required" unless block_given? BlockWithTCO.new(&block).result end |