Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve show for 0-dim array #33206

Merged
merged 11 commits into from
Oct 3, 2019
Merged

Conversation

nickrobinson251
Copy link
Contributor

@nickrobinson251 nickrobinson251 commented Sep 9, 2019


Before (on version 1.2.0):

# repl display
julia> a = zeros(Int)
0-dimensional Array{Int64,0}:
0

julia> b = collect('b')
0-dimensional Array{Char,0}:
'b'

julia> c = fill(undef)  
0-dimensional Array{UndefInitializer,0}:
array initializer with undefined values

# show
julia> show(a)
0
julia> show(b)
'b'
julia> show(c)
array initializer with undefined values

# repr
julia> repr(a)
"0"

julia> repr(b)
"'b'"

julia> repr(c)
"array initializer with undefined values"

# leads to confusing test output
julia> @test a == 0
Test Failed at REPL[8]:1
  Expression: a == 0
   Evaluated: 0 == 0
ERROR: There was an error during testing

this PR: [EDIT: updated below]

# repl display (unchanged)
julia> a = zeros(Int)
0-dimensional Array{Int64,0}:
0

julia> b = collect('b')
0-dimensional Array{Char,0}:
'b'

julia> c = fill(undef)
0-dimensional Array{UndefInitializer,0}:
array initializer with undefined values

# show
julia> show(a)
fill(0)
julia> show(b)
fill('b')
julia> show(c) # EDIT: changed below; now `fill(array initializer with undefined values)`
fill(undef)

# repr
julia> repr(a)
"fill(0)"

julia> repr(b)
"fill('b')"

julia> repr(c)  # EDIT: changed below; now `fill(array initializer with undefined values)`
"fill(undef)"

# clearer test output
julia> @test a == 0
Test Failed at REPL[21]:1
  Expression: a == 0
   Evaluated: fill(0) == 0
ERROR: There was an error during testing

@nickrobinson251
Copy link
Contributor Author

@KristofferC makes the good point that fill(undef) and Array{Any,0}(undef) are probably never intended i.e

you tried to fill an array with undefined values and mistakenly used the undef array initializer

So for these cases, what should we print?

one option is something that doesn't parse, e.g. "fill(#undef)" (which is an incomplete expression) or "fill(array initializer with undefined values)" (which obvious isn't valid syntax)

@KristofferC
Copy link
Sponsor Member

Array{Any,0}(undef)

is just an unitialized 0 dimensional array:

julia> a = Array{Any,0}(undef)
0-dimensional Array{Any,0}:
#undef

julia> a[]
ERROR: UndefRefError: access to undefined reference
Stacktrace:

fill(undef)

is an initialized 0-dimensional array with the uninitialized-array initializer in it.

julia> b = fill(undef)
0-dimensional Array{UndefInitializer,0}:
array initializer with undefined values

julia> b[]
array initializer with undefined values

@nickrobinson251
Copy link
Contributor Author

nickrobinson251 commented Sep 10, 2019

okay, how do things look now? we have

julia> x = fill(undef)
0-dimensional Array{UndefInitializer,0}:
array initializer with undefined values

julia> y = Array{Any,0}(undef)
0-dimensional Array{Any,0}:
#undef

julia> repr(x)
"fill(array initializer with undefined values)"

julia> repr(y)
"fill(#undef)"

Edit:
replacing the old behaviour

julia> repr(x)
"array initializer with undefined values"

julia> repr(y)
"#undef"

this seems consistent and reasonable to me - but keen to hear opinions :)

Thanks for the help @KristofferC !

@nickrobinson251 nickrobinson251 changed the title WIP: Improve show for 0-dim array Improve show for 0-dim array Sep 10, 2019
@nickrobinson251
Copy link
Contributor Author

there was one related test failure, where the old output was hard coded

Error in testset offsetarray:
Test Failed at /Users/julia/buildbot/worker-tabularasa/tester_macos64/build/share/julia/test/offsetarray.jl:223
  Expression: String(take!(io)) == targets2[n + 1]
   Evaluated: "(fill(1.0), fill(1.0))" == "(1.0, 1.0)"

So I have updated that test :)

@JeffBezanson
Copy link
Sponsor Member

It really seems to me that repr(fill(undef)) should be fill(undef). There is no point to printing something like fill(array initializer with undefined values) --- it has all the ugliness of parseable output without being parseable. I don't think it matters that the user probably didn't intend to write that --- having mistakenly written it, we might as well at least print it correctly.

base/arrayshow.jl Outdated Show resolved Hide resolved
@JeffBezanson
Copy link
Sponsor Member

Adding to that, it looks like the existing show method for UndefInitializer should be a text/plain MIME show method.

@JeffBezanson JeffBezanson added domain:arrays [a, r, r, a, y, s] domain:display and printing Aesthetics and correctness of printed representations of objects. labels Sep 10, 2019
@nickrobinson251
Copy link
Contributor Author

There is no point to printing something like fill(array initializer with undefined values) --- it has all the ugliness of parseable output without being parseable.

Adding to that, it looks like the existing show method for UndefInitializer should be a text/plain MIME show method.

Yep, totally agree on all these points 👍

As i think you've seen, I made the undef changes in the separate PR #33211 (just to keep any issues distinct) -- prompted by exactly this -- sorry, should have linked them earlier :)

base/arrayshow.jl Outdated Show resolved Hide resolved
base/arrayshow.jl Outdated Show resolved Hide resolved
@JeffBezanson JeffBezanson added the status:triage This should be discussed on a triage call label Sep 12, 2019
@JeffBezanson
Copy link
Sponsor Member

A couple issues from triage:

  • Possibly print Array{T,0}(undef) instead of fill(#undef) ?
  • The fill(x) printing doesn't show the array element type; maybe use a different printing if the eltype is not the same as typeof(x)?

@nickrobinson251
Copy link
Contributor Author

  • Possibly print Array{T,0}(undef) instead of fill(#undef) ?
  • The fill(x) printing doesn't show the array element type; maybe use a different printing if the eltype is not the same as typeof(x)?

Yeah, sounds good to me 👍 Think it adds a small bit of extra complexity but means we should get eval(Meta.parse(repr(x))) == x for all cases (pretending that == when values are #undef).

@nickrobinson251
Copy link
Contributor Author

The fill(x) printing doesn't show the array element type; maybe use a different printing if the eltype is not the same as typeof(x)?

On second thoughts, how does one construct a Array(T1,0}(x::T2) with T1 != T2 except with undef?

@nickrobinson251
Copy link
Contributor Author

nickrobinson251 commented Sep 13, 2019

After the latest commit (and rebased to include #33211) we have:

julia> for x in (:(zeros(Int32)), :(collect('b')), :(fill(nothing)), :(BitArray(0)), :(fill(undef)), :(Array{String, 0}(undef)), :(Array{Int32, 0}(undef)))
           println("input: ", x)
           println("show:  ", eval(x))
           println()
       end
input: zeros(Int32)
show:  fill(0)

input: collect('b')
show:  fill('b')

input: fill(nothing)
show:  fill(nothing)

input: BitArray(0)
show:  fill(false)

input: fill(undef)
show:  fill(UndefInitializer())

input: Array{String, 0}(undef)
show:  Array{String,0}(UndefInitializer())

input: Array{Int32, 0}(undef)
show:  fill(210687536)

As the BitArray case shows, for non-Arrays, the show/repr will show how to construct an equal value but not of the same type

julia> x = BitArray(0)
0-dimensional BitArray{0}:
0

julia> repr(x)
"fill(false)"

julia> x == eval(Meta.parse(repr(x)))
true

julia> x === eval(Meta.parse(repr(x)))
false
julia> struct MyZeroDimArray{T} <: AbstractArray{T, 0}
           data::Array{T, 0}
       end

julia> Base.size(A::MyZeroDimArray) = size(A.data)

julia> Base.getindex(A::MyZeroDimArray, indices...) = A.data[indices...]

julia> x = ZeroDimArray(fill(0))
0-dimensional MyZeroDimArray{Int64}:
0

julia> repr(x)
"fill(0)"

julia> x == eval(Meta.parse(repr(x)))
true

julia> x === eval(Meta.parse(repr(x)))
false

I think this is fine, since we cannot know what is a valid constructor for these types, e.g. BitArray{0}(0) and MyZeroDimArray{Int64}(0) are not valid.


Please let me know how this seems, and if I can improve things further :)

@nickrobinson251
Copy link
Contributor Author

bump :)

@nickrobinson251
Copy link
Contributor Author

(^just resolving merge conflicts in NEWS)

@stevengj
Copy link
Member

(The "triage" label means that it is flagged to get a decision soon, no need to bump.)

test/show.jl Outdated Show resolved Hide resolved
@mbauman mbauman added the status:merge me PR is reviewed. Merge when all tests are passing label Oct 3, 2019
@JeffBezanson
Copy link
Sponsor Member

Triage says merge when CI is done.

@JeffBezanson JeffBezanson merged commit 979bf43 into JuliaLang:master Oct 3, 2019
@nickrobinson251
Copy link
Contributor Author

Thanks for all the help on this!

@nickrobinson251 nickrobinson251 deleted the npr/0dim-array-show branch October 3, 2019 19:32
@Keno Keno removed the status:triage This should be discussed on a triage call label Feb 27, 2020
@DilumAluthge DilumAluthge removed the status:merge me PR is reviewed. Merge when all tests are passing label Jan 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:arrays [a, r, r, a, y, s] domain:display and printing Aesthetics and correctness of printed representations of objects.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

show of 0-dimensional array misleading
9 participants