Re: Mixing OO and DB

From: David BL <davidbl_at_iinet.net.au>
Date: Fri, 15 Feb 2008 17:45:16 -0800 (PST)
Message-ID: <4d1955b9-73c7-4ea0-8754-0a96fbcb83fe_at_s13g2000prd.googlegroups.com>


On Feb 16, 5:24 am, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de> wrote:
> On Fri, 15 Feb 2008 08:46:54 -0800 (PST), David BL wrote:
> > On Feb 15, 8:20 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
> > wrote:
> >> On Thu, 14 Feb 2008 20:27:52 -0800 (PST), in
>
> >>> Consider the function 1/x which is axiomatically defined on (nonzero)
> >>> reals but not the integers. That suggests that Z is not a subtype of
> >>> R. However consider
>
> >>> float Invert(float x) { return 1/x; }
>
> >>> That doesn't stop us calling Invert(2) even though 2 is only an
> >>> integer. We still get a float result!
>
> >> I think there is a confusion here. Note that invert as an operation deals
> >> with a tuple float x float:
>
> >> Invert : float -> float
>
> >> Now, the question is where are you going to substitute ints?
>
> >> 1. In the first appearance of float
> >> 2. In the second one (result)
> >> 3. In both
>
> >> Depending on that Invert will become inheritable or not. I.e
> >> substitutability is not only parameter mode depending, it also depends on
> >> the concrete parameters too. (For the sake of genericity, results are
> >> parameters.)
>
> > I'm aware of the three conceivable options, but I'm quite clear in my
> > mind that the system should only support the narrowing of in-
> > parameters and widening of out-parameters.
>
> It is an arbitrary constraint, worse is that it kills any algebraic
> operations.

I imagine any notion of sub-typing could be called arbitrary because the fact is that there is no single definition that will keep everyone happy.

I hope you are remembering in this discussion that I expect an OO language to support at least two distinct notions of subtype. One centres on substitutability of values and the other on substitutability of objects. I'm reticent to say variable instead of object because some people assume (by definition) variable represents a value.

I'm assuming here we are only discussing value-types. Agreed?

> >Therefore, as Invert() has
> > been written (1) is the only option.
>
> As a counterexample, consider C (complex) instead of Z.

Please provide more details. Are you alluding to covariant return types? ie

Complex Invert(Complex x);
Real Invert(Real x);

I don't see how this presents a problem.

> > If you want option (3) then you
> > need to explicitly write a parameterised function. Eg
>
> > template <class T> T Invert(T x) { return 1/x; }
>
> > However it seems inappropriate to allow Invert<int>().
>
> From the language design point of view there is no any problem because the
> type system shall have different types for polymorphic and specific values.

Sorry, I can't understand "different types for polymorphic and specific values".

> So you could declare Invert in either of four forms:
>
> Invert : T -> T (substitutes both)
> Invert : class T -> T (substitutes the result)
> Invert : T -> class T (substitutes the argument)
> Invert : class T -> class T (does not substitute)

> > When C.Date talks about value substitutability he doesn't mean you can
> > pick any function you like and substitute a sub-type in place of a
> > super-type throughout the function.
>
> Then it is worse, it is so that substitutability is not controlled by the
> type. If so, then how it is any better than just let the programmer to do
> what he wants?

I don't understand what the problem is. Please provide an example.

> > Doing so gives you a *distinct*
> > function and the system is not allowed to guess that it is meaningful
> > to do so. If you wanted this to be valid, then it would greatly
> > restrict possible sub-typing relationships and that limits code
> > reuse. In particular, it would no longer be possible to treat Z as a
> > subtype of R.
>
> (which is not, in LSP sense.)

I think there is a misunderstanding here. In this discussion I'm only talking about value-types. In an OO application I would imagine that many if not most types are *not* value-types and indeed go by LSP for sub-typing. Note that I assume LSP is (only) about substitutability of objects (or if you like, variables that have state but don't necessarily represent a value).

The types we are discussing here - ints, floats, circles, ellipses are all value-types. I don't see any sense in demanding LSP sub-typing amongst value-types. Variables for these types do nothing but hold a value, and don't exhibit behaviour in the sense that is relevant to LSP. In fact imposing LSP sub-typing amongst value-types means there cannot be any non-trivial sub-typing amongst value-types at all.

Here is a proof by contradiction: Suppose S,T are value-types and values(S) is a strict subset of values(T). Now also suppose S is a LSP-sub-type of T. In other words, a pointer to a variable of type S can be implicit cast to a pointer to a variable of type T.

    void foo(T* x)
    {

        // By definition, value-types always support assignment
        // on variables
        *x = <some value in  values(T)\values(S)>;
    }

    S s;
    foo(&s); // oops

> > Probably some mathematicians would think that is
> > sensible since the system Z doesn't inherit the axiom for existence of
> > multiplicative inverses from R. However, I prefer the idea that
> > algorithms are parameterised explicitly where appropriate, and only
> > let the system perform implicit type conversions on in/out parameters
> > or assignments.
>
> This is too restricting to me. I prefer to be able to design algorithms
> without parametrization.

But paradoxically, if you enforce LSP on sub-typing of value-types, you won't get any sub-typing amongst value-types at all, so you'll be forced to use more parameterisation in your algorithms, not less!

> 1. Why should I specify the parameters if the types are already known to
> the system?
>
> 2. Static only parametrization makes impossible to design a huge range of
> applications where types are known only to be constrained to certain class.
> Even where applicable it becomes extremely weird. Look at STL. It is a
> mess.

Please provide some examples. Received on Sat Feb 16 2008 - 02:45:16 CET

Original text of this message