Crystal语言出现了“Array(Type)#[]”与类型(Int32 | Nil)不匹配的重载错误。

3

我在使用索引时发现了一些奇怪的行为。

#Defined in the class's initialize    
@my_list = [] of Type

index = @my_list.index { |i| i.value == 2 } # => 0

@my_list[0] # => 2
@my_list[index] # => error

我遇到了以下错误:

没有匹配类型为(Int32 | Nil)的'Array(Type)#[]'重载

不确定为什么索引不起作用,因为索引=0。

编辑:

更多信息。如果我这样做:

if index == nil
  #Do something
#error => undefined method '>=' for Nil (compile-time type is (Int32 | Nil))
elsif index >= 0
  #Do something else
end

我明白。它可能是nil,但既然我已经检查过它是否为nil,这里就不应该有问题。我认为先前的代码片段也遇到了同样的问题。

4个回答

3
问题在于Array#index可能为空,它可能找不到任何内容并返回nil,因此它返回一个Int32|Nil联合类型。
编译器最终失败,因为Array#[]需要一个Int32参数,但我们传递了一个Int32|Nil。您必须注意这种情况(以避免后来出现的错误),例如通过检查返回值是否为真。

1

正如@julien-portalier所说:

问题在于Array#index是可空的;它可能在数组中找不到任何内容并返回Nil,因此它返回(Int32 | Nil)联合类型。

您可以使用Object#not_nil!来消除Nil类型:

@my_list = [2, 4, 6, 8]

index = @my_list.index { |i| i == 6 }.not_nil! # => 2
# compile type of 'index' is Int32

@my_list[0] # => 2
@my_list[index] # => 6

它将确保Array#index返回的类型不是Nil,如果是,将会抛出异常(参见Nil#not_nil!


如果您需要在不使用异常处理的情况下处理索引错误,可以简单地检查Array#index是否失败:

@my_list = [2, 4, 6, 8]

index = @my_list.index { |i| i == 6 } # => 2
# compile-time type of 'index' is (Int32 | Nil)

if index
    # In this scope, compile-time type of 'index' is Int32
    @my_list[0] # => 2
    @my_list[index] # => 6
end

0

我只是要做这个:

def get_index(val)
  i = 0
  while i < @my_list.size
    if @my_list[i].value == val
       return i
    end

    i += 1
  end

  return -1
end

这样只会返回 int 值,不会返回 nil。看起来运行良好。


0
更好的方法是使用times方法,它更简单、更清晰:
def get_index(val)
  @my_list.size.times do |i|
    return i if @my_list[i] == val
  end
  -1
end

更新

或更简单

def get_index(val)
  @my_list.index { |value| value == val } || -1
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接