-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Indexable itself cannot be used for Enumerable#zip #8608
Comments
This is because |
Just define class Foo(T)
def initialize(@a : T, @b : T)
end
def some_work
@a.zip(@b) do |a, b|
puts a, b
end
end
end
f = Foo.new([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])
f.some_work |
@asterite that's a workaround in this case, not a solution still. |
I noticed that this problem occurs only if the argument type is a = [1, 2, 3]
if rand < 0.5
b = {1.0, 2.0, 3.0} # Indexable
else
b = Dir.open("/") # Iterable but not Indexable
end
a.zip(b) do |x, y|
puts x, y
end https://play.crystal-lang.org/#/r/89qb I don't know who mixes up a = [1, 2, 3]
if rand < 0.5
b = {1.0, 2.0, 3.0} # Indexable
elsif rand < 0.5
b = Dir.open("/") # Iterable but not Indexable
else
b = ['a', 'b', 'c'].each # Iterator
end
a.zip(b) do |x, y|
puts x, y
end https://play.crystal-lang.org/#/r/89a4 I just tried to implement module Enumerable(T)
module Zipper
def self.for(iter : Iterator(T)) forall T
ZipIterator(T).new(iter)
end
def self.for(iter : Indexable(T)) forall T
ZipIndexable(T).new(iter)
end
def self.for(iter : Iterable(T)) forall T
ZipIterable(T).new(iter)
end
end
struct ZipIndexable(T)
def initialize(@container : Indexable(T))
end
def next(index_hint) : T
@container[index_hint]
end
end
struct ZipIterator(T)
def initialize(@iter : Iterator(T))
end
def next(index_hint) : T
if (n = @iter.next).is_a?(Iterator::Stop)
raise IndexError.new
else
n
end
end
end
struct ZipIterable(T)
@iter : Iterator(T)
def initialize(iter : Iterable(T))
@iter = iter.each
end
def next(index_hint) : T
if (n = @iter.next).is_a?(Iterator::Stop)
raise IndexError.new
else
n
end
end
end
def self.zip(main, others : U, &block) forall U
{% begin %}
iters = {
{% for o, i in U %}
Zipper.for(others[{{i}}]),
{% end %}
}
puts typeof(iters) # To confirm the type has been reduced as possible as we can
main.each_with_index do |m, i|
elems = {
m,
{% for o, i in U %}
iters[{{i}}].next(i),
{% end %}
}
yield elems
end
{% end %}
end
def zip(*others : Indexable | Iterable | Iterator, &block)
Enumerable.zip(self, others) do |elems|
yield elems
end
end
end
a = [1, 2, 3]
if rand < 0.5
b = {1.0, 2.0, 3.0} # Indexable
elsif rand < 0.5
b = Dir.open("/") # Iterable but not Indexable
else
b = ['a', 'b', 'c'].each # Iterator
end
a.zip(b) do |x, y|
puts({typeof(x), typeof(y)})
puts({x, y})
end
puts
a.zip([1.0, 2, "a"], Dir.open(".")) do |x, y, z|
puts({typeof(x), typeof(y), typeof(z)})
puts({x, y, z})
end |
With the following definition, it says that
Enumerable#zip
acceptsIndexable
(and objects include it), butIndexable
itself cannot be used as an argument ofEnumerable#zip
, and getting error on the internal macro expansion.crystal/src/enumerable.cr
Lines 1507 to 1546 in 8dd3271
I wanted to create a generic class which accept two any objects which can be used for
#zip
(with other data).https://play.crystal-lang.org/#/r/88yn
Getting following error:
I have not checked for
Iterable
norIterator
.The text was updated successfully, but these errors were encountered: