35

Given a Julia object of composite type, how can one determine its fields?

I know one solution if you're working in the REPL: First you figure out the type of the object via a call to typeof, then enter help mode (?), and then look up the type. Is there a more programmatic way to achieve the same thing?

Yly
  • 2,150
  • 4
  • 20
  • 33
  • 5
    a hack that I use: at the REPL, for object `x`, type `x.` (that's `x` followed by a dot `.`) and then hit TAB once or twice. that asks Julia to autocomplete the command. Julia will then show you the fields of `x`, assuming that it has any. – Kevin L. Keys Jan 17 '17 at 01:39

2 Answers2

55

For v0.7+

Use fieldnames(x), where x is a DataType. For example, use fieldnames(Date), instead of fieldnames(today()), or else use fieldnames(typeof(today())).

This returns Vector{Symbol} listing the field names in order.

If a field name is myfield, then to retrieve the values in that field use either getfield(x, :myfield), or the shortcut syntax x.myfield.

Another useful and related function to play around with is dump(x).

Before v0.7

Use fieldnames(x), where x is either an instance of the composite type you are interested in, or else a DataType. That is, fieldnames(today()) and fieldnames(Date) are equally valid and have the same output.

Colin T Bowers
  • 18,106
  • 8
  • 61
  • 89
  • If I get the first field of a Struct: `fieldnames(s)[1]` that will be a Symbol. But I cannot use the result of this expression to get the value of that field like: `s.fieldnames(s)[1]` although s.:field works. `getfield` works as expected. – karatedog Jul 20 '18 at 20:28
  • `s.fieldnames(s)[1]`, roughly speaking, parses to: find the field literally named `fieldnames` in `s`, and then call it as if it is a function with `(s)` as argument, and then get the first element of the result, ie `[1]` (which is obviously not what you are trying to do). If you have the actual fieldname stored in some symbol `a`, then use `getfield(s, a)`. It is true that `s.:a` also works, but this is not idiomatic Julia, so others will probably have a hard time reading your code. I've updated my answer to try and clear up any ambiguity. – Colin T Bowers Jul 22 '18 at 22:43
  • 1
    above link is broken – liang Dec 04 '20 at 08:05
  • @liang [updated link](https://docs.julialang.org/en/v1/devdocs/reflection/) – Colin T Bowers Dec 04 '20 at 10:03
  • 1
    N.b. if you want the types of the fields, `fieldtypes(T)`. And if you want both the field names and their types, `NamedTuple{fieldnames(T)}(fieldtypes(T))`, which for `Rational` would give `(num = Integer, den = Integer)`. – BallpointBen May 08 '21 at 17:17
8

suppose the object is obj,

you can get all the information of its fields with following code snippet:

T = typeof(obj)
for (name, typ) in zip(fieldnames(T), T.types)
    println("type of the fieldname $name is $typ")
end

Here, fieldnames(T) returns the vector of field names and T.types returns the corresponding vector of type of the fields.

novatena
  • 186
  • 3