How to correctly handle one-element array vs scalar

I have a statement in my code where I need to compute the mean of an ND array A along the 1st dimension, which is

M = mean(A,dims=1);

However, sometimes A is just a scalar, in which case an error will be reported, as the “dims” argument is not allowed. What is the correct way of handling this?

Since the central paradigm of Julia is multiple dispatch, it is quite easy to write your code such that different types are handled differently.

Why is it that A is sometimes a scalar and sometimes not? Is there a type instability, or is it predictable from the input types? If the former, you should fix it, but if it’s the latter, you should simply have a different method for the cases where the inputs lead to scalar A.

Perhaps this sounds a bit vague, but your question is also a bit vague. Can you make it a bit more concrete? Do you have a code snippet? Why is the type of A variable?

The most trivial solution is, of course

foo(A::AbstractArray) = mean(A, dims=1)
foo(A::Number) = A
M = foo(A) 
1 Like

Thanks for the response. As I am new from Matlab, I have formed the habit to use simplest possible syntax where certain obvious implied meaning of a statement is automatically interpreted to behave “correctly”. So when I pass a single number, it should be interpreted as a 1-vector, or 1x1 matrix if necessary. But as you suggested, Julia is more rigorous in typing than Matlab, so understandably it takes more effort as you suggested to have these behaviors correctly specified.

if it’s just some script you’re working on, you can hack it by

M = try
        mean(A, dims=1)
    catch
        A
    end

I would suggest being more explicit about scalar vs. matrix operations in Julia and using broadcasting to apply a scalar operation elementwise to a matrix.

Matlab has sin(1.0), but it also has sin([1, 2, 3]) meaning [sin(1) sin(2) sin(3)]. It has to have that, because actually doing [sin(1) sin(2) sin(3)] in Matlab would be very slow, so you have to “vectorize” the sin function.

Julia doesn’t need that. You can do sin(1) or sin.([1, 2, 3]) (notice the . after sin). There is only one sin function needed (the scalar version), but the .() syntax lets you apply it to each element in the vector at no additional cost. That’s because loops in Julia are fast and loops in Matlab are slow, so Matlab has to provide vectorized functions that save you from writing loops yourself.

So if your function is fundamentally a scalar operation, then I would suggest only writing it for scalars. Then you can do my_function.(my_array_of_scalars) to apply it elementwise as necessary.

5 Likes

By the way, Julia actually does have a sin function taking a matrix input, but that’s because the matrix sine is a real thing. So in Julia you can do sin(my_matrix) to compute a matrix sine or you can do sin.(my_matrix) to compute a sine of each element of the matrix separately. That doesn’t work in Matlab because Matlab has to use sin(my_matrix) to mean the elementwise sin. If you want a true matrix sine, you have to download a separate package with a different name.

Ok, tangent over.

2 Likes

Surely you can’t jump straight from sin to tangent, without covering cos?

3 Likes

This works. I did it this way:
*

ndims(A)==0 ? A : mean(A,dims=1)