I'm making Serie
- an immutable time-series with missing values. But it can't be initialized without nulls.
class Serie(T)
def initialize(@array = Array(T?).new); end
def self.[](*values : T); Serie(T).new values.to_a.as(Array(T?)) end
def self.[](*values : T?); Serie(T).new values.to_a end
end
Serie[1, nil, 2] # Works
Serie[1, 2] # Throws an Error
Also, it can't be initialized with array without explicit types and throws an error. Although it seems like there's enough information to infer the type.
Serie.new(Int32?)([1, nil, 2]) # Works
Serie.new([1, nil, 2]) # Throws an Error
P.S.
I'm using a hack to initialize it with Serie.self[...]
do you know a way to initialize it as Array-like object Serie{1, 2}
but avoid adding <<
method because it's static immutable time series data?
Array(T).new.as(Array(T?))
can't work because Array(T?)
is not a valid restriction of Array(T)
(Crystal's generics can't express covariance yet).
In order to transform from Array(T)
to Array(T?)
you need to actually create a new array of type Array(T?)
and copy the items over. One way to do that is values.map(&.as(T?))
.
(Technically, you could also use unsafe type casts to get an instance of This is not actually true, the binary representation is different because of the union type.Array(T?)
pointing at the same memory as the Array(T)
because the binary representation is identical; but it easily breaks when adding nil
values via the nilable instance.)
I'm using a hack to initialize it with Serie.self[...] do you know a way to initialize it as Array-like object Serie{1, 2} but avoid adding << method because it's static immutable time series data?
Adding a self.[]
method is probably the best workaround for that. There is a discussion about changing the implementation of array-like literals to call a single method instead of transforming to a series of <<
calls in #5703.