Hi Stefan,

On Wed, Feb 12, 2014 at 9:42 PM, Stefan Karpinski <[email protected]>wrote:

> Thanks for taking the time and effort to sign up for the list just to
> correct my errors. I swear that I'm not intentionally spreading
> disinformation about Dylan - my mistakes are purely due to ignorance, not
> malice! Dylan is a great language.
>

Glad to hear that you think so. :)


> Dylan's "limited types" do indeed appear to do the trick for allowing
> efficient representation of numeric arrays (among lots of other cool
> things). I was thrown off by the somewhat non-standard naming. Can you
> clarify what distinguishes limited types from parametric types? Is it just
> that the parameters are not considered part of the type, so you can't
> dispatch on them? I had encountered Hannes Mehnert's thesis when looking
> into this earlier, but obviously having a research implementation of a
> non-standard feature doesn't count - by that criterion, Java has every
> language feature ever invented.
>

Limited types are part of the base language. The thesis from Hannes was an
extension to add parametric types to method definitions.  The limited types
are types and can be dispatched upon just like anything else.

    define constant <integer-vector> = limited(<vector>, of: <integer>);

    define method foo (vec :: <vector>)
      ...
    end;

    define method foo (vec :: <integer-vector>)
      ...
    end;

    define method foo (vec :: limited(<vector>, of: <single-float>, size:
4))
      ...
    end;

As for the difference between limited and parametric types, I can't do the
direct equivalent of using parametric types to define a Point class that
might have Float or Integer coordinates as in your documentation.  This is
sometimes annoying, but can also be worked around in some cases, like this
(I think ... not tested):

    define constant <point> = limited(<vector>, size: 2);
    define constant <integer-point> = limited(<vector>, of <integer>, size:
2);
    define constant <float-point> = limited(<vector>, of <single-float>,
size: 2);

    define inline method point-x (p :: <point>)
      p[0]
    end;

    define inline method point-y (p :: <point>)
      p[1]
    end;

    define inline method point-x-setter (x, p :: <point>)
      p[0] := x;
    end;

    define inline method point-y-setter (y, p :: <point>)
      p[0] := y;
    end;

    // This should work:
    let fp :: <float-point> = make(<float-point>);
    fp.point-x := 3;
    fp.point-y := 5;

This could be more elegant, but it should work as expected (so long as
Dylan treats <integer-point> and <float-point> as subtypes of <point>,
which I think it will).  The inlining there should get rid of any dispatch
in most cases and result in good code generation.


> My syntax and o.o. lamentations were really separate from each other. I
> like the S-expression syntax better - I know, that's rich coming from a
> designer of another language with clearly
>

Some people do like it better. There's actually someone who is working on
writing an additional reader for the compiler to support an s-expression
syntax again as an experiment. We aren't sure yet where this will go.


> algol-derived non-S-expression syntax. Completely unrelatedly, I also find
> some of the o.o.-related aspects in Dylan too featurey. I mean things like
> slot and method annotations - protected, private, `init-keyword: foo:`,
> `required-init-keyword: bar:`, etc. There are a lot of these and it seems
> like they can combine in a dizzying number of ways. I'm sure this is all
> thoroughly documented somewhere and it works great, but it's just a lot of
> *stuff*. The business of declaring attributes like this seems to have
> started in Smalltalk and continued in most of its sphere of influence -
> declaring this method to be virtual and that field to be private, etc. It
> just strikes me as fiddly and that there are too many things that can
> combine in too many ways. But like I said, this is a matter of taste.
>

Dylan doesn't have protected, public, private adjectives. The visibility of
a binding is, instead, decided by whether or not it has been exported from
the module / library.  This is discussed some on the Dylan Wikipedia page
as a difference between classical OO and CLOS-style OO. In classical OO,
the class is the unit of encapsulation, while in Dylan and CLOS, it is the
module. This is an extra degree of flexibility and control for the Dylan or
CLOS programmer.

There aren't really that many modifiers and it is pretty easy to grasp when
you're using the language. There are also no "virtual" modifiers. :)


> Questions... Can one inherit from concrete types in Dylan, as you can in
> most object systems? Is there a way to create user-defined immutable types?
>

You can inherit from any class that hasn't been sealed.  For a sealed
class, it can only be extended within the same module that defines it.
(This is part of the Dylan philosophy of allowing the programmer to put
limits on the dynamicism of the system so that the compiler can optimize
better).

As for immutable types, you have 2 options.

First is to just define all of the slots to be constant:

    define class <point> (<object>)
        constant slot point-x :: <number>,
          required-init-keyword: x:;
        constant slot point-y :: <number>,
          required-init-keyword: y:;
    end;

Now, you can create and work with points:

    let p = make(<point>, x: 3, y: 5);
    format-out("p is at (%d, %d)\n", p.point-x, p.point-y);

Or, you could define the slot to not be constant, but not export the setter
functions from the module. This allows you to easily control who has access
to modifying the object.


> Thanks again for stopping by!
>

No problem!

 - Bruce

Reply via email to