Class: R::List
- Includes:
- Enumerable, IndexedObject
- Defined in:
- lib/R_interface/rlist.rb
Overview
Constant Summary
Constants inherited from Object
Instance Attribute Summary
Attributes inherited from Object
Instance Method Summary collapse
-
#+(other_object) ⇒ Object
--------------------------------------------------------------------------------------.
- #>>(index) ⇒ Object
- #class ⇒ Object
-
#each ⇒ Object
-------------------------------------------------------------------------------------- Each cannot return a Enumerator because R is single threaded.
-
#each_with_index ⇒ Object
-------------------------------------------------------------------------------------- Need to override each_with_index, as R indexing starts at 1 --------------------------------------------------------------------------------------.
-
#method_missing_assign(elmt_name, arg) ⇒ Object
--------------------------------------------------------------------------------------.
-
#unboxed_get(index = nil, depth = 0) ⇒ Object
-------------------------------------------------------------------------------------- Unbox list to Ruby.
Methods included from IndexedObject
Methods inherited from Object
#==, build, build_class_probe_count, build_from_r_class_string, build_from_wrapper_tag, #call, class_probe_fetch_r_class, increment_build_class_probe_count!, #initialize, #inspect, #instance_of?, #instance_variable_get, #instance_variable_set, #is_a?, #method_missing, #nil?, #pretty_print, #rclass, reset_build_counters!, #respond_to?, #send, #to_ary, #to_i, #to_ruby, #to_s, #typeof
Methods included from ExecUniOp
Methods included from UnaryOperators
Methods included from ExecBinOp
Methods included from BinaryOperators
#!=, #%, #*, #**, #-, #/, #<, #<=, #>, #>=, #_, #eq, #int_div, #til
Constructor Details
This class inherits a constructor from R::Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class R::Object
Instance Method Details
#+(other_object) ⇒ Object
42 43 44 |
# File 'lib/R_interface/rlist.rb', line 42 def +(other_object) ::R::Support.exec_function_name("`+`", @r_interop, other_object.r_interop) end |
#>>(index) ⇒ Object
149 150 151 152 153 |
# File 'lib/R_interface/rlist.rb', line 149 def >>(index) # Count the list root as depth 1 so MAX_UNBOX_DEPTH applies to list nesting # the same way legacy unboxing specs expect. unboxed_get(index, 1) end |
#each ⇒ Object
Each cannot return a Enumerator because R is single threaded. When this restriction is removed, make each return self.to_enum
160 161 162 163 164 165 166 167 168 169 |
# File 'lib/R_interface/rlist.rb', line 160 def each len = length len = len.is_a?(::R::Vector) ? len.unboxed_get(0) : len (1..len).each do |i| # In Ruby list[[i]] is list.[]( [i] ) → single Array arg → we use R's [[ (element) yield self[[ [i] ]] end end |
#each_with_index ⇒ Object
Need to override each_with_index, as R indexing starts at 1
175 176 177 178 179 180 181 182 183 |
# File 'lib/R_interface/rlist.rb', line 175 def each_with_index len = length len = len.is_a?(::R::Vector) ? len.unboxed_get(0) : len (1..len).each do |i| yield self[[ [i] ]], i end end |
#method_missing_assign(elmt_name, arg) ⇒ Object
50 51 52 |
# File 'lib/R_interface/rlist.rb', line 50 def method_missing_assign(elmt_name, arg) setR_name("`[[<-`", elmt_name, arg) end |
#unboxed_get(index = nil, depth = 0) ⇒ Object
Unbox list to Ruby. Recurses until only Ruby values (no R::Object in result).
- index.nil? → whole list → Array of unboxed elements (single list → [x]).
- index i → list[[i+1]] unboxed (one Ruby value). Raises R::UnboxDepthError when recursion exceeds MAX_UNBOX_DEPTH (can be expensive).
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/R_interface/rlist.rb', line 60 def unboxed_get(index = nil, depth = 0) if depth >= ::R::Support::MAX_UNBOX_DEPTH ::Kernel.raise(::R::UnboxDepthError, "unbox: list too deep (max depth #{::R::Support::MAX_UNBOX_DEPTH} exceeded)") end if index.nil? && depth <= 1 && ::R.bridge.respond_to?(:unbox_materialize) materialized = ::R.bridge.unbox_materialize(@r_interop, max_depth: ::R::Support::MAX_UNBOX_DEPTH, max_nodes: 200_000) case materialized[:status] when :ok return materialized[:value] when :depth_limit ::Kernel.raise(::R::UnboxDepthError, "unbox: list too deep (max depth #{::R::Support::MAX_UNBOX_DEPTH} exceeded)") when :node_limit # Fall through to structural path if node budget is hit. when :unsupported # Fall through to structural path for mixed/unsupported types. end end # Fast preflight for deep nested lists on the new bridge: # detect depth overflow in one bridge call before recursive element reads. if index.nil? && depth <= 1 && ::R.bridge.respond_to?(:unbox_walk) walk = ::R.bridge.unbox_walk(@r_interop, max_depth: ::R::Support::MAX_UNBOX_DEPTH, max_nodes: 200_000) if walk[:status] == :depth_limit ::Kernel.raise(::R::UnboxDepthError, "unbox: list too deep (max depth #{::R::Support::MAX_UNBOX_DEPTH} exceeded)") end end # NewBridge hardening path: use structural bridge reads during recursion. if ::R.bridge.respond_to?(:unbox_list_length) && ::R.bridge.respond_to?(:unbox_list_element) n = ::R.bridge.unbox_list_length(@r_interop) if index.nil? return [] if n <= 0 arr = [] (1..n).each do |i| elt = ::R.bridge.unbox_list_element(@r_interop, i) if elt.nil? arr << nil elsif !elt.is_a?(::R::Object) arr << elt else arr << elt.unboxed_get(nil, depth + 1) end end return arr end bound = n - 1 ::Kernel.raise(::IndexError.new("index #{index} out of list bounds: 0...#{bound}")) if index > bound elt = ::R.bridge.unbox_list_element(@r_interop, index + 1) return elt unless elt.is_a?(::R::Object) return nil if elt.nil? return nil if elt.respond_to?(:rclass) && elt.rclass.to_s.strip == 'NULL' return elt.unboxed_get(nil, depth + 1) end if index.nil? # Whole list → Array of unboxed elements (recurse into each element). len_val = length n = len_val.is_a?(::R::Vector) ? len_val.unboxed_get(0) : len_val n = n.to_i if n.respond_to?(:to_i) return [] unless n.is_a?(::Integer) && n >= 1 arr = [] (1..n).each do |i| elt = self[[ [i] ]] if elt.nil? arr << nil elsif !elt.is_a?(::R::Object) arr << elt else arr << (elt.is__null.unboxed_get(0) ? nil : elt.unboxed_get(nil, depth + 1)) end end return arr end # Single element at index bound_val = length bound = bound_val.is_a?(::R::Vector) ? bound_val.unboxed_get(0) : bound_val bound = bound.to_i - 1 if bound.respond_to?(:to_i) bound = 0 if bound.nil? || !bound.is_a?(::Integer) || bound < 0 ::Kernel.raise(::IndexError.new("index #{index} out of list bounds: 0...#{bound}")) if index > bound elt = self[[ [index + 1] ]] return elt unless elt.is_a?(::R::Object) return nil if (elt.is__null.respond_to?(:unboxed_get) ? elt.is__null.unboxed_get(0) : elt.is__null) elt.unboxed_get(nil, depth + 1) end |