Skip to content

Instantly share code, notes, and snippets.

@ixti
Last active August 22, 2019 19:56
Show Gist options
  • Save ixti/b035c9b1988be13de34dda8f677df167 to your computer and use it in GitHub Desktop.
Save ixti/b035c9b1988be13de34dda8f677df167 to your computer and use it in GitHub Desktop.
def print_result(desc)
result = yield
puts "#{desc} class=#{result.class} inspect=#{result.inspect}"
rescue => e
warn "#{desc} fail: #{e}"
end
def test(obj)
puts "\n== #{obj.inspect} == "
print_result("[*obj] =>") { [*obj] }
print_result("Array(obj) =>") { Array(obj) }
print_result("Array.wrap(obj) =>") { Array.wrap(obj) }
end
# trivial cases work the same:
[nil, true, false, 161, [1, 3, 1, 2], { :foo => :bar }].each(&method(:test))
# things become different with objects that implement implicit (to_ary) and/or
# explicit (to_a) coercions:
test(1..3)
# now, let's go crazy:
class Dummy
def initialize(to_a:, to_ary:)
@to_a = to_a
@to_ary = to_ary
define_singleton_method(:to_a) { @to_a } if @to_a
define_singleton_method(:to_ary) { @to_ary } if @to_ary
end
class << self
alias [] new
end
end
test(Dummy[:to_a => [1, 6, 1], :to_ary => [1, 3, 1, 2]])
test(Dummy[:to_a => "AFA", :to_ary => [1, 3, 1, 2]])
test(Dummy[:to_a => [1, 6, 1], :to_ary => "ACAB"])
test(Dummy[:to_a => [1, 6, 1], :to_ary => nil])
test(Dummy[:to_a => nil, :to_ary => [1, 6, 1]])
test(Dummy[:to_a => "AFA", :to_ary => nil])
test(Dummy[:to_a => nil, :to_ary => "AFA"])
test(Dummy[:to_a => nil, :to_ary => nil])
@sensorsasha
Copy link

Seems like Array.wrap is the most obvious implementation.

@ixti
Copy link
Author

ixti commented Aug 22, 2019

To make it easier to think of those methods, here's brief outline of behaviours:

Array(object)

  • Return object as is if it's an Array
  • Otherwise coerce object implicitly (if object responds to #to_ary)
    • Raise TypeError if coercion returned in non-Array
  • Otherwise coerce object explicitly (if object responds to #to_a)
    • Raise TypeError if coercion returned non-Array
  • Otherwise wrap object into an Array (as in: [object])

Array.wrap(object)

  • Return object as is if it's an Array
  • Otherwise coerce object implicitly (if object responds to #to_ary)
    • Return result of coercion as is if it's truthy (anything but nil or false)
  • Otherwise wrap object into an Array (as in: [object])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment