# Floats or Integers or Vectors with specific ranges?

**URL:** <https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682>\
**Category:** General Usage\
**Created:** [January 30, 2018, 1:41am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682 "2018-01-30T01:41:56Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ivo\_welch](https://avatars.discourse-cdn.com/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://discourse.julialang.org/u/ivo_welch)\
**Post date:** [January 30, 2018, 1:41am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/1 "2018-01-30T01:41:56Z")

</div>

Very basic questions:

- can I define an Int8 Type that can only range from 5 to 20, but throws an error if I try to assign 21 ?
- can I define a Float64 Type that can only range from 1.0 to Infinity, if I try to assign 0.5 ?
- can I define a Vector (e.g., of Floats) that must be of length 5 (or null), but throws an error if I try to assign a vector of length 4 or 6??

I suspect no, except with my own code (e.g., checking when assigning, structs with custom initializers that are checking, etc). Types are already complicated enough. I am just asking for confirmation.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 30, 2018, 2:03am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/2 "2018-01-30T02:03:00Z")

</div>

> [@ivo\_welch](#):
>
> can I define…I suspect no, except with my own code

Huh? How else would you define something, but with your own code?

```julia
julia> struct FiveToTwenty <: Unsigned
           val::UInt8
           function FiveToTwenty(val)
               @assert val >= 5 && val <= 20
               new(UInt8(val))
           end
       end

julia> Base.show(io::IO, v::FiveToTwenty) = print(io, v.val)

julia> FiveToTwenty(4)
ERROR: AssertionError: val >= 5 && val <= 20
Stacktrace:
 [1] FiveToTwenty(::Int64) at ./REPL[159]:4

julia> FiveToTwenty(14)
14

julia> FiveToTwenty(24)
ERROR: AssertionError: val >= 5 && val <= 20
Stacktrace:
 [1] FiveToTwenty(::Int64) at ./REPL[159]:4

julia> isbits(FiveToTwenty(14))
true

```

Ideas for others would be similar. For the vector, you may just want to use a mutable struct with 5 fields, or wrap an MVector (from `StaticArrays.jl`).

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 30, 2018, 2:25am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/3 "2018-01-30T02:25:39Z")

</div>

The better question is, what are you trying to do? If you’re trying to constrain optimization variables, there’s better ways to do that. If you’re trying to enforce constraints in a nonlinear equation, a transformation could help. Etc.

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://avatars.discourse-cdn.com/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://discourse.julialang.org/u/ivo_welch)\
**Post date:** [January 30, 2018, 3:38am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/4 "2018-01-30T03:38:10Z")

</div>

thanks. Chris, I am just trying to impose discipline on my code, and perhaps get lucky finding errors along the way (rather than with `assert`s). I am also just trying to learn the feature set of julia. I believe the optimization routines have box constraints, which I will work with later.

Elrod, are you running 0.6.2?

```julia
julia> struct FiveToTwenty <: Unsigned
                  val::UInt8
                  function FiveToTwenty(val)
                      @assert val >= 5 && val <= 20
                      new(UInt8(val))
                  end
              end

julia> FiveToTwenty(14)
Error showing value of type FiveToTwenty:
ERROR: MethodError: no method matching leading_zeros(::FiveToTwenty)
Closest candidates are:
  leading_zeros(::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) at int.jl:238
Stacktrace:
 [1] hex(::FiveToTwenty, ::Int64, ::Bool) at ./intfuncs.jl:543
 [2] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::MIME{Symbol("text/plain")}, ::FiveToTwenty) at ./REPL.jl:122
 [3] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::FiveToTwenty) at ./REPL.jl:125
 [4] display(::FiveToTwenty) at ./multimedia.jl:218
 [5] eval(::Module, ::Any) at ./boot.jl:235
 [6] print_response(::Base.Terminals.TTYTerminal, ::Any, ::Void, ::Bool, ::Bool, ::Void) at ./REPL.jl:144
 [7] print_response(::Base.REPL.LineEditREPL, ::Any, ::Void, ::Bool, ::Bool) at ./REPL.jl:129
 [8] (::Base.REPL.#do_respond#16{Bool,Base.REPL.##26#36{Base.REPL.LineEditREPL,Base.REPL.REPLHistoryProvider},Base.REPL.LineEditREPL,Base.LineEdit.Prompt})(::Base.LineEdit.MIState, ::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Bool) at ./REPL.jl:646

```

Your example (after I get it to work) was unintuitive to me. I thought of a struct as a composite type, while an Int is a base type; and I think you are defining a struct to be a subtype of a base type. Gotta learn and experiment more…

/iaw

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 30, 2018, 4:30am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/5 "2018-01-30T04:30:13Z")

</div>

You need to define Base.show for this type.

```julia
julia> struct FiveToTwenty <: Unsigned
                         val::UInt8
                         function FiveToTwenty(val)
                             @boundscheck val >= 5 && val <= 20
                             new(UInt8(val))
                         end
                     end

julia> FiveToTwenty(14)
Error showing value of type FiveToTwenty:
ERROR: MethodError: no method matching leading_zeros(::FiveToTwenty)
Closest candidates are:
  leading_zeros(::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) at int.jl:238
Stacktrace:
 [1] hex(::FiveToTwenty, ::Int64, ::Bool) at ./intfuncs.jl:543
 [2] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::MIME{Symbol("text/plain")}, ::FiveToTwenty) at ./REPL.jl:122
 [3] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::FiveToTwenty) at ./REPL.jl:125
 [4] display(::FiveToTwenty) at ./multimedia.jl:218
 [5] eval(::Module, ::Any) at ./boot.jl:235
 [6] print_response(::Base.Terminals.TTYTerminal, ::Any, ::Void, ::Bool, ::Bool, ::Void) at ./REPL.jl:144
 [7] print_response(::Base.REPL.LineEditREPL, ::Any, ::Void, ::Bool, ::Bool) at ./REPL.jl:129
 [8] (::Base.REPL.#do_respond#16{Bool,Base.REPL.##26#36{Base.REPL.LineEditREPL,Base.REPL.REPLHistoryProvider},Base.REPL.LineEditREPL,Base.LineEdit.Prompt})(::Base.LineEdit.MIState, ::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Bool) at ./REPL.jl:646

julia> x = ans;

julia> Base.show(io::IO, v::FiveToTwenty) = print(io, v.val)

julia> x
14

```

The hint was that the error said “Error showing…”  
You created the object just fine, but the error came in displaying the actual value. This is why we could still assign the value (without error), as long as we followed the operation with a semicolon.  
Then, defining a show method let you display it.

In Julia, if you want a custom type with certain properties, you can just define it on your own.  
If you don’t like always having the error checking, you can

```julia
julia> struct FiveToTwenty2 <: Unsigned
                                val::UInt8
                                @inline function FiveToTwenty2(val)
                                    @boundscheck begin @assert val >= 5 && val <= 20 end
                                    new(UInt8(val))
                                end
                            end
julia> Base.show(io::IO, v::FiveToTwenty2) = print(io, v.val)

julia> f(x) = (@inbounds x = FiveToTwenty2(x); x)
f (generic function with 1 method)

julia> FiveToTwenty2(21)
ERROR: AssertionError: val >= 5 && val <= 20
Stacktrace:
 [1] FiveToTwenty2(::Int64) at ./REPL[52]:4

julia> f(11)
11

julia> f(21)
21

```

Thus, once you’ve confirmed your code never violates the bounds, you can add the `@inbounds` and turn bounds checking off.

Although if someone else put a lot of time into a solution, of course it’s easier to take advantage of their work. People’ve asked a few times what the best way to actually discover packages is though…

Anyway, if you’re facing constrained optimization problems with straightforward constraints (eg, 1 \< y \< infinity), a straightforward approach is as in:

> **[GitHub - tpapp/ContinuousTransformations.jl: Continuous transformations from...](https://github.com/tpapp/ContinuousTransformations.jl)**
>
> Continuous transformations from ℝ or ℝⁿ to various open sets - GitHub - tpapp/ContinuousTransformations.jl: Continuous transformations from ℝ or ℝⁿ to various open sets

Where you transform the variables from the constrained to an unconstrained version.  
Eg, -infinity \< log(y-1) \< infinity. The above package handles transforms like this, as well as providing everything else, like Jacobians and the inverse transforms.

For the third case,

> **[GitHub - JuliaArrays/StaticArrays.jl: Statically sized arrays for Julia](https://github.com/JuliaArrays/StaticArrays.jl)**
>
> Statically sized arrays for Julia. Contribute to JuliaArrays/StaticArrays.jl development by creating an account on GitHub.

```julia
julia> using StaticArrays

julia> FiveVector1{T} = MVector{5,T}
StaticArrays.MArray{Tuple{5},T,1,5} where T

julia> FiveVector2{T} = SizedArray{Tuple{5},T}
StaticArrays.SizedArray{Tuple{5},T,N,M} where M where N where T

julia> FiveVector1(randn(5))
5-element MVector{5,Float64}:
  0.804218
  3.43472 
 -0.786301
  0.47925 
  1.69257 

julia> FiveVector2(randn(5))
5-element StaticArrays.SizedArray{Tuple{5},Float64,1,1}:
 -1.37541 
  0.969937
  0.364058
 -0.364662
 -2.35112 

```

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://avatars.discourse-cdn.com/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://discourse.julialang.org/u/ivo_welch)\
**Post date:** [January 30, 2018, 5:25am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/6 "2018-01-30T05:25:06Z")

</div>

thanks, again, Elrod. Grrr…I should have made this multiple questions. I had expected a “no work” and move on. julia feels more like perl, in that there are so many things to discover, than like C, where it is easy to learn and then remember everything.

thank you for explaining where I messed up on the `FiveToTwenty`. instead of defining `show`, is it possible to tell julia that the FiveToTwenty type can be promoted to an Integer? Then, not only would the print work automatically , but also examples like

```julia
julia> 15+FiveToTwenty(14)
ERROR: no promotion exists for Int64 and FiveToTwenty

```

I did not see a working example in the docs, so I tried

```julia
julia> promote_rule(::Type{Int}, ::Type{FiveToTwenty}) = Int
ERROR: error in method definition: function Base.promote_rule must be explicitly imported to be extended

```

As a sidenote, Pascal had a few type innovations decades ago, one of which were range types. julia’s innovations in the type realm are fascinating, and not just a little syntactic sugar, but a lot. One needs a lot of insulin to digest it.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 30, 2018, 5:51am UTC](https://discourse.julialang.org/t/floats-or-integers-or-vectors-with-specific-ranges/8682/7 "2018-01-30T05:51:38Z")

</div>

If you want to extend a function from another module, you have to preface the name with the module (see the error message).  
For example, instead of `show`, I had to say `Base.show`.

In your case, that means (you also need to define convert methods, so Julia knows how to do the conversion):

```julia
Base.promote_rule(::Type{Int}, ::Type{FiveToTwenty}) = Int
Base.convert(::Type{Int}, x::FiveToTwenty) = Int(x.val)
FiveToTwenty(14) + 2
FiveToTwenty(14) + 20

```

The output is of a regular integer (64 bit on 64 bit systems).  
That doesn’t for for showing though.  
Honestly, I haven’t messed with displays for custom types nearly enough, so I’m not really sure what the best way to do things are. If you delete the `<: Unsigned` part, it will display automatically as:

```julia
julia> struct FiveToTwenty3
              val::UInt8
              @inline function FiveToTwenty3(val)
                  @boundscheck begin @assert val >= 5 && val <= 20 end
                  new(UInt8(val))
              end
         end

julia> FiveToTwenty3(8)
FiveToTwenty3(0x08)

julia> isbits(ans)
true

```

A fallback show for numeric types doesn’t seem to be defined. The above is normal, although not especially pretty.

If you’re adding a lot of new types, you can

```julia
import Base: promote_rule
promote_rule(::Type{Int}, x::FiveToTwenty) = Int(x.val)

```

In Julia, you can get range types like

```julia
julia> typeof(1:20)
UnitRange{Int64}

julia> typeof(linspace(0.3, 17, 100))
StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}

```

I love Julia’s innovations.  
Multiple dispatch is incredible.  
I think it can take a while to get used to, but how it lets you get low/zero overhead performant abstractions with extreme generalization…just mind blowing!

Like, about a month ago I was working on a problem, and my answers were nonsense.  
The functions involved inverting and multiplying a few (ill-conditioned) matrices. Simply calling BigFloat.() on the inputs → everything worked, the answers were right, and I had derivative-enhanced quadrature rules.

More impressive of course is how automatic differentiation “just works” on most code, or how @ChrisRackauckas got a bunch of functions to also work on GPUArrays…
