1.0 annoyances and Matlab comparison

Maybe something like blob for unformatted memory blob

Array{T}(blob,7)

or byob for bring your own bits

3 Likes

I imagine a lot of Julia’s users will also write performance sensitive code (that’s why they chose Julia, after all), and I would allow for the possibility that some of them will know what they are doing.

IMO using the length of a variable name to indicate “risky” semantics is not a good design choice, and it is not the way APIs have worked so far in Julia. Especially given that it is exported at the same time, so it is part of the API but ostensibly one will be discouraged from using it because it is long? ArgumentError has the same number of characters, does this mean we should approach it with caution, too?

As I said above, I can live with uninitialized, and I can also accept the reasoning that junk was suggestive of stochastic initialization and was not “dignified” enough.

My primary practical problem with not using uninitialized all the time is the following: suppose I have a function that takes a collection A with eltype T, and calculates a result B::Array which has a similar eltype but a different shape. The result is filled up elementwise, and preallocated at the beginning. The most obvious way I see to start that function is

B = Array{T}(uninitialized, dims)

The alternative I imagine is

B = fill(first(A), dims)

which is clunky and does not express my intent (first(A) is nothing special, I will be overwriting it, but fill needs an element). So even though the first one is more verbose expect I will use it all the time.

I’d use similar(A, dims) in the case you described.

3 Likes

I like uninitialized: it evokes the right mental image and it is not very likely to conflict with user-named variables.

4 Likes

reaallly, who cares? What was the post about, I forgot

2 Likes

Which works great, except for the cases where similar is not defined (eg A is not an AbstractArray).

Julia is considered a performance language, right? All performance languages I’m aware of declare variables uninitialized by default. Even in Lua, all variables point to nil until they are assigned a value or initialized. Since my day-1 using Julia (5 years ago), I declare arrays Array(T,dims) and don’t use zeros (it will be deprecated after all). The language shouldn’t force the user to fill an array with zeros or whatever, when it will be assigned different values later any way. If I wasn’t searching for performance, I’d have stuck with MATLAB. All Julia users, I assume, care about performance and know exactly what they do.

I think perhaps the whole array constructor design should be reconsidered (my recommendation), or just choose an easier name, nil, junk, … I know it’s somehow late, but better late than never.

Personally, I’ve been lately (with 0.7 release) using something like this a lot:

F64(n...) = Array{Float64}(uninitialized, n)
F32(n...) = Array{Float32}(uninitialized, n)
I64(n...) = Array{Int}(uninitialized, n)
Bol(n...) = Array{Bool}(uninitialized, n)

I really miss Fortran’s real A(m,n).

3 Likes

Since I was almost always creating uninitialized vectors, not matrices, of varying types, I made a simple, easy to understand function:

uninit(T, len) = @static isdefined(Base, :uninitialized) ? T(uninitialized, len) : T(len)
create_vector(T, len) = uninit(Vector{T}, len)

This also allows my code to be more readable (IMO), and work the same in both master and earlier releases.

3 Likes

I like the new syntax, but uninitialized is indeed a bit long and hard to type. We could probably find something shorter but with more dignity than junk. Maybe raw? unfilled? blank?

1 Like

junk?

4 Likes

unin + tab is all it takes for me to get uninitialized to appear on 0.7.
Doesn’t work of course if you have other variables that start with unini in your name space.

EDIT:
Something else you can look into:

While I prefer uninitialized over junk, I don’t really care either way.

1 Like

Perhaps we can get out of this dilemma if we are able to redefine fill to work with types the same way as it works with values. For example, the following two statements could be made equal:
A = fill(Float64, m, n)
A = Array{Float64}(uninitialized, m, n).

This way, uninitialized can be left intact and used inside base and packages, without forcing the user to use it or loose performance from calling zeros(m, n) or fill(0.0, m, n).

julia> fill(Float64, 2, 2)
2×2 Array{DataType,2}:
 Float64  Float64
 Float64  Float64
4 Likes

Since when was programming dignified???

3 Likes

The goal was not to protect against uninitialized data via the length of the name, but just by forcing you to be explicit. I do find uninitialized very long though; I would be fine with simply renaming it to uninit.

11 Likes

Which kind of initialization we have to wait after deprecation phase?

Edit:

And BTW could you explain what exactly do you like? What will be more simple or more clear?

Why not to keep default Array constructor to use uninitialized memory?

2 Likes

:+1:

I guess it won’t be optional, so could there be other values to pass here, like a valid default value &/or the original uninit / junk / inseclogindeets (lol). A default would probably be handy for arrays of Union types, and could even be performant if done lazily? ie set or return the default value on read if still undefined / unwritten, like a hidden(?) union of type x + initialized boolean that will fall back to type x on true (initialized)

I’d also really like to see a convenience constructor for constructing an arbitraily initialized array complementing ones, zeros, etc.

I’d really like a naive empty(T, dims...) from a users perspective. But I guess I can also live with uninit(T, dims...) given the fact that there is an empty function already with a different meaning.

3 Likes

See Array{T}(initialization,...) syntax - #2 by mbauman.

1 Like

You would need to use e.g. OffsetArray{T}(uninitialized, dims...) for any AbstractArray other than Arrays. Creating a bunch of Array specific functions when there are so many other type of AbstractArrays seems less good than having functions that work for all of them.

2 Likes