I am trying to make a Hash of Arrays with tuples in them. This is causing a weird issue which I suspect is a compiler bug, but I am not 100% sure.
The syntax I am using:
class SomeClass
@@weird_object = Hash(String, Array(Tuple(String, String -> ))).new {|h, k| h[k] = [] of Tuple(String, String -> ) }
#...
def self.some_method
@@weird_object.each do |tuple|
pp tuple[0]
pp tuple[1] #=> This causes compile error "index out of bounds for tuple {(String, String -> Void)}"
end
@@weird_object.each do |the_sting, callback|
#this causes a "Nil trace:" for the callback parameter
end
#...
end
It looks like this has become a tuple of a (String, String -> void)
object, and not String, String -> void
. This error shows up when I run crystal spec
but not when I run crystal build ./src/main.cr
.
Is this a compiler/runtime error, or have I messed up the syntax?
Crystal 0.8.0 [e363b63] (Sat Sep 19 12:00:17 UTC 2015)
Your actual code has:
Hash(String, Array({String, String -> })).new
This tuple is the same as
{(String, String ->)}
So you need parens to disambiguate
Hash(String, Array({String, (String -> )})).new
Your actual code also has a problem with Void appearing everywhere, I'm not sure why, but a few casts can workaround it. Here's the full diff to make it work
diff --git a/src/untangle/aggregator.cr b/src/untangle/aggregator.cr
index 8c49681..7553eb2 100644
--- a/src/untangle/aggregator.cr
+++ b/src/untangle/aggregator.cr
@@ -3,7 +3,7 @@ class Aggregator
@@subscribers_all = Array(String, String ->).new
@@responders = Hash(String, (String ->)).new
#@@reroutes = {} of String => Proc(String)
- @@reroutes = Hash(String, Array({String, String -> })).new {|h, k| h[k] = Array({String, String -> }).new }
+ @@reroutes = Hash(String, Array({String, (String -> )})).new {|h, k| h[k] = Array({String, (String -> )}).new }
def self.subscribe (message_type, &callback : String ->)
@@subscribers[message_type] << callback
@@ -35,11 +35,11 @@ class Aggregator
spawn do
message_type = ch.receive
data = ch.receive
- callback.call(message_type, data)
+ callback.call(message_type, data as String)
end
ch.send(message_type)
- ch.send(data)
+ ch.send(data as String)
end
@@subscribers[message_type].each do |callback|
@@ -48,14 +48,14 @@ class Aggregator
spawn do
callback.call(ch.receive)
end
- ch.send(data)
+ ch.send(data as String)
end
@@reroutes[message_type].each do |tuple| #|to_type, callback|
# puts "!!!!!!!!!!!!!!!!!!!"
# pp tuple
# puts "!!!!!!!!!!!!!!!!!!!"
- Aggregator.publish(tuple[0], tuple[1].call(data))
+ Aggregator.publish(tuple[0], tuple[1].call(data as String))
end
end
def self.request(message_type, arguments)
Please also give http://crystal-lang.org/docs/conventions/coding_style.html a read if you plan adoption of your library in the Crystal community.