What's the best way to minimize the need of run time checks?

Juan Pablo Romero Méndez jpablo.romero at gmail.com
Sun Aug 28 14:25:06 EDT 2016


2016-08-28 0:04 GMT-07:00 Steven D'Aprano <
steve+comp.lang.python at pearwood.info>:

> On Sunday 28 August 2016 15:56, Juan Pablo Romero Méndez wrote:
>
> > 2016-08-27 21:30 GMT-07:00 Steve D'Aprano <steve+python at pearwood.info>:
> [...]
> >> Now it is true that speaking in full generality, classes and types
> refer to
> >> different things. Or to be perhaps more accurate, *subclassing* and
> >> *subtyping* are different things:
> >>
> >> http://c2.com/cgi/wiki?SubTypingAndSubClassing
> >>
> >> Many languages treat them the same, but fundamentally they are
> different.
> >
> > Oh, I don't think he is thinking in terms of OO "classes", I think he
> meant
> > two different "kinds" or "varieties" of values (although kind has a
> > technical meaning)
>
> That's not quite right either. "Two different kinds or varieties" is what
> both
> subclassing and subtyping aim to describe, in different ways: e.g. dogs and
> cats are two different kinds of mammal.
>
> What you are describing here:
>
> > In TypeScript terms what he is saying can be described like this:
> >
> > type Complex =
> >  { real: number, i: number }
> > | { r: number, φ: number}
> >
> > const c1: Complex = { real: 1, i: 1 }
> > const c2: Complex = { r: 1, φ: 0.5 }
> >
> > You have two values of the same type but different representation.
>
> seems to be more like what is called "variant record" in Pascal.
>
> http://www.freepascal.org/docs-html/ref/refsu16.html
>
>
> I'm not familiar with TypeScript. How does this work? If I say:
>
> const c1: Complex = {real: 1, imag: 1 }
>
> print c1.r
> print c1.φ
>
> what do I get? If r and φ are merely alternative names for "real" and
> "imag",
> that's not good enough. Given real=1, imag=1, then we need to get
> r=1.414213
> and φ = pi/4 without any extra effort on the part of the user.
>
>

Here's a more complete example:

type CartesianC = { real: number, i: number }
type PolarC = { r: number, φ: number}

type Complex = PolarC | CartesianC

const c1: Complex = { real: 1, i: 1 };
const c2: Complex = { r: 1, φ: 0.5 };

// This is called a Type Guard

function isCartesian(c: Complex): c is CartesianC {

return (<CartesianC> c).real !== undefined;
}

if(isCartesian(c1)) {
    // c1 is a CartesianC here
    c1.real
} else {
    // and a PolarC here. Using c1.real is a compile error
    c1.r
}

TypeScript doesn't support pattern matching so there's some boilerplate
involved: you need to define a TypeGuard so that inside the if branch TS
allows you to treat c1 as a CartesianC; within the else branch it is
treated as a PolarC.



>
> The point is, the complex number (1, 1) in Cartesian coordinates and
> (sqrt(2),
> pi/4) in polar coordinates aren't two different kinds of things, they are
> two
> different ways of writing the same value. Like writing 1A in hex and 26 in
> decimal. Somebody may choose to implement this as two different classes
> ("CartesianComplex" and "PolarComplex") but that's a limitation of their
> code,
> or of their language, it doesn't reflect a real difference between two
> different kinds of things.
>


Well conceptually you might think of c1 as the abstract representation of a
complex number but at runtime they have very different constitutions.



>
> Another way to put it:
>
> If you were programming a first person shooter game, you might choose each
> of
> the enemies as an object. Let's say you have an enemy called the Grue. You
> can
> view the Grue from the front or from the back, depending on which way it is
> standing when you see it. Would you implement this as two different
> classes?
>
> GrueSeenFromFront
>
> GrueSeenFromBack
>
> I should hope not. It's the same object, the same Grue, it just looks
> different
> depending on which way you approach it.
>
>
>
>
>
> --
> Steve
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list