How to use type parameter variables across multiple parametric types

Hello Julia folk,

I am testing something very simple, a dot product, and I want to ensure, it gets two arrays (or vectors) of the same length. This attempt does not work:

function dot_product{N::UInt64}(vec1::Array{Float64, N}, vec2::Array{Float64, N})
	return sum((x,y) -> x * y, zip(vec1, vec2))

and neither this one:

function dot_product(vec1::Array{Float64, N}, vec2::Array{Float64, N}) where N :: UInt64
	return sum((x,y) -> x * y, zip(vec1, vec2))

(problems with the where clause).

Is Julia able to infer and work with types like that? How to do it?

As you pointed out, I accidentally wrote “length” but I meant “dimensional length” (dimensions) in my head. Sorry.

the N parameter of an array is the number of dimensions not the length. all vectors are Array{T,1}

1 Like

Oh, thank you for the clarification. I replaced it with AbstractVector.
But concerning this question, how can I guarantee, that parameter 1 and parameter 2 both share an Array with same number of dimensions?

You can either use StaticArrays, or do a runtime length check.

1 Like

Okay, so Julia does not officially support generic variables for concrete type parameters, right?
(For example, in languages with template parameterization, they often allow for template parameters which are constants or concrete values, not just types.)

The proper functionality in my original post can be written as

function dot_product(x::AbstractVector, y::AbstractVector)
    return sum(pair -> pair[1] * pair[2], zip(x,y))

I don’t know, why Julia does not destructure a single tuple argument into multiple arguments, the pair thing is needed, but it gives me the same results like · from LinearAlgebra package.

What do you think the N stands in for?

Also, doesn’t destructing work?

function dot_product(x::AbstractVector, y::AbstractVector)
    return sum((xi,yi) -> xi * yi, zip(x,y))

Can’t check on phone.

Yes, bitstype values are supported as type parameters, including integers, as you can see in Array{Float64, 2} for example.

But the 2 stands for number of dimensions (matrix), not length.

Also you cannot use the syntax {N::Int} for restricting type parameters, only <:T is allowed, meaning that N must be unrestricted.

The syntax foo{T}(...) for functions is also not valid, except for type constructors.

I am talking about concrete values as variables for type parameters, that means N as an integer value, not a type. In C++ I can just write

template<int N> float dot_product(std::array<float,N> x, std::array<float,N> y) ...

I don’t know at the moment, if conventional C++ compilers would infer the N automatically, but in D for example, it is able to infer it for some cases.

Compile-time variables for concrete values make a type system more flexible and better usable because you get earlier compiler warnings and don’t need to write explicit asserts or similar. (Type annotations are basically just compile-time-evaluated assertion shortcuts.)

My question only was how to do that in Julia, when supported.

Yes, that’s what I said. See for example the 2 in Array{Float64, 2}.

In a function signature you could use it as

foo(x::AbstractArray{Int, N}) where {N} = ... 

to match any dimensionality, or a specific value to restrict it.

Nice! Thank you! That one worked:

function dot_product(x::AbstractArray{Float64,N}, y::AbstractArray{Float64,N}) where {N}

If I want to pass someone a reference, under what kind of term I would find documentation of this notation using where {N}?

Just be aware, the N does not have anything to do with size or length, only number of dimensions.

Under where: Essentials · The Julia Language