Re: Mixing OO and DB
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'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