Ensuring Positive Values – Part 2
My last post started the discussion about how to ensure data values met certain constraints. The solutions I talked about were ones where you checked at certain places during a calculation, but the constraints were not continuously enforced. If I want to ensure that values are always appropriate, I might create my own class and make sure values can never go sour.
Contents
Starting Positive
Here's a very simple skeleton of such a class in action. Let me first create an all-positive array.
m = magic(3)
m = 8 1 6 3 5 7 4 9 2
Next let me convert my array to the new class PositivelyLoren.
mpos = PositivelyLoren(m)
mpos = PositivelyLoren Properties: values: [3x3 double]
And let's see if we can nudge it out of good graces. We first will try to assign a NaN to the (3,3) element.
try mpos.values(3,3) = NaN; catch ENotPos disp(ENotPos.message) end
Expected input to be finite.
Now try a negative number.
try mpos.values(3,3) = -17; catch ENotPos disp(ENotPos.message) end
Expected input to be positive.
I'll try Inf next.
try mpos.values(3,3) = Inf; catch ENotPos disp(ENotPos.message) end
Expected input to be finite.
And finally a string.
try mpos.values(3,3) = {'fred'}; catch ENotPos disp(ENotPos.message) end
Conversion to double from cell is not possible.
Go Negative
Next let me try to create one of these PositivelyLoren objects with a matrix that doesn't contain only positive values.
r = randn(3)
r = 0.2916 -0.8045 -0.2437 0.1978 0.6966 0.2157 1.5877 0.8351 -1.1658
try bp = PositivelyLoren(b); catch PLE disp(PLE.message) end
Expected input to be positive.
The Class
The class is very rudimentary. You can tell that I didn't go into detail in the error message to give better diagnostic information (I could have). And I haven't added lots of useful methods, nor done much to contain the data well. Here's the class code.
type PositivelyLoren
classdef PositivelyLoren %PositivelyLoren Class values finite and positive. % This class contains data that is finite and positive ALWAYS. properties values end methods function obj = PositivelyLoren(vals) % PositivelyLoren constructor, for finite, positive numeric data. % Allow for default constructor. if nargin > 0 obj.values = vals; end end function obj = set.values(obj,vals) % Enforce finite, positive values for data. validateattributes(vals,{'numeric'},... {'finite','positive'}); obj.values = vals; end end end
The class has one property holding the data (values). It's got a constructor that allows for the default constructor. And it has the all important set.values method that is invoked any time any element in the obj is possibly being set. In there, I make sure, using the validateattributes function discussed last time, to only allow the data to be set if it meets the constraints of finite and positive.
How Do You Enforce Rules?
Have you needed to enforce rules for certain data constructs? How have you done so? Did you do it in the one-off manor like I did in the last post, or have you created your own class? Let me know here.