# Restriction on field names in a user-defined composite type?

**URL:** <https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 6, 2017, 7:37pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944 "2017-02-06T19:37:38Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![BVPs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bvps/32/2190_2.png) [@BVPs](https://discourse.julialang.org/u/BVPs)\
**Post date:** [February 6, 2017, 7:37pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/1 "2017-02-06T19:37:38Z")

</div>

Hello! I want to define my own composite type for my dataset, e.g., the following is a simpler version of what I want to define:

```julia
type MyData
 data::Matrix{Float64}
 length::Int64
 size::Tuple{Int64,Int64}
end

```

When I wrote inner constructors for this type, I got an error, and apparently, julia does not like the field names such as `length` and `size` since they are predefined function names in the `Base` module. Can we get away from this kind of restrictions? Of course if I replace `length` and `size` in `MyData` by `len` and `dsize`, everything works. But in general, we should have flexibility in naming fields of any composite types. I would appreciate your comments!  
Best,  
BVPs

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [February 6, 2017, 8:00pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/2 "2017-02-06T20:00:33Z")

</div>

Works for me on Julia 0.5:

```julia
julia> type MyData
        data::Matrix{Float64}
        length::Int64
        size::Tuple{Int64,Int64}
       end

julia> t = MyData(rand(3,3), 4, (5,5))
MyData([0.399807 0.051389 0.0959585; 0.42537 0.215592 0.777495; 0.293881 0.0591327 0.335123],4,(5,5))

julia> t.length
4

julia> t.size
(5,5)

julia> t.data
3×3 Array{Float64,2}:
 0.399807 0.051389 0.0959585
 0.42537 0.215592 0.777495
 0.293881 0.0591327 0.335123

```

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [February 6, 2017, 8:01pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/3 "2017-02-06T20:01:50Z")

</div>

Ah, didn’t see that it was the inner constructor that was the problem. It’s impossible to help without seeing what you tried, though.

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [February 6, 2017, 8:17pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/4 "2017-02-06T20:17:35Z")

</div>

I think you might be mistaken about what the problem is. Having field names that conflict with exports from Base is not an issue, regardless of whether there are inner constructors.

It would be very helpful if you could post more context so we could help diagnose the problem.

---

<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 6, 2017, 8:29pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/5 "2017-02-06T20:29:03Z")

</div>

This works for me on 0.6

```julia
julia> type MyData
           data::Int
           length::Int
           size::Int
           MyData(data, length, size) = new(data, length, size)
       end

julia> MyData(1, 2, 3)
MyData(1, 2, 3)

```

Of course since I also use them as argument names, they shadow the global names and you can’t use them directly as global functions anymore.

---

<div class="post-metadata">

**Author:** ![BVPs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bvps/32/2190_2.png) [@BVPs](https://discourse.julialang.org/u/BVPs)\
**Post date:** [February 6, 2017, 9:21pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/6 "2017-02-06T21:21:42Z")

</div>

Hi, @dpsanders and @yuyichao. Thanks a lot for your feedback. I need to give you a bit more detailed type definition, which is still simpler than my real type, but it already shows the problem. Let me define my type and constructors as follows (note: they are still a bit artificial):

```julia
type MyData
    data1::Matrix{Float64}
    data2::Matrix{Float64}
    length::Int64
    size::Tuple{Int64,Int64}

    MyData(data1,data2,length,size) =
      if isempty(data1)
        error("data cannot be empty!")
      elseif size(data1,1) != size(data2,1)
        error("inconsistent number of rows!")
      else
        new(data1, data2, length, (size(data1,1),size(data1,2)+size(data2,2)))
      end
end

MyData(data1) = MyData(data1, Matrix{Float64}(), size(data1,1), size(data1))
MyData(data1,data2) = MyData(data1, data2, size(data1,1), (size(data1,1),size(data1,2)+size(data2,2)))

```

Now, in my julia session, I got the following error:

```julia
tmp=MyData(eye(2), eye(2))
>MethodError: objects of type Tuple{Int64,Int64} are not callable

```

and the error points to the line: `elseif size(data1,1) != size(data2,1)`.

Note that if I replace the fieldname `size` in `MyData` by `datasize`, I don’t get any error and it works correctly.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 6, 2017, 9:24pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/7 "2017-02-06T21:24:56Z")

</div>

Can’t you use `Base.size`?

---

<div class="post-metadata">

**Author:** ![BVPs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bvps/32/2190_2.png) [@BVPs](https://discourse.julialang.org/u/BVPs)\
**Post date:** [February 6, 2017, 9:30pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/8 "2017-02-06T21:30:05Z")

</div>

Thanks, @kristoffer.carlsson !  
It works if I replace my use of the function `size` in the **inner constructor** by `Base.size`. Then, I can use the fieldname `size` in `MyData`. But I have one question. In my **outer constructors** , i.e.,

```julia
MyData(data1) = MyData(data1, Matrix{Float64}(), size(data1,1), size(data1))
MyData(data1,data2) = MyData(data1, data2, size(data1,1), (size(data1,1),size(data1,2)+size(data2,2)))

```

I didn’t have to replace `size` function by `Base.size` function. Why the outer constructors accept this while the inner constructor does not?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 6, 2017, 9:35pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/9 "2017-02-06T21:35:39Z")

</div>

Because you don’t have an argument named `size` in those functions so you are not shadowing the exported `Base.size`.

---

<div class="post-metadata">

**Author:** ![BVPs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bvps/32/2190_2.png) [@BVPs](https://discourse.julialang.org/u/BVPs)\
**Post date:** [February 6, 2017, 9:46pm UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/10 "2017-02-06T21:46:29Z")

</div>

Thanks a lot, @kristoffer.carlsson . May I ask you one more question? In my definition of `MyData` type, the most critical input arguments are `data1` followed by `data2`. The correct values of the fields `length` and `size` in `MyData` object can be determined completely once `data1` and `data2` are given. What I want to do is like my outer constructor, i.e., `tmp=MayData(data1,data2)` automatically fills the correct values of `tmp.length` and `tmp.size`. To do so, do I still need to write the inner constructor and outer constructors like I did? Is there any better way to achieve the same? I feel my current code is a bit awkward.  
Thanks for your help!  
BVPs

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [February 7, 2017, 1:34am UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/11 "2017-02-07T01:34:17Z")

</div>

You can just write the inner constructor with 2 arguments (data1, data2), like you did for the outer constructor:

```julia
type MyData
    data1::Matrix{Float64}
    data2::Matrix{Float64}
    length::Int64
    size::Tuple{Int64,Int64}

    function MyData(data1::Matrix{Float64}, data2::Matrix{Float64})
        if isempty(data1)
            error("data cannot be empty!")
        elseif size(data1,1) != size(data2,1)
            error("inconsistent number of rows!")
        else
            new(data1, data2, Base.size(data1,1), (Base.size(data1,1), Base.size(data1,2)+size(data2,2)))
        end
    end
end

```

If you want a single argument (data1) constructor, you can provide an outer constructor:

```julia
MyData(data1::Matrix{Float64}) = MyData(data1, Matrix{Float64}(size(data1,1), 0))

```

or use a default argument to the inner constructor:

```julia
function MyData(data1::Matrix{Float64}, data2::Matrix{Float64} = Matrix{Float64}(size(data1,1), 0))

```

---

<div class="post-metadata">

**Author:** ![BVPs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bvps/32/2190_2.png) [@BVPs](https://discourse.julialang.org/u/BVPs)\
**Post date:** [February 7, 2017, 2:12am UTC](https://discourse.julialang.org/t/restriction-on-field-names-in-a-user-defined-composite-type/1944/12 "2017-02-07T02:12:02Z")

</div>

Thank you very much, @greg_plowman ! Perhaps, the inner constructor with the default arguments would be neater. I tested it and worked well!
