# Eltype of structs containing true or false values

**URL:** https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024
**Category:** General Usage
**Created:** [April 3, 2023, 5:19pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024 "2023-04-03T17:19:25Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Janssena](https://avatars.discourse-cdn.com/v4/letter/j/dfb087/32.png) [@Janssena](https://discourse.julialang.org/u/Janssena)
#### Post date: [April 3, 2023, 5:19pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/1 "2023-04-03T17:19:25Z")

</div>

Hey All,

I am creating a struct and a corresponding iterable. I want to make the eltype of the iterable more specific but am running into an issue since part of the eltype of my struct is true / false:

simple example:

```julia
struct MyStruct{B, T<:AbstractArray} # B here is either true or false
  x::T
  ...
end

struct MyIterator
  x::vector{MyStruct}
end

Base.eltype(::Type{MyIterator}) = MyStruct # I want to be able to pass the type of T as well.

```

B here denotes special cases of MyStruct that I use in specialized functions later on (e.g. `f(s::MyStruct{true, T}) where T`)  
Problem here is then when I want to pass T along like so:

```julia
struct MyIterator{T}
  x::Vector{MyStruct}
end
Base.eltype(::Type{MyIterator{T}} where T = MyStruct{?, T} # I also need to specify ? here with a type

```

The problem is of course that instead of the ? we have the value true or false. I want MyIterator to handle elements  
with either MyStruct{false} or MyStruct{true}.

Is there something I am missing or is this just not possible and should I instead create an abstract type;  
`abstract type MyAbstractStruct{T<:AbstractArray} end`  
and create two distinct structs for MyStruct?

Help is very much appreciated.

---

<div class="post-metadata">

### Author: ![jacobusmmsmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacobusmmsmit/32/217669_2.png) [@jacobusmmsmit](https://discourse.julialang.org/u/jacobusmmsmit)
#### Post date: [April 3, 2023, 5:39pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/2 "2023-04-03T17:39:49Z")

</div>

Please forgive me if I’m misinterpreting the question, but, in its current state, `MyIterator` is type unstable, and so inferring its `eltype` is impossible from the type alone. In other words, the type doesn’t contain enough information for `eltype` to return a concrete type, which in this case is what you want as `MyStruct{B,A}` is concrete.

If you want to write `eltype` like that, you’re half right in that you need to have `MyIterator` be two different structs, but you don’t need to define an abstract MyIterator: parameterised structs without the parameters specified _are_ abstract.

If you write

```julia
struct MyIterator{T<:MyStruct}
  x::Vector{T}
end
Base.eltype(::Type{MyIterator{T}}) where {T} = T

```

then, while you haven’t constrained `MyIterator` to contain only `MyStruct`s, you do know that as long as `T` is concrete i.e. `T = MyStruct{B,A}`, then it will contain both `B` and `A`.

You could instead parameterise `MyIterator` in the same way as `MyStruct` but this depends entirely on the codebase and how `MyIterator` will be used in it.

```julia
struct MyIterator{B, T<:AbstractArray}
  x::MyStruct{B,T}
end
Base.eltype(::Type{MyIterator{B,T}}) where {B,T} = MyStruct{B,T}

```

---

<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: [April 3, 2023, 5:50pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/3 "2023-04-03T17:50:04Z")

</div>

> [@jacobusmmsmit](#):
>
> ```julia
> struct MyIterator{T}
> x::Vector{T}
> end
> 
> ```

This could be restricted as

```julia
struct MyIterator{T<:MyStruct}
    x::Vector{T}
end

```

---

<div class="post-metadata">

### Author: ![jacobusmmsmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacobusmmsmit/32/217669_2.png) [@jacobusmmsmit](https://discourse.julialang.org/u/jacobusmmsmit)
#### Post date: [April 3, 2023, 6:21pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/4 "2023-04-03T18:21:30Z")

</div>

Yes, of course. Silly me

---

<div class="post-metadata">

### Author: ![Janssena](https://avatars.discourse-cdn.com/v4/letter/j/dfb087/32.png) [@Janssena](https://discourse.julialang.org/u/Janssena)
#### Post date: [April 3, 2023, 6:27pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/5 "2023-04-03T18:27:50Z")

</div>

Hey Jacobus,

Thanks for you comment.

I am considering of making an AbstractMyStruct rather than an abstract version of MyIterator to replace MyStruct{false, T} and MyStruct{true, T} like so:

```julia
abstract type AbstractMyStruct end

MyStructA{T<:AbstractArray} <: AbstractMyStruct # Or should it be AbstractMyStruct{T}?
  x::T
  ...
end

MyStructB{T<:AbstractArray} <: AbstractMyStruct
  x::T
  ...
end

MyIterable{T<:AbstractMyStruct}
  x::Vector{T}
end

```

In my functions I can then use

```julia
function f(s::AbstractMyStruct)
  # do some stuff
  g(s)
end

g(s::MyStructA) = # do specialized stuff for MyStructA
g(s::MyStructB) = # do specialized stuff for MyStructB

```

Whereas in my current setup I for example have `g(s::MyStruct{true, T}) = # do special stuff`.  
The elements of MyIterable should be able to be either a MyStructA or MyStructB. However, like this I think I have the same problem; the eltype of MyIterable is not concrete…

Alternatively I was hoping in my current setup (with MyStruct{B, T} with B being false or true) I could do

```julia
MyIterable{B<:Bool, T<:AbstractArray}
  x::Vector{MyStruct{B, T}} # This errors since B is not actually a Bool but rather literally the value true or false.
end

```

In my mind I want to do something like `Vector{MyStruct{Union{false, true}, T}}` but that doesn’t work.

---

<div class="post-metadata">

### Author: ![Janssena](https://avatars.discourse-cdn.com/v4/letter/j/dfb087/32.png) [@Janssena](https://discourse.julialang.org/u/Janssena)
#### Post date: [April 3, 2023, 6:40pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/6 "2023-04-03T18:40:18Z")

</div>

I have the feeling what I want to do is not possible.  
Maybe I should just make the bool a field of MyStruct like so

```julia
struct MyStruct{T<:AbstractArray}
  x::T
  is_special::Bool
end

g(s::MyStruct{T}) where T = s.is_special ? do_x() : do_y()

```

Depending on when doing x or y, the return type will be either an Vector or a Matrix, and I think the compiler will not like that…

---

<div class="post-metadata">

### Author: ![jacobusmmsmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacobusmmsmit/32/217669_2.png) [@jacobusmmsmit](https://discourse.julialang.org/u/jacobusmmsmit)
#### Post date: [April 3, 2023, 6:41pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/7 "2023-04-03T18:41:05Z")

</div>

> [@Janssena](#):
>
> `# Or should it be AbstractMyStruct{T}?`

Rule of thumb is that if you care about the `T` in `AbstractMyStruct{T}` and you want to use it (in this case to constrain the subtyping behaviour of `MyStruct` i.e. it’s only a subtype of the specific `AbstractMyStruct` when `T` matches), then put the `T` there. Otherwise, it’s implicitly there anyway.

---

<div class="post-metadata">

### Author: ![jacobusmmsmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacobusmmsmit/32/217669_2.png) [@jacobusmmsmit](https://discourse.julialang.org/u/jacobusmmsmit)
#### Post date: [April 3, 2023, 6:47pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/8 "2023-04-03T18:47:20Z")

</div>

> [@Janssena](#):
>
> Alternatively I was hoping in my current setup (with MyStruct{B, T} with B being false or true) I could do

You want to do value dispatch (that’s the googleable name for it). It’s completely possible, but you’re right that `B<:Bool` won’t work. `<:` means “is a subtype of”, and `false` is a value not a type, so there’s no hope in `false` being a subtype of `Bool`. You can, however, just elide the subtyping in the definition of `MyIterable` and write:

```julia
MyIterable{B, T<:AbstractArray}
    x::Vector{MyStruct{B, T}}
    MyIterable{B,T}(x) = B isa Bool ? new{B,T}(x) : error("B has to be a bool")
end

```

The constructor will now deal with whether the struct is valid at runtime, but this is generally not such a big issue.

This is the easy way around it. The hard way would be using `Val`. I don’t know how to do that properly so I won’t try, but if you google “value dispatch Julia” you’ll find some useful information.

---

<div class="post-metadata">

### Author: ![Janssena](https://avatars.discourse-cdn.com/v4/letter/j/dfb087/32.png) [@Janssena](https://discourse.julialang.org/u/Janssena)
#### Post date: [April 3, 2023, 7:05pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/9 "2023-04-03T19:05:00Z")

</div>

```julia
MyIterable{B, T<:AbstractArray}
    x::Vector{MyStruct{B, T}}
    MyIterable{B,T}(x) = B isa Bool ? new{B,T}(x) : error("B has to be a bool")
end

```

This will not work since B in MyIterable is not a single value; `x` is a Vector containing `MyStruct{true, T}` and `MyStruct{false, T}`, so B in MyIterable will have to be both `true` and `false`.  
I am looking into value dispatch but it seems there is quite a considerable overhead in performance when doing that…

---

<div class="post-metadata">

### Author: ![jacobusmmsmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacobusmmsmit/32/217669_2.png) [@jacobusmmsmit](https://discourse.julialang.org/u/jacobusmmsmit)
#### Post date: [April 3, 2023, 7:17pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/10 "2023-04-03T19:17:31Z")

</div>

Oh right, in that case it probably makes sense to have an `AbstractMyStruct` and two subtypes. Or, and you should definitely try this, what about

```julia
struct MyStruct{T}
    b::Bool
    x::T
end

```

For this specific case, `MyStruct{T}` (with `T` specified) is now concrete, which means `MyIterable` will have a concrete `eltype`. This may or may not be faster than the `AbstractMyStruct` method. It’s definitely worth trying both.

---

<div class="post-metadata">

### Author: ![Janssena](https://avatars.discourse-cdn.com/v4/letter/j/dfb087/32.png) [@Janssena](https://discourse.julialang.org/u/Janssena)
#### Post date: [April 4, 2023, 7:54am UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/11 "2023-04-04T07:54:46Z")

</div>

Okay, the way I go about it now is as follows:

```julia
struct MyStruct{T1<:AbstractArray,T2<:AbstractArray}
  x::T1 # This can be either a matrix or a vector
  t::T2 # This will always be a one dimensional Array
  y::T2 # Should always have the same type as t
end

struct MyIterable{T1<:AbstractArray,T2<:AbstractArray}
  s::Vector{MyStruct{T1,T2}
end

get_types(_::MyStruct{T1,T2}) where {T1,T2} = T1, T2

function MyIterable(s::Vector{MyStruct})
  T1, T2 = get_types(first(s))
  return MyIterable{T1,T2}(convert(Vector{MyStruct{T1,T2}}, s))
end

Base.eltype(::Type{MyIterable{T1,T2}}) where {T1,T2} = MyStruct{T1,T2}

```

I think my initial goal of having two types of MyStruct in MyIterable will just result in a non-concrete eltype; either containing MyStruct.x == Vector or MyStruct.x == Matrix.  
With the above approach, all elements in MyIterable will have the same type, and the following check does not result in any allocations (whereas it resulted in ~4k allocations in my previous setup)

```julia
function f(iterable::MyIterable)
  a = 0.
  for s in iterable
    a += sum(s.x)
  end
  return a
end

```

What is left is making sure during construction of MyIterable that all entries have the same T1 and T2. I am hoping that having these concrete times will improve performance downstream, since now I will have to convert all entries of MyIterable to have a x::Matrix instead of Vectors and Matrices. I can now specialize my functions on T1 instead of the boolean that I used previously.

---

<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: [April 4, 2023, 9:44am UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/12 "2023-04-04T09:44:28Z")

</div>

> [@Janssena](#):
>
> `get_types(_::MyStruct{T1,T2})`

Syntax: You can just omit the unused variable like this:

```julia
get_types(::MyStruct{T1,T2})

```

---

<div class="post-metadata">

### Author: ![Janssena](https://avatars.discourse-cdn.com/v4/letter/j/dfb087/32.png) [@Janssena](https://discourse.julialang.org/u/Janssena)
#### Post date: [April 4, 2023, 4:57pm UTC](https://discourse.julialang.org/t/eltype-of-structs-containing-true-or-false-values/97024/13 "2023-04-04T16:57:46Z")

</div>

Thanks, that cleans it up just that little bit more 😉
