Array co-something inconsistency

Hello,

This code (https://carc.in/#/r/5whi):

class Foo
end

class Bar < Foo
end

ary = Array(Foo.class).new
ary << Bar

Compiles nicely, while when replacing class with module (https://carc.in/#/r/5whj):

module Foo
end

class Bar
  include Foo
end

ary = Array(Foo.class).new
ary << Bar

It failes to compile with no overload matches 'Array(Foo:Module)#<<' with type Bar.class.

Is that intended? Is that going to change?

Thanks,

I suspect what you’ve intended to write is:
https://play.crystal-lang.org/#/r/5wp0

module Foo
end

class Bar
  include Foo
end

ary = Array(Foo).new
ary << Bar.new()
p! ary

No, I’m absolutely sure that I need to store classes, not their instances.

Probably not intended nor designed. I don’t recall any story about the metaclass design related to modules and classes that are including them.

What is what you are trying to achieve later with that array?

There are two things here. First, it’s OK for the code not to compile because when you include a module only the instance type gets included, so technically the Bar class is not a Foo class. You can see this is like that because you can’t invoke class methods of Foo from Bar.

module Foo
  def self.foo
    1
  end
end

class Bar
  include Foo
end

Bar.foo # undefined method 'foo' for Bar.class

However, I think it should work when extending the module… but it doesn’t.

Also, as @bcardff says, all of this hasn’t been well defined yet.

That’s interesting. However, even when extending, it doesn’t work as well (Carcin):

module Foo
end

class Bar
  extend Foo
end

ary = Array(Foo.class).new
ary << Bar
Error in line 9: no overload matches 'Array(Foo:Module)#<<' with type Bar.class
Overloads are:
 - Array(T)#<<(value : T)

Nevertheless, my use-case is Event-Driven Architecture (EDA), where a number of subscribers can subscribe to an Event. For performance benefit, it’s smart to store them in a Hash(Event.class, Array(Proc(Event, Nil)) for faster reaction times. Currently the code looks like this:

struct MyEvent < Event
  getter foo

  def initialize(@foo : String)
  end
end

channel.subscribe(MyEvent) { |event| do_something(event.foo) }

It works nicely when Event is abstract struct, but I’d like to make it a module – just for more beautiful (subjectively) code. :leaves:

Summing it up, Hash(Event.class, Proc(Event, Nil)) doesn’t work when Event is a module, as well as Set(Event.class) and Array(Event.class), as stated in the first post.

P.S: I managed to store Procs with abstract Event in the hash as a pair of Void*.
_P.P.S: For better understanding, I have a code sample for channel: https://gist.github.com/vladfaust/455b343f539188af43a91188d06a1a07_

Okay, as always, after posting I understand that module would not work for me in my case because all_subclasses for a module doesn’t make sense. And I need to know subclasses for my arch.

However, the issue still remains, and I cannot use a module Foo's includer in the place of Foo.class.

How about Array(Foo.module)?