2015-09-08 2 views
0

Проблема возникает, когда переменная, из которой был построен массив, первоначально была nil."undefined method 'zero' for Nil: Class" when #sum the Array without Nils

y = (1..2).map do 
    v = nil 
    v = 1 
    v 
end 
p y  # => [1, 1] 
p y.class # => Array(Int32) 
p y.sum # => 2 

Когда v перестает быть nil о состоянии, то есть потенциально вычислительная и не разрешимы при компиляции:

z = (1..2).map do 
    v = nil 
    v = 1 if true 
    v 
end 
p z  # [1, 1] 
p z.class # => Array(Nil | Int32) 

Массив получает более сложный тип, что не совместимо с текущей sum реализации, так p z.sum причины компиляции ошибки времени:

undefined method 'zero' for Nil:Class (compile-time type is (Nil | Int32):Class) 
def sum(initial = T.zero) 
        ^~~~ 

Как я должен бороться с этим про Perly?
Или, может быть, он ждет некоторой лучшей реализации метода stdlib sum или чего-нибудь еще?

UPD: inject дает тот же:

p z.inject{ |i, j| i + j } 

undefined method '+' for Nil (compile-time type is (Nil | Int32)) 

ответ

4

Вы можете использовать Iterator#compact_map для выбора значений, не равна нулю. В этом случае компилятор сможет вывести Array(Int32).

http://play.crystal-lang.org/#/r/e85

z = (1..2).map do 
    v = nil 
    v = 1 if true 
    v 
end 

pp typeof(z) # => Array(Nil | Int32) 
pp z # => z = [1, 1] 

y = z.compact_map(&.itself) 
pp typeof(y) # => Array(Int32) 
pp y # => y = [1, 1] 

Кроме того, обратите внимание, что typeof(Expr) и Expr.class может привести к различным результатам. Первый - это тип времени компиляции, а позже - тип времени выполнения.

Смежные вопросы