Hi.
Sorry if this is obvious or belies a complete misunderstanding of the Julia way… but I was trying to figure out how to do argument checking in a user defined type. For example, to enforce that a value be a positive valued number.
As a relative beginner (a Matlab convert) I didn’t really know how to do this. The closest I got in searching the documentation was that it should be done as a constructor, so I need some kind of function in my user defined type.
I managed to find an example from Distributions.jl where you define a normal distribution, where sigma has to be positive
struct Normal{T<:Real} <: ContinuousUnivariateDistribution
μ::T
σ::T
Normal{T}(μ, σ) where {T} = (@check_args(Normal, σ > zero(σ)); new{T}(μ, σ))
end
So this is pretty opaque to me as a beginner, and it seems like @check_args is a macro specific to the Distributions.jl package?
I also found that there is the ArgCheck.jl package which looks promising. But my hunch is that there should be a way of doing this with base Julia.
Anyway, I guess my friendly point here is that as a beginner approaching this pretty routine task I didn’t really get very far. If anyone could point me towards an example, or provide an answer, that would be cool. My hunch is that quite a lot of newcomers to Julia would probably appreciate a little worked example in the docs.
There’s an example in the manual which constructs an ordered pair, subject to the constraint that the pair is, in fact, ordered: Constructors · The Julia Language
The ternary a ? b : c syntax is kind of weird if you’re not used to it from a language like C. I personally find the more verbose version clearer in this case:
struct MyThing
positive_thing::Number
function MyThing(positive_thing)
if positive_thing > 0
return new(positive_thing)
else
error("Should be positive")
end
end
end
I agree, I also find that clearer. So a few things going on there…
Is that validation function automatically run (not simply defined) because it is declared in a struct?
Your suggestion is to be more specific and essentially create a new PositiveNumber type so you are dealing with one field at a time, then you can enforce that some of your types in other larger composition types are ::PositiveNumber ? Or was that just a simplification in your example?
For the sake of learning, I checked and it looks like I can do it in one…
struct MyThing
whatever::Float64
positive_thing::Float64
function MyThing(whatever, positive_thing)
if positive_thing > 0
return new(whatever, positive_thing)
else
error("positive_thing should be positive")
end
end
end
That function is an “inner constructor” (see Constructors · The Julia Language ), so it’s the lowest-level way to construct a MyThing. I’m just using the syntax:
function foo(x, y)
x + y
end
instead of the shorter but exactly equivalent syntax:
foo(x, y) = x + y
which is used in that particular example in the manual.
I was just simplifying. But having a PositiveNumber{T <: Number} type that does all your positivity-checking would also be a reasonable thing to do.