# Why will we have to say fieldnames(typeof(v)) instead of fieldnames(v)?

**URL:** <https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129>\
**Category:** General Usage\
**Created:** [February 17, 2018, 3:58pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129 "2018-02-17T15:58:44Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 18, 2018, 12:14pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/21 "2018-02-18T12:14:31Z")

</div>

Sorry for being dense, but what is this ambiguity? I don’t understand it.

If the input is a type, then return the field names. If it is not, then return the field names of the type of the input.

I’m not upset about this change, and I can appreciate the argument that the new behaviour is a bit more logically rigorous, but I flat out cannot see where the ambiguity is.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 12:37pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/22 "2018-02-18T12:37:00Z")

</div>

> [@DNF](#):
>
> If the input is a type, then return the field names. If it is not, then return the field names of the type of the input.

Because a type is also a value and it’s type has it’s own fields.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 18, 2018, 12:39pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/23 "2018-02-18T12:39:45Z")

</div>

So what? You return the field names of whatever type is passed in, except when it’s not a type at all.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 12:59pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/24 "2018-02-18T12:59:53Z")

</div>

> [@DNF](#):
>
> So what?

So that’s the ambiguity. This is literally your question.  
Edit: and since it was apparently not obvious to everyone, I don’t like your tone. Please be more polite.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [February 18, 2018, 1:08pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/25 "2018-02-18T13:08:47Z")

</div>

> [@DNF](#):
>
> You return the field names of whatever type is passed in, except when it’s not a type at all.

So simple, so logical, so non-breaking.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 1:15pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/26 "2018-02-18T13:15:05Z")

</div>

> [@joa-quim](#):
>
> So simple, so logical, so non-breaking.

And more importantly, so ambiguous and so dangerous.

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [February 18, 2018, 2:07pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/27 "2018-02-18T14:07:53Z")

</div>

As someone working with types as values a lot I’m happy to see this change. Let’s say, we have a type like this:

```julia
struct Foo 
    x::Int 
end

foo = Foo(108)

```

It looks appealing to write `fieldnames(Foo)` or `fieldnames(foo)` to get the list `[:x]`. We can use this meta facility to write generic code like this:

```julia
function dump_object(x)
    for f in fieldnames(x)
        println("$f: $(getfield(x, f))")
    end
end
dump_object(Foo(3)) # ==> "x: 3"

```

This is actually what I used a couple of times for serialization and various meta-programming tasks. What sounds good about this function is that it’s general enough to apply to literally any value in Julia, right? Not quite: what if we want to dump the type `Foo` instead of the value?

```julia
dump_object(Foo)
# ERROR: type DataType has no field x
# Stacktrace:
# [1] dump_object(::Type{T} where T) at ./REPL[14]:3

```

D’oh! Even though we passed a type into `dump_object`, `fieldnames` thought we wanted to get the list of fields of its instance. To make this function really general, we need to use `fieldnames(typeof(x))` instead:

```julia
function dump_object(x)
    for f in fieldnames(typeof(x))
        v = isdefined(x, f) ? getfield(x, f) : "<undefied>"
        println("$f: $v")
    end
end
dump_object(Foo(42)) # ==> [:x]
dump_object(Foo) # ==> long list of DataType's fields

```

I’ve got into this trap several times, sometimes in packages that I’ve written months and years ago and considered stable. So in all my new code I try to never use `fieldnames(v)`, exactly because it’s ambiguous and hard to predict in practice. Julia 0.7 will also help me to find this issue in old code, which sounds good.

At the same time, I like the idea of having `fieldnames_t()` as a shorthand for the `fieldnames(typeof(...))` pattern.

---

<div class="post-metadata">

**Author:** ![NaOH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/naoh/32/5632_2.png) [@NaOH](https://discourse.julialang.org/u/NaOH)\
**Post date:** [February 18, 2018, 2:13pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/28 "2018-02-18T14:13:10Z")

</div>

This is a similar issue to my answer back here:

- [julia - How to check a type for mutability - Stack Overflow](https://stackoverflow.com/questions/40706962/how-to-check-a-type-for-mutability)

```julia
julia> using Base: @pure

julia> @pure is_mutable(x::DataType) = x.mutable # for a type
is_mutable (generic function with 1 method)

julia> @pure is_mutable(x) = is_mutable(typeof(x)) # for a value
is_mutable (generic function with 2 methods)

julia> @pure is_immutable(x) = !is_mutable(x)
is_immutable (generic function with 1 method)

```

You could use `DataType` to dispatch on it and use the generic method for everything else.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [February 18, 2018, 2:14pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/29 "2018-02-18T14:14:48Z")

</div>

Julia’s dispatch mechanisms allow you to define different implementations based on the input type, but the guiding principle should be that all the methods for a given function should _mean_ the same thing. Obviously that’s pretty loosely-defined, so I try to think about what the help string for a given generic function should be, and minimise the number of “except when” clauses you’d need.

So in this case it seems like the new behavior is “`fieldnames(x)` returns a list of the fields of `x`”. You’re arguing for

“`fieldnames(x)` returns a list of the fields of `typeof(x)`. `fieldnames(x::Type)` returns the fields of `x`.”

This sort of punning is discouraged because while it may make things more convenient when you know a prori the type of `x`, it makes it harder to write generic code that means the same thing regardless of the type of `x`.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 3:09pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/30 "2018-02-18T15:09:15Z")

</div>

> [@NaOH](#):
>
> You could use DataType to dispatch on it and use the generic method for everything else.

Note that this will lead to wrong answer for types like `Array`.

> [@ssfrr](#):
>
> Obviously that’s pretty loosely-defined,

It is indeed loosely-defined in general but it’s very clear in this case. If the function can have two different meanings for **the same input** than, 1) it’s ambiguous 2) it definately is not doing a single thing.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [February 18, 2018, 3:56pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/31 "2018-02-18T15:56:37Z")

</div>

Perhaps the problem can be solved by using two appropriate function names for the different meanings and not overloading a single function name with qualitatively distinct actions. As an example, apart from **`fieldnames`** , there is also the **`names`** function. If we define,

```julia
Base.names(v) = fieldnames(typeof(v))

```

then we get the second operation with a user-friendly name. The upshot **`names`** is already defined for Modules with a sort-of isomorphic action: returns a list of symbols which can be **`.`** -indexed to the _value_ of the parameter.

For example:

```julia
julia> names(Base.Random)
21-element Array{Symbol,1}:
 :AbstractRNG    
 :GLOBAL_RNG     
 :MersenneTwister
 :Random         
 :RandomDevice   
 :bitrand        
 :rand           
⋮ 
 :randsubseq     
 :randsubseq!    
 :shuffle        
 :shuffle!       
 :srand          

julia> names(1:10)
2-element Array{Symbol,1}:
 :start
 :stop 

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 4:24pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/32 "2018-02-18T16:24:23Z")

</div>

I’ve said many times that this is certainly fine. It just doesn’t have to be both in base and since the one operation on the type can be used to define the one operating on values but not the other way around, the one in base should be the one operating on types. Checking the field of a value/type or provide other necessary info about the type is also a help system feature as mentioned above.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 4:25pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/33 "2018-02-18T16:25:42Z")

</div>

Also, you shouldn’t be overriding `names`. For one you are basically introducing type piracy if you define it in your own code and if you want to put it in base you are creating a different ambiguity.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 18, 2018, 4:38pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/34 "2018-02-18T16:38:18Z")

</div>

> [@yuyichao](#):
>
> So that’s the ambiguity. This is literally your question.

That’s not what ‘ambiguity’ means. That is just a branch. `if A do B else do C`. It’s only ambiguous if `A` is not definitively either `true` or `false` in each case. The statement `A` here is “x is a type”. Are you really saying that this does not always have a definitive answer?

If we ask a related question: “is x a type or is it a value?”, _that_ is ambiguous.

I think @ssfrr and @dfdx make good arguments for why the new behaviour is sensible, but none of them have anything to do with ambiguities, so I don’t think it makes sense to advance that as an argument.

Unless, of course, there really _is_ some case where `A` is ambiguous, but that was my original question, which has not been answered.

---

<div class="post-metadata">

**Author:** ![wookyoung](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wookyoung/32/157_2.png) [@wookyoung](https://discourse.julialang.org/u/wookyoung)\
**Post date:** [February 18, 2018, 5:47pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/35 "2018-02-18T17:47:53Z")

</div>

how about `Base.propertynames`  
[https://docs.julialang.org/en/latest/base/base/#Base.propertynames](https://docs.julialang.org/en/latest/base/base/#Base.propertynames)

refer this PR  
[https://github.com/JuliaLang/julia/pull/25311](https://github.com/JuliaLang/julia/pull/25311)

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 5:54pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/36 "2018-02-18T17:54:45Z")

</div>

> [@DNF](#):
>
> That’s not what ‘ambiguity’ means. That is just a branch. if A do B else do C.

It is, your branch is ignoring the ambiguity and doesn’t prove anything at all. It is of course always possible to force the ambiguous case to mean one of its meaning but it’s a terrible implementation and it does not mean the ambiguity is not there.

> [@DNF](#):
>
> I think @ssfrr and @dfdx make good arguments for why the new behaviour is sensible, but none of them have anything to do with ambiguities, so I don’t think it makes sense to advance that as an argument.

No, none of their arguments makes sense if there’s no ambiguity. See below.

And I’ll repeat again that there are two different things here.

1. Get the field names of a type, this means returning empty for `Array`, `Int`, and error for `[]`.
2. Get the field names of a value, this means returning the fieldnames for the type `UnionAll`, `DataType` and `Vector{Any}` for the above three cases.

The examples given above shows that there are already two cases where both meaning are valid and that _IS_ ambiguity. In fact, this is necessarily true for everything that the first meaning is valid (I.e. all types) since

> [@yuyichao](#):
>
> a type is also a value and it’s type has it’s own fields.

If there isn’t this ambiguity, one would never think about to write any generic code that require a specific behavior for all objects so that wouldn’t be a valid arguments at all and the function that implement these based on dispatch wouldn’t be clearly doing two different things.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 18, 2018, 8:07pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/37 "2018-02-18T20:07:45Z")

</div>

> [@yuyichao](#):
>
> 1. Get the field names of a type, this means returning empty for `Array`, `Int`, and error for `[]`.
> 2. Get the field names of a value, this means returning the fieldnames for the type `UnionAll`, `DataType` and `Vector{Any}` for the above three cases.

`Array` is a type, `Int` is a type, `[]` is _not_ a type, `UnionAll` is a type, `DataType` is a type, `Vector{Any}` is a type. No ambiguity. They are _also_ values, but whether or not they are types is unambiguous (???).

Unfortunately, I don’t get it, and possibly won’t. Too bad, because I’m curious, but since I don’t really mind the change, I give up now.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [February 18, 2018, 8:22pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/38 "2018-02-18T20:22:20Z")

</div>

Here’s an example of how the old behavior could be confusing in generic code:

```julia
julia> firstfieldname(x) = fieldnames(x)[1]
       getfirstfield(x) = getfield(x, 1)
getfirstfield (generic function with 1 method)

julia> firstfieldname(1im)
┌ Warning: `fieldnames(v)` is deprecated, use `fieldnames(typeof(v))` instead.
│ caller = firstfieldname(::Complex{Int64}) at REPL[13]:1
└ @ Main REPL[13]:1
:re

julia> getfirstfield(1im)
0

julia> firstfieldname(Complex{Int})
:re

julia> getfirstfield(Complex{Int})
Complex

```

The object `Complex{Int}` _does not_ have a field named `re`. It’s first field name is, well, the name of the type:

```julia
julia> fieldnames(typeof(Complex{Int}))
(:name, :super, :parameters, :types, :names, :instance, :layout, :size, :ninitialized, :uid, :abstract, :mutable, :hasfreetypevars, :isconcretetype, :isdispatchtuple, :isbitstype, :zeroinit, :isinlinealloc, Symbol("llvm::StructType"), Symbol("llvm::DIType"))

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 18, 2018, 8:56pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/39 "2018-02-18T20:56:41Z")

</div>

I never said that checking a type is ambiguous that’s also completely irrelevant to the whle discussion.

I’m saying that the two meanings of the function are ambiguous and you should realize that the meaning of the function is the whole point of this thread, starting from the very title of it.

> [@DNF](#):
>
> Unfortunately, I don’t get it, and possibly won’t.

Edit: I don’t like your tone. Please be more constructive on a conversation you started.

> [@DNF](#):
>
> I give up now.

Good to know.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 19, 2018, 12:18pm UTC](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129/40 "2018-02-19T12:18:01Z")

</div>

I think I finally understand what you are saying. By ‘ambiguity’, you refer directly to the fact that the `fieldnames` function has two different meanings depending on whether you interpret the input as a value or as a type. Correct?

If so, that’s an ok argument for making this change, because it can be confusing, and is error-prone, like @mbauman demonstrated .

And in that case, you are simply using the word “ambiguous” incorrectly. This is not an example of an ambiguity. As far as I can tell, that is the origin of this whole misunderstanding.

[Previous page](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129.md?page=1)

[Next page](https://discourse.julialang.org/t/why-will-we-have-to-say-fieldnames-typeof-v-instead-of-fieldnames-v/9129.md?page=3)
