The Null<> Class

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

The Null<> Class

Dimathematician

I had a closer look at it and would like to propose some changes. The first thing
that I think is worth discussing is the comparison against

std::numeric_limits<T>::max.

So the following code:

    Real myReal=(std::numeric_limits<float>::max)();
    bool   realIsNull=(myReal==Null<Real>());

would set the boolean to true. But myReal is actually a Real number, the largest one
which can be represented on the system. I agree that this will work most of the time,
but I think it would make more sense to compare it against

std::numeric_limits<float>::quiet_isNaN

Comparing any real against this object type will return false, exactly what we want. The second
thing that I'd like to mention is that for the class

class Foo{
    private:
      Real var_;
    public:
        Foo():var_(10.0){}

        bool operator==(const Foo& rhs) {
            return var_==rhs.var_;
        }
  };

which has a standard constructor, the following will yield a boolean which is true

Foo myFoo;
bool myFooIsNull=(myFoo==Null<Foo>());

In this case, we are comparing against a standard constructor, which is not really a Null object,
since some member variables are initialized. I propose something similar too

#include<limits>
#include <boost/static_assert.hpp>

  template <class Type> class NullNew {
     
  public:
       
        NullNew() {}

        operator Type() const {
            BOOST_STATIC_ASSERT(std::numeric_limits<Type>::has_quiet_NaN);
            return std::numeric_limits<Type>::quiet_NaN();
        }

        bool operator==(const NullNew<Type>&) {
            return true;
        }
  };

The following happens here: first of all, we don't need a template definition for all types
like int, double, long int.... Second: we are checking against quiet_NaN. Third: I disable
any casting of anything which doesn't have the quiet_NaN implementation. Boost static
assert lets the compilation fail in this case. I don't know whether we are using Null<Foo>
for any other objects than Real, Natural.. In case we do, this will not work. Until we have
something better, e.g. a isNull implementation for all objects  (which could then be incorporated
easily in the class above), we should prevent the cast operator from returning a standard
instance.

What do you think?











   






------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

Luigi Ballabio
On Fri, 2009-09-18 at 15:58 +0200, Dima wrote:
>
> I had a closer look at it and would like to propose some changes.

Dima,
        I know, Null<> has a number of shortcomings.  But rather than trying to
patch it, I'd replace it with boost::optional<> instead.  

The problem is, we're already late for the 1.0 train.  Over the next
releases, I'll try to replace it in a few places where it doesn't break
backward compatibility.  For the other places, I guess we'll wait for
the next overhaul (2.0, probably in a few years.)  The shortcomings are
not that bad anyway.

Thoughts?
        Luigi


--

Newton's Law of Gravitation:
What goes up must come down. But don't expect it to come down
where you can find it. Murphy's Law applies to Newton's.



------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

Dimathematician
Luigi, I know that you're working on the 1.0 release and it wasn't meant
to go into the next release. I just wanted it to be on some to do list - where
I'd be happy to contribute.

The shortcomings are not bad since it is probably used correctly in the
current library. However, some users might use the particular class- as
a standalone class- in their own applications and might not know about
the mentioned behavior. Also, other contributors might use it without
looking into the details and some errors can occurr, in particular in the
default constructor comparison. This is why I  proposed a temporary fix
until we have something better.

I'm aware of boost::optional and think it could be the way to go. However,
I don't see an easy way to incorporate it in the current Null design. I think
it would have to be used directly such as in:

boost::optional<double> optVar;
QL_REQUIRE(optVar!=NULL,".....");
double var=*optVar;

Anyways, you might be busy with more important stuff. If you need help
to rewrite classes with boost::optional in the future, let me know.



2009/9/23 Luigi Ballabio <[hidden email]>
On Fri, 2009-09-18 at 15:58 +0200, Dima wrote:
>
> I had a closer look at it and would like to propose some changes.

Dima,
       I know, Null<> has a number of shortcomings.  But rather than trying to
patch it, I'd replace it with boost::optional<> instead.

The problem is, we're already late for the 1.0 train.  Over the next
releases, I'll try to replace it in a few places where it doesn't break
backward compatibility.  For the other places, I guess we'll wait for
the next overhaul (2.0, probably in a few years.)  The shortcomings are
not that bad anyway.

Thoughts?
       Luigi


--

Newton's Law of Gravitation:
What goes up must come down. But don't expect it to come down
where you can find it. Murphy's Law applies to Newton's.




------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

Luigi Ballabio
On Wed, 2009-09-23 at 15:48 +0200, Dima wrote:
> Luigi, I know that you're working on the 1.0 release and it wasn't
> meant to go into the next release. I just wanted it to be on some to
> do list - where I'd be happy to contribute.

Sure, I had taken it in this spirit.

> I'm aware of boost::optional and think it could be the way to go.
> However, I don't see an easy way to incorporate it in the current Null
> design.

Neither do I. It would replace Null entirely.

Luigi


--

Though this be madness, yet there is method in't.
-- Hamlet, Act II, scene II



------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

japari

> > I'm aware of boost::optional and think it could be the way to go.
> > However, I don't see an easy way to incorporate it in the current Null
> > design.
>
> Neither do I. It would replace Null entirely.
>

Should we start dropping Null<> and move to optional then?

Regards
Pepe

------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

Luigi Ballabio
On Fri, 2009-09-25 at 07:58 +0200, Jose Aparicio-Navarro wrote:
> > > I'm aware of boost::optional and think it could be the way to go.
> > > However, I don't see an easy way to incorporate it in the current Null
> > > design.
> >
> > Neither do I. It would replace Null entirely.
> >
>
> Should we start dropping Null<> and move to optional then?

Moving to optional for new functionality---yes.
Dropping Null in existing code---no. At this point we keep
compatibility.

Luigi


--

Green's Law of Debate:
Anything is possible if you don't know what you're talking about.



------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

Dimathematician
I still think we need a little wrapper instead of the pure optional class.
It is not convenient to dereference the optional object in the code by
writing

// -------------------------------------
optional<double> a(1.1);
double b=2.2;
double res;

QL_REQUIRE(a,"Empty a")
res=b*a.get();
// -------------------------------------

Would require a lot of rewriting of old Null class code too. How about the following alternative:

 template <class Type>
  
 class Optional{
      public:

        Optional(){}
        Optional(Type val):val_(val) {}

        operator Type() const {
            return val_.get();
        }
   
        bool isEmpty() const{
            return !val_;
        }

        bool isInitialized() const{
            return !isEmpty();
        }

        void reset(const Type& val){
            val_.reset(val);
        }

        void reset(){
            val_.reset();
        }

        bool operator==(Type const& x){
            return x==val_;
        }
       
        bool operator==(Optional<Type> const& x){
            return x==val_;
        }

    private:
        boost::optional<Type> val_;
    };

Here, Optional has a cast operator to the template class. So we would
check isInitialized() and then use the class without dereferencing. Here is
some example code

    Optional<double> a(2.0);
    Optional<double> b;
    double c=1.1;

    std::cout << "------------" << std::endl;
    std::cout << "a empty:" << a.isEmpty() << std::endl;
    std::cout << "b empty:" << b.isEmpty() << std::endl;
    std::cout << "------------" << std::endl;
    std::cout << "a initialized:" << a.isInitialized() << std::endl;
    std::cout << "b initialized:" << b.isInitialized() << std::endl;
    std::cout << "------------" << std::endl;
    b.reset(c);
    std::cout << "b initialized:" << b.isInitialized() << std::endl;
    std::cout << "------------" << std::endl;
    b.reset();
    std::cout << "b initialized:" << b.isInitialized() << std::endl;
    std::cout << "------------" << std::endl;
   
    // simple multiplication, as if a is a double
    std::cout << "c*a: " << c*a << std::endl;
   
// comparison of a with a double
    a.reset(c);
    std::cout << "a==c: " << (a==c) << std::endl;


Gives

------------
a empty:0
b empty:1
------------
a initialized:1
b initialized:0
------------
b initialized:1
------------
b initialized:0
------------
c*a: 2.2
a==c: 1


A QuantLib rewriting example for the Instrument class:


// instead of
//---------------------------------------------------------------------------
public:
inline Instrument::Instrument()
    : NPV_(Null<Real>()), errorEstimate_(Null<Real>()) {}

private:
Real NPV_

 inline Real Instrument::NPV() const {
        calculate();
        QL_REQUIRE(NPV_ != Null<Real>(), "NPV not provided");
        return NPV_;
    }
//---------------------------------------------------------------------------

// Optional version
//---------------------------------------------------------------------------
public:
inline Instrument::Instrument(){} // no initialization of member needed

private:
// make NPV_ an Optional variable
Optional<Real> NPV_

 inline Real Instrument::NPV() const {
        calculate();
        QL_REQUIRE(NPV_.isInitialized(), "NPV not provided");
        return NPV_;
    }
//---------------------------------------------------------------------------


Of course, the Optional class has to be polished. Thoughts?



2009/9/25 Luigi Ballabio <[hidden email]>
On Fri, 2009-09-25 at 07:58 +0200, Jose Aparicio-Navarro wrote:
> > > I'm aware of boost::optional and think it could be the way to go.
> > > However, I don't see an easy way to incorporate it in the current Null
> > > design.
> >
> > Neither do I. It would replace Null entirely.
> >
>
> Should we start dropping Null<> and move to optional then?

Moving to optional for new functionality---yes.
Dropping Null in existing code---no. At this point we keep
compatibility.

Luigi


--

Green's Law of Debate:
Anything is possible if you don't know what you're talking about.




------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev
Reply | Threaded
Open this post in threaded view
|

Re: The Null<> Class

Luigi Ballabio
On Sat, 2009-09-26 at 17:35 +0200, Dima wrote:

> I still think we need a little wrapper instead of the pure optional
> class.
> It is not convenient to dereference the optional object in the code
> [...]
> A QuantLib rewriting example for the Instrument class:
>
> // Optional version
> //---------------------------------------------------------------------------
> public:
> inline Instrument::Instrument(){} // no initialization of member
> needed
>
> private:
> // make NPV_ an Optional variable
> Optional<Real> NPV_
>
>  inline Real Instrument::NPV() const {
>         calculate();
>         QL_REQUIRE(NPV_.isInitialized(), "NPV not provided");
>         return NPV_;
>     }
> //---------------------------------------------------------------------------
>
>
> Of course, the Optional class has to be polished. Thoughts?

I don't know, I'm not fond of automatic conversions (as you might see
from the several "explicit" keywords we added to constructors...)
It's true that this means rewriting some code (or possibly a lot of it)
but I think it would be safer. And once we rule out explicit conversion,
the code is not that verbose. With boost::optional, the excerpt above
would be written as:

//---------------------------------------------------------------------------
public:
  Instrument::Instrument(){} // no initialization of member needed

private:
  // make NPV_ a boost::optional variable
  boost::optional<Real> NPV_;

  Real Instrument::NPV() const {
      calculate();
      QL_REQUIRE(NPV_, "NPV not provided");
      return *NPV_;
  }
//---------------------------------------------------------------------------


Luigi


--

The First Rule of Optimization: Don't do it.
The Second Rule of Optimization (For experts only): Don't do it yet.
-- Michael Jackson



------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-dev mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-dev