Nim: Openarray of openarrays: type mismatch for array/seq of arrays/seq

Created on 23 Sep 2018  路  15Comments  路  Source: nim-lang/Nim

We need to use generics due to #9041

func foo[T](x: openarray[openarray[T]]): T =
  x[0][0]

var x: array[2, array[3, int]]
echo x.foo

var y: seq[seq[int]]
echo y.foo
Error: type mismatch: got <array[0..1, array[0..2, int]]>
but expected one of:
func foo[T](x: openArray[openArray[T]]): T

expression: foo(x)
Error messages

Most helpful comment

I don't want to make this decision. I want to provide a convenient interface that allows users to pass in what they have.

All 15 comments

There is no such thing as openarray[openarray[T]]. The complain about this construct, not about the type mismatch.

There is no such thing as openarray[openarray[T]]

That's the point of the issue, isn't it? It would be really useful to accept all of seq[seq[T]], seq[array[N, T]], array[N, seq[T]], array[N, array[M, T]].

@bluenote10 yea I know it would be useful, but it doesn't work.

And it is impossible to make it work?

I am closing this, because my issue superseeds this issue.

@bluenote10 It is better if it is explicity forbidden that if the compiler tries at all costs to shoehorn something in an openarray structure even if the structure isn't made for it.

@krux02 What would be your recommendation for users how to implement nested array/seq parameters without duplicating overloads for array and seq? Is the final goal to support this via concepts e.g. Indexable[Indexable[T]]?

My recommendation is that you decide if you want an openarray[seq[...]] or openarray[array[...]]. If one doesn't work convert to the other via refactoring.

I don't want to make this decision. I want to provide a convenient interface that allows users to pass in what they have.

You can also use a concept for this, I think.

Just to confirm, the baseconcepts to be introduced in https://github.com/nim-lang/Nim/pull/9311 solve the problem nicely:

# taken from the PR
type
  Iterable*[T] = concept c
    for x in items(c): x is T
    for x in mitems(c): x is var T
  Indexable*[T] = concept c
    var i: int
    c[i] is T
    c[i] is var T
    var val: T
    c[i] = val
    c.len is int

proc totalLen[T](nested: Indexable[Indexable[T]]): int =
  for inner in nested:
    result += inner.len

echo totalLen([[1, 2], [3, 4]])
echo totalLen(@[[1, 2], [3, 4]])
echo totalLen([@[1, 2], @[3, 4]])
echo totalLen(@[@[1, 2], @[3, 4]])

Having the Indexable concept makes me wonder if openarray is still needed at all?

@bluenote10 Openarray parameters are always indexed starting from 0. Even if you pass in a parameter, lets say array[5..10, int].
So a concept equivalent to openarray must have low and high (and len) in addition to being Indexable.

Having the Indexable concept makes me wonder if openarray is still needed at all?

Yes, it is. Openarray is not a generic, it is mapped to a (pointer, len) pair and so has different code-size/performance characteristics.

Openarray is not a generic, it is mapped to a (pointer, len) pair and so has different code-size/performance characteristics.

I'm aware of that, so the concept offers more flexibility at the cost of code size. I was going over the usages of openarray in the Nim standard library, and on first glance, for most of the procs it would make sense to change them to Indexable, because they are already generic in T. What will be the rule of thumb to decide between Indexable and openarray? If a proc is generic anyways, use Indexable and openarray for concrete types?

If a proc is generic anyways, use Indexable and openarray for concrete types?

We are still figuring out the rules but your suggestion makes sense.

Was this page helpful?
0 / 5 - 0 ratings