comp.lang.ada
 help / color / mirror / Atom feed
* discriminant questions
@ 2011-09-17 16:30 ytomino
  2011-09-17 17:19 ` Dmitry A. Kazakov
  2011-09-18 16:32 ` ytomino
  0 siblings, 2 replies; 89+ messages in thread
From: ytomino @ 2011-09-17 16:30 UTC (permalink / raw)


Hello, I'm excited at the containers of Ada 2012.
I tried to write my code with the style of Ada 2012, and I have some
questions.

1) Why is below code error?

procedure q1 is
   generic
      type e is private;
   package the_package_like_ada2012_vector is
      type ref (element : not null access e) is null record;
   end the_package_like_ada2012_vector;
   generic
      type e is private;
      type ref (element : not null access e) is private;
   package the_package_use_ref is
   end the_package_use_ref;
   package inst1 is new the_package_like_ada2012_vector (integer);
   package inst2 is new the_package_use_ref (integer, inst1.ref); --
error
begin
   null;
end q1;

q1.adb:13:65: types of actual discriminants must match formal
q1.adb:13:65: instantiation abandoned

It seems no way to write a generic algorithm independent of a
container.
(without Element or Query_Element of Ada 2005 style)

2) Why non-limited types can not have access discriminant with
default?

procedure q2 is
	type t1 (value : integer := 100) is null record; -- ok
	type int_access is access all integer;
	default : aliased int_access := null;
	type t2 (element : access int_access := default'access) is null
record; -- error
begin
	null;
end q2;

q2.adb:5:56: (Ada 2005) access discriminants of nonlimited types
q2.adb:5:56: cannot have defaults

I would like to write smart pointer and make that it is able to assign-
able type,
as follows:

declare
   a : the_smart_pointer (element => wrap (new Integer'(100)));
   b : the_smart_pointer (element => wrap (new Integer'(200)));
begin
   a.element.all.all := 300; -- a.all := 300; (if compiler supported
Implicit_Dereference)
   b := a; -- it frees element of b on Finalize and add reference
count of a on Assign
end;

Why is it disallowed?

Thank you.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 16:30 discriminant questions ytomino
@ 2011-09-17 17:19 ` Dmitry A. Kazakov
  2011-09-17 17:46   ` ytomino
  2011-09-18 16:32 ` ytomino
  1 sibling, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-17 17:19 UTC (permalink / raw)


On Sat, 17 Sep 2011 09:30:46 -0700 (PDT), ytomino wrote:

> I would like to write smart pointer and make that it is able to assign-
> able type, as follows:
> 
> declare
>    a : the_smart_pointer (element => wrap (new Integer'(100)));
>    b : the_smart_pointer (element => wrap (new Integer'(200)));
> begin
>    a.element.all.all := 300; -- a.all := 300; (if compiler supported
> Implicit_Dereference)
>    b := a; -- it frees element of b on Finalize and add reference
> count of a on Assign
> end;

Given:

   with Object.Handle;

   type Integer_Object is new Object.Entity with record
      Value : Integer;
   end record;
   type Integer_Object_Ptr is access Integer_Object'Class;

   package Integer_Handles is
      new Object.Handle (Integer_Object, Integer_Object_Ptr);
   use Integer_Handles;

   function Wrap (Value : Integer) return Handle is
   begin
      return Ref (new Integer_Object'(Object.Entity with Value));
   end Wrap;

You write:

   use Integer_Handles;

   A : Handle := Wrap (100);
   B : Handle := Wrap (200);
begin
   A.Ptr.Value := 300;
   B := A; -- Frees B.Ptr, increases the count of A.Ptr

For the sample sources see:

http://www.dmitry-kazakov.de/ada/components.htm#Objects_etc

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 17:19 ` Dmitry A. Kazakov
@ 2011-09-17 17:46   ` ytomino
  2011-09-17 19:41     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-17 17:46 UTC (permalink / raw)


Thanks Dmitry, but I already understand that smart pointer is able to
write with Ada 95.
I'm trying to make it as same syntax of raw access types by
Implicit_Dereference,
like smart pointer of C++ having implicit cast operator T*().



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 17:46   ` ytomino
@ 2011-09-17 19:41     ` Dmitry A. Kazakov
  2011-09-17 22:55       ` ytomino
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-17 19:41 UTC (permalink / raw)


On Sat, 17 Sep 2011 10:46:44 -0700 (PDT), ytomino wrote:

> I'm trying to make it as same syntax of raw access types by
> Implicit_Dereference, like smart pointer of C++ having implicit cast operator T*().

C++ does not have implicit dereferencing at all. Ada has it but only for
attributes, array indexing, component members.

In all other cases you have to use explicit .all. And .Ptr is neither worse
nor better. What are you trying to achieve?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 19:41     ` Dmitry A. Kazakov
@ 2011-09-17 22:55       ` ytomino
  2011-09-18  8:50         ` Dmitry A. Kazakov
  2011-09-19 23:35         ` Randy Brukardt
  0 siblings, 2 replies; 89+ messages in thread
From: ytomino @ 2011-09-17 22:55 UTC (permalink / raw)


>C++ does not have implicit dereferencing at all. Ada has it but only for
> attributes, array indexing, component members.

C++ has it.

struct reference_type {
	int *element;
	operator int & () { return *element; }
};

This code is same as:

type Reference_Type (Element : access Integer) is null record;

and replace int * to int ** and int & to int *&,
we can use reference_type where raw pointer is required.
(In fact, smart pointers in Boost and C++0x have not cast operator
but operator * and operator -> . However client codes are same.)

Therefore, there is no reason that we could not it with Ada.
...except assignment.

Two Ada variables having different discriminant are incompatible
and it raise Constraint_Error at runtime.
But if default value exists, we can assign these variables.

Return to the first question. An access discriminant can not have
default value.
So I can not make smart pointer like syntax of raw access types after
all.
I want to know the reason.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 22:55       ` ytomino
@ 2011-09-18  8:50         ` Dmitry A. Kazakov
  2011-09-18 10:54           ` ytomino
  2011-09-20  0:01           ` Randy Brukardt
  2011-09-19 23:35         ` Randy Brukardt
  1 sibling, 2 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-18  8:50 UTC (permalink / raw)


On Sat, 17 Sep 2011 15:55:15 -0700 (PDT), ytomino wrote:

>>C++ does not have implicit dereferencing at all. Ada has it but only for
>> attributes, array indexing, component members.
> 
> C++ has it.
> 
> struct reference_type {
> 	int *element;
> 	operator int & () { return *element; }
> };

Dereferencing is implicit when a pointer is substitutable in the context
where the target type is expected. Though C++ supports user-defined type
conversions, it does not do it for pointers.

> This code is same as:
> 
> type Reference_Type (Element : access Integer) is null record;

It is not same, and I don't see the purpose of using this construct. In any
case it cannot serve as a good basis for smart pointers.

> Therefore, there is no reason that we could not it with Ada.
> ...except assignment.

You can write it, but again, what are you trying to achieve?

> Two Ada variables having different discriminant are incompatible
> and it raise Constraint_Error at runtime.
> But if default value exists, we can assign these variables.

It is not so. Discriminant is an integral part of a value, which can be
changed only together, as a whole. Another issue is that an object can be
constrained to a class of values having certain values of the
discriminants.

> So I can not make smart pointer like syntax of raw access types after
> all.

If you mean specifically overriding the "operation" X.all, no you cannot.
But I see no reason for that in the context of smart pointers, where you
wanted to get rid of pointer semantics, rather than mimic it. The latter is
possible to do in Ada, but admittedly boring. I did it some projects. The
schema is as in the example I gave earlier, plus interfaces on top of it:

   type Foo_Interface is limited interface;
   procedure Bar (X : in out Foo_Interface) is abstract;

   type Foo_Object is
       new Object.Entity and Foo_Interface with record ...;
   overriding procedure Bar (X : in out Foo_Object);

   type Foo_Object_Ptr is access Foo_Object'Class;

   package Foo_Handles is
      new Object.Handle (Foo_Object, Foo_Object_Ptr);

   type Foo_Handle is new Foo_Handles.Handle and Foo_Interface
       with null record;
   overriding procedure Bar (X : in out Foo_Handle);

   procedure Bar (X : in out Foo_Handle) is
   begin
       X.Ptr.Bar; -- Delegation
   end Bar;

Now the object (Foo_Object) and its smart pointer (Foo_Handle) can be used
interchangeably in the context where Foo_Interface is expected.

Normally you would hide the objects and expose only handles to them and
factories returning handles to newly created objects.

> I want to know the reason.

Discriminants of anonymous access types were meant to be safe (though, they
are not). That was the reason for a pile of (incomprehensible) rules
limiting use of such discriminants.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18  8:50         ` Dmitry A. Kazakov
@ 2011-09-18 10:54           ` ytomino
  2011-09-18 11:35             ` Dmitry A. Kazakov
  2011-09-20  0:01           ` Randy Brukardt
  1 sibling, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-18 10:54 UTC (permalink / raw)


> Dereferencing is implicit when a pointer is substitutable in the context
> where the target type is expected. Though C++ supports user-defined type
> conversions, it does not do it for pointers.

You are right. Any (user-defined) implicit conversions are not applied
for raw pointer.
But only implicit conversion from struct to pointer is necessary for
smart pointer.

> If you mean specifically overriding the "operation" X.all, no you cannot.

I would like to make record look like access type, not dereferenced
value.
If we can replace P.Element.all.all to P.all, that is good enough.
(type of P.Element is access access target-type)
".all" is applied to raw access value on my plan.
Probably it's not related that you are worried.

> but again, what are you trying to achieve?

No purpose.
If you insist, my purpose is trying new feature which seems to be
interesting.

> Discriminants of anonymous access types were meant to be safe (though, they
> are not). That was the reason for a pile of (incomprehensible) rules
> limiting use of such discriminants.

uh-huh...mm...



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 10:54           ` ytomino
@ 2011-09-18 11:35             ` Dmitry A. Kazakov
  2011-09-18 12:41               ` ytomino
                                 ` (2 more replies)
  0 siblings, 3 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-18 11:35 UTC (permalink / raw)


On Sun, 18 Sep 2011 03:54:48 -0700 (PDT), ytomino wrote:

>> If you mean specifically overriding the "operation" X.all, no you cannot.
> 
> I would like to make record look like access type, not dereferenced
> value.

That is. You want to implement the interface of an access type (X.all is a
part of this interface) by a type which is not access. Ada does not allow
this, unfortunately.

My position is that interfaces of all types must be inheritable and
implementable, including access types, but most people here disagree with
me.

> If we can replace P.Element.all.all to P.all, that is good enough.
> (type of P.Element is access access target-type)
> ".all" is applied to raw access value on my plan.
> Probably it's not related that you are worried.

But you can have P.Element which is much more comfortable. There is no
reason to expose access semantics if you can avoid it. And smart pointers
are to hide pointers rather than to expose them.

> If you insist, my purpose is trying new feature which seems to be
> interesting.

I am not sure if Ada 2012 offers new features interesting for designers of
container libraries. OK, maybe one, functions have finally got [in] out
parameters.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 11:35             ` Dmitry A. Kazakov
@ 2011-09-18 12:41               ` ytomino
  2011-09-18 13:17                 ` Dmitry A. Kazakov
  2011-09-18 14:43               ` Dmitry A. Kazakov
  2011-09-18 16:46               ` Robert A Duff
  2 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-18 12:41 UTC (permalink / raw)


> That is. You want to implement the interface of an access type (X.all is a
> part of this interface) by a type which is not access.
Yes.

> Ada does not allow this, unfortunately.
OK.
...If I remove assignment operation like unique_ptr of C++0x, it's
possible.

> My position is that interfaces of all types must be inheritable and
> implementable, including access types, but most people here disagree with
> me.
I agree with you. I want to make multi-precision Big_Integer, more
usable Unbounded_String, etc, too.

> But you can have P.Element which is much more comfortable. There is no
> reason to expose access semantics if you can avoid it. And smart pointers
> are to hide pointers rather than to expose them.
If it hides semantics of access type,
Ada.Containers.Indefinite_Holders gives good interface.
(if reference-counted implementation is provided.
but http://gcc.gnu.org/svn/gcc/trunk/gcc/ada/a-coinho.adb is not.)



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 12:41               ` ytomino
@ 2011-09-18 13:17                 ` Dmitry A. Kazakov
  2011-09-18 16:22                   ` ytomino
  2011-09-18 16:32                   ` ytomino
  0 siblings, 2 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-18 13:17 UTC (permalink / raw)


On Sun, 18 Sep 2011 05:41:24 -0700 (PDT), ytomino wrote:

>> But you can have P.Element which is much more comfortable. There is no
>> reason to expose access semantics if you can avoid it. And smart pointers
>> are to hide pointers rather than to expose them.

> If it hides semantics of access type,
> Ada.Containers.Indefinite_Holders gives good interface.

One problem of Indefinite_Holders is the definition of "=",  it is wrong
because Holder is declared tagged. When tagged, "=" must be doubly
dispatching. The correct definition should at least be:

   function "=" (Left : Holder; Right : Holder'Class) return Boolean;
        -- Emulates double dispatch by cascaded dispatch

But this is only an indicator of a bigger problem, which is that the design
does not support Element_Type classes. I understand that they didn't want
Holder'Class but must allow it to support prefix notation. This is how
language design problems get reflected in the container design!

Anyway, in my experience smart pointers become almost useless without
classes. I.e. you want a hierarchy of elements accompanied by a hierarchy
of smart pointers/handles/holders (name it as you wish). You also need
*same* set of operations implemented by both, such that operations on the
pointer would be delegated to the object. I.e. you don't want:

   X.Element + Y.Element

you want

   X + Y

instead. Even less you want pseudo-functional mess like:

   X.Update (Invert'Access);

you do

   Invert (X);

> (if reference-counted implementation is provided.
> but http://gcc.gnu.org/svn/gcc/trunk/gcc/ada/a-coinho.adb is not.)

My implementation uses reference counting, because its intended use was to
be a smart pointer. The intended use of Indefinite_Holders is not smart
pointers. It is only a definite wrapper for an indefinite content, only
this nothing more. Smart pointer is also definite, but much more than just
that. From smart pointers you expect them being comparable, delegating
operations, managing shared objects, supporting serialization, task safety
and so on.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 11:35             ` Dmitry A. Kazakov
  2011-09-18 12:41               ` ytomino
@ 2011-09-18 14:43               ` Dmitry A. Kazakov
  2011-09-18 16:46               ` Robert A Duff
  2 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-18 14:43 UTC (permalink / raw)


On Sun, 18 Sep 2011 13:35:47 +0200, Dmitry A. Kazakov wrote:

> On Sun, 18 Sep 2011 03:54:48 -0700 (PDT), ytomino wrote:
> 
>> If you insist, my purpose is trying new feature which seems to be
>> interesting.
> 
> I am not sure if Ada 2012 offers new features interesting for designers of
> container libraries. OK, maybe one, functions have finally got [in] out
> parameters.

I forgot about aspects. It is difficult to evaluate their usefulness for
containers, let us see.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 13:17                 ` Dmitry A. Kazakov
@ 2011-09-18 16:22                   ` ytomino
  2011-09-18 16:32                   ` ytomino
  1 sibling, 0 replies; 89+ messages in thread
From: ytomino @ 2011-09-18 16:22 UTC (permalink / raw)


You're right.
Smart pointer shold support type conversions supported on raw access
types like access all to access constant, or derived type to base
type.
Indefinite_Holder does not support these conversions.
I was not careful of it.

>   X + Y

Well, if semantics of smart pointer differs from semantics of value, I
think it makes misunderstanding.
(so I want to write X.all + Y.all)



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 13:17                 ` Dmitry A. Kazakov
  2011-09-18 16:22                   ` ytomino
@ 2011-09-18 16:32                   ` ytomino
  2011-09-18 18:15                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-18 16:32 UTC (permalink / raw)


You're right.
Smart pointer shold support type conversions supported on raw access
types
like access all to access constant, or derived type to base type.
Indefinite_Holder does not support these conversions.
I was not careful of it.

>   X + Y
If semantics of smart pointer differs from semantics of value, it may
make misunderstanding.
(so I prefer to write X.all + Y.all)



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 16:30 discriminant questions ytomino
  2011-09-17 17:19 ` Dmitry A. Kazakov
@ 2011-09-18 16:32 ` ytomino
  2011-09-19 14:46   ` ytomino
  1 sibling, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-18 16:32 UTC (permalink / raw)


By the way, would anybody answer to (1) ?



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 11:35             ` Dmitry A. Kazakov
  2011-09-18 12:41               ` ytomino
  2011-09-18 14:43               ` Dmitry A. Kazakov
@ 2011-09-18 16:46               ` Robert A Duff
  2011-09-18 18:01                 ` Dmitry A. Kazakov
  2 siblings, 1 reply; 89+ messages in thread
From: Robert A Duff @ 2011-09-18 16:46 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> I am not sure if Ada 2012 offers new features interesting for designers of
> container libraries. OK, maybe one, functions have finally got [in] out
> parameters.

There's a whole bunch of stuff.  Look at these AI's:

AI05-0139-2.TXT : !subject Syntactic sugar for accessors, containers, and iterators
AI05-0142-4.TXT : !subject Explicitly aliased parameters
AI05-0143-1.TXT : !subject In Out parameters for functions
AI05-0162-1.TXT : !subject Allow incomplete types to be completed by partial views
AI05-0212-1.TXT : !subject Accessors and Iterators for Ada.Containers

The stuff you need to know for writing containers is pretty arcane.
But the use of containers becomes much simpler.
For example, you can say things like:

    A(X).Y := A(X).Y + 1;

whether A is an array or a Vector.

- Bob



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 16:46               ` Robert A Duff
@ 2011-09-18 18:01                 ` Dmitry A. Kazakov
  2011-09-18 19:20                   ` Maciej Sobczak
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-18 18:01 UTC (permalink / raw)


On Sun, 18 Sep 2011 12:46:19 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> I am not sure if Ada 2012 offers new features interesting for designers of
>> container libraries. OK, maybe one, functions have finally got [in] out
>> parameters.
> 
> There's a whole bunch of stuff.  Look at these AI's:
> 
> AI05-0139-2.TXT : !subject Syntactic sugar for accessors, containers, and iterators
> AI05-0142-4.TXT : !subject Explicitly aliased parameters

When interfaces were introduced I thought they would make the use simpler,
but that didn't happen, because re-use was thrown overboard. Limited
results and aggregates was an obvious miss. The mentioned features look
much like hacks.

> AI05-0143-1.TXT : !subject In Out parameters for functions

Finally.

> AI05-0162-1.TXT : !subject Allow incomplete types to be completed by partial views

This one is helpful, I ran into this one or two times.

> AI05-0212-1.TXT : !subject Accessors and Iterators for Ada.Containers

I don't care about iterators and accessors, they IMO are just
misconceptions coming from languages with pointers.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 16:32                   ` ytomino
@ 2011-09-18 18:15                     ` Dmitry A. Kazakov
  2011-09-18 23:44                       ` ytomino
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-18 18:15 UTC (permalink / raw)


On Sun, 18 Sep 2011 09:32:00 -0700 (PDT), ytomino wrote:

> Smart pointer shold support type conversions supported on raw access
> types like access all to access constant, or derived type to base type.

They should rather be transparent to constraining, e.g. immutability
constraint must propagate from the target subtype to the pointer subtype.
Compare it with renaming. When you rename an immutable object the result is
immutable.

> Indefinite_Holder does not support these conversions.

There is Implicit_Dereference aspect introduced in Ada 2012, but in such a
strange way that made it impossible to define on Holder itself, rather on
another type obtained from Holder using a function! What was the gain?

>>   X + Y
> If semantics of smart pointer differs from semantics of value, it may
> make misunderstanding.

There is no difference, compare it with by-reference parameters. The
program shall not be written to exploit by-reference vs. by-value. Smart
pointer is a substitute for what it points to.

> (so I prefer to write X.all + Y.all)

If you are happy with such mess, then what is wrong with X.Element +
Y.Element?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 18:01                 ` Dmitry A. Kazakov
@ 2011-09-18 19:20                   ` Maciej Sobczak
  2011-09-19  7:39                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Maciej Sobczak @ 2011-09-18 19:20 UTC (permalink / raw)


On Sep 18, 8:01 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> I don't care about iterators and accessors, they IMO are just
> misconceptions coming from languages with pointers.

Problem: enumerate elements from two parallel containers (aka
zipping).

Even with a single container an iterator is more flexible than an
enumeration operation if the iteration logic is more involved than a
single pass over the whole. Like iterate from the beginning until you
find some specific value. Or get top 10 from a sorted container. And
so on.

Which might mean that the concept of pointers is not completely
missing the point (pun intended).

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 18:15                     ` Dmitry A. Kazakov
@ 2011-09-18 23:44                       ` ytomino
  2011-09-19  7:27                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-18 23:44 UTC (permalink / raw)


>>>   X + Y
>> If semantics of smart pointer differs from semantics of value, it may
>> make misunderstanding.
>
> There is no difference, compare it with by-reference parameters. The
> program shall not be written to exploit by-reference vs. by-value. Smart
> pointer is a substitute for what it points to.

Ada has mainly value semantics.
If container is intended to be used as value (like Indefinite_Holder),
"substitutable" is natural.
But if container is intended to be used as access type (like smart
pointer or handle), I think, it is unnatural.
Because we can define another operation having same name for access
type.

type Integer_Access is access Integer;
function "+" (Left : Integer_Access; Right : Storage_Offset) return
Integer_Access;

declare
   a, b : Integer;
   c : Integer_Access; d : Storage_Offset;
begin
   a + b -- sum of integers
   c + d -- address arithmetic
   c.all + d -- sum of referenced integer and offset value
end;

(of course, we usually does not address arithmetic with smart pointer.
this is supposed story.)



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 23:44                       ` ytomino
@ 2011-09-19  7:27                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-19  7:27 UTC (permalink / raw)


On Sun, 18 Sep 2011 16:44:08 -0700 (PDT), ytomino wrote:

> But if container is intended to be used as access type (like smart
> pointer or handle), I think, it is unnatural.

No, in that (rare) case the container shall explicitly use access types. 

For a smart pointer (handle), being a hidden reference is an implementation
detail not to be exposed, detected, exploited.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 19:20                   ` Maciej Sobczak
@ 2011-09-19  7:39                     ` Dmitry A. Kazakov
  2011-09-19 20:00                       ` Maciej Sobczak
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-19  7:39 UTC (permalink / raw)


On Sun, 18 Sep 2011 12:20:26 -0700 (PDT), Maciej Sobczak wrote:

> On Sep 18, 8:01�pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> I don't care about iterators and accessors, they IMO are just
>> misconceptions coming from languages with pointers.
> 
> Problem: enumerate elements from two parallel containers (aka
> zipping).

What is wrong with using relative positions? Actually, mathematically,
there is no other way, and the word enumeration technically means a mapping
of the elements of a set onto a set numbers.

> Which might mean that the concept of pointers is not completely
> missing the point (pun intended).

It does. Consider a container located in a machine registers, where are the
pointers? The pointer itself is based on an enumeration in mathematical
sense of this word, where memory elements are mapped onto numbers.

The problem of pointers/iterators etc is that they require more than needed
(persistent element identity), which is a burden for both the container
designer and the user of. It might be a minor problem for C++, which walked
wrong path from very beginning: in C you can have pointer to almost
anything. But Ada tried not fall into this.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18 16:32 ` ytomino
@ 2011-09-19 14:46   ` ytomino
  2011-09-19 15:14     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-19 14:46 UTC (permalink / raw)


Please look below:

procedure q1 is
   generic
      type e is private;
   package the_package_like_ada2012_vector is
      type ref (element : not null access e) is null record;
   end the_package_like_ada2012_vector;
   generic
      type e is private;
      type ref (element : not null access e) is private;
   package the_package_use_ref is
   end the_package_use_ref;
   package inst1 is new the_package_like_ada2012_vector (integer);
   package inst2 is new the_package_use_ref (integer, inst1.ref); --
error (line 13)
   -- additional from here
   type int_ref (element : not null access Integer) is null record;
   package inst3 is new the_package_use_ref (integer, int_ref); --
ok !?!?
begin
   null;
end q1;
-- q1.adb:13:65: types of actual discriminants must match formal
-- q1.adb:13:65: instantiation abandoned

I can not understand the reason that inst1 is error and inst2 is ok.
It seems bug to me.

Can someone tell me which is this bug or specified in RM?
If this is actual bug, I'd like to report it to gcc.

Quick fix for the time being: (is this fix correct?)

Index: gcc/ada/sem_ch12.adb
===================================================================
--- gcc/ada/sem_ch12.adb	(revision 178831)
+++ gcc/ada/sem_ch12.adb	(working copy)
@@ -10158,10 +10158,10 @@
                   if Ekind (Base_Type (Formal_Subt)) =
E_Anonymous_Access_Type
                     and then (Ekind (Base_Type (Etype
(Actual_Discr)))) =
                                 E_Anonymous_Access_Type
-                    and then
+                    and then Subtypes_Match (
                       Get_Instance_Of
-                        (Designated_Type (Base_Type (Formal_Subt))) =
-                           Designated_Type (Base_Type (Etype
(Actual_Discr)))
+                        (Designated_Type (Base_Type (Formal_Subt))),
+                           Designated_Type (Base_Type (Etype
(Actual_Discr))))
                   then
                      null;



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19 14:46   ` ytomino
@ 2011-09-19 15:14     ` Dmitry A. Kazakov
  2011-09-19 17:49       ` ytomino
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-19 15:14 UTC (permalink / raw)


On Mon, 19 Sep 2011 07:46:15 -0700 (PDT), ytomino wrote:

> Please look below:
> 
> procedure q1 is
>    generic
>       type e is private;
>    package the_package_like_ada2012_vector is
>       type ref (element : not null access e) is null record;
>    end the_package_like_ada2012_vector;
>    generic
>       type e is private;
>       type ref (element : not null access e) is private;

<I am not a language lawyer>

The relevant part is probably 12.5.1(14):

"The subtype of each discriminant of the actual type shall statically match
the subtype of the corresponding discriminant of the formal type."

which I read as *no formal generic discriminants*. I.e. if "statically
match" means what I think, then "element" in

   type ref (element : not null access e) is private;

cannot be matched because "e" is a formal generic parameter.

</I am not a language lawyer>

As a work-around, make the second package a child or pass the first one as
a parameter to it.

BTW, as my experience shows, designs based on generics fail, and ones
passing formal parameters of one generics to other generics fail always.
Nobody would ever able to instantiate this mess or say what was wrong.
Generic children/formal packages alleviate the problem.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19 15:14     ` Dmitry A. Kazakov
@ 2011-09-19 17:49       ` ytomino
  2011-09-20  7:29         ` Georg Bauhaus
  2011-09-20  8:08         ` Dmitry A. Kazakov
  0 siblings, 2 replies; 89+ messages in thread
From: ytomino @ 2011-09-19 17:49 UTC (permalink / raw)


> The relevant part is probably 12.5.1(14):
> "The subtype of each discriminant of the actual type shall statically match
> the subtype of the corresponding discriminant of the formal type."
> which I read as *no formal generic discriminants*. I.e. if "statically
> match" means what I think, then "element" in
>    type ref (element : not null access e) is private;
> cannot be matched because "e" is a formal generic parameter.

Thanks. Yes, I did grep RM just now and found the definition of
"statically match". It's written in 4.9.1:

* both are null constraints;
* both are static and have equal corresponding bounds or discriminant
values;
* both are nonstatic and result from the same elaboration of a
constraint of a subtype_indication or the same evaluation of a range
of a discrete_subtype_definition; or
* both are nonstatic and come from the same formal_type_declaration.
<- *A*

4th clause (*A*) is probably applied.
It seems that a formal type is match only itself.
However, it does not explain why does int_ref (having access Integer)
match the_package_use_ref.ref (having access e), since Integer is not
e statically.

(sorry,
> I can not understand the reason that inst1 is error and inst2 is ok.
This is my typo. "inst2 is error and inst3 is ok" is right.)

Should inst3 be error if inst2 is error?

As another reason, if it is disallowed, we can not replace generic
algorithm from Ada 2005 interface to Ada 2012 interface.

for example, from

-- "count" algorithm with Ada 2005 version
generic
   type Element_Type (<>) is private;
   type Cursor is private;
   type Container is private;
   with procedure Iterate (C : Container; Proc : access procedure (P :
Cursor));
   with function Element (P : Cursor) return Element_Type;
procedure Generic_Count (C : Container; Value : Element_Type) return
Count_Type;

to

-- "count" algorithm with Ada 2005 version
generic
   type Element_Type (<>) is private;
   type Cursor is private;
   type Container is private;
   package Iterator_Interfaces is
      new Ada.Iterator_Interfaces (Cursor, others => <>);
   with function Iterate (C : Container)
      return Iterator_Interfaces.Forward_Iterator'Class;
   type Constant_Reference_Type (
      Element : not null access constant Element_Type) with private;
<- *B*
   with function Constant_Reference (C : Container; P : Cursor)
      return Constant_Reference_Type;
procedure Generic_Count (C : Container; Value : Element_Type) return
Count_Type;

There is no way to use a instance of Vectors.Constant_Reference_Type
as *B*.
We have to use Element or Query_Element still in generic.
I feel this is strange and I think designer(s) of new containers did
not intend it.

> As a work-around, make the second package a child or pass the first one as
> a parameter to it.

It means that we have to write plural versions of Generic_Count for
Vectors, for Doubly_Linked_Lists, for Ordered_Sets and more.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19  7:39                     ` Dmitry A. Kazakov
@ 2011-09-19 20:00                       ` Maciej Sobczak
  2011-09-20  7:33                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Maciej Sobczak @ 2011-09-19 20:00 UTC (permalink / raw)


On Sep 19, 9:39 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > Problem: enumerate elements from two parallel containers (aka
> > zipping).
>
> What is wrong with using relative positions? Actually, mathematically,
> there is no other way, and the word enumeration technically means a mapping
> of the elements of a set onto a set numbers.

Mathematically you can pretend that the physicality of some operations
can be ignored.
But try your idea with linked lists.

> > Which might mean that the concept of pointers is not completely
> > missing the point (pun intended).
>
> It does. Consider a container located in a machine registers, where are the
> pointers?

I'm not interested in impractical examples.

Note also that it is a problem of the compiler, not mine - the same
issue as with access to single variable, which might be possibly
stored in a register. I don't need to know how this is done at the
level of registers, I'm interested in high-level results.

> The pointer itself is based on an enumeration in mathematical
> sense of this word, where memory elements are mapped onto numbers.

Interesting, but off-topic. What we are interested in is not memory
elements, but the ability of some entity (the iterator) to represent -
and be dereferenced! - a value within the container.

> The problem of pointers/iterators etc is that they require more than needed
> (persistent element identity), which is a burden for both the container
> designer and the user of.

Could you elaborate and why this is a problem?

> But Ada tried not fall into this.

But now we see that the idea is useful. Like in container zipping.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-17 22:55       ` ytomino
  2011-09-18  8:50         ` Dmitry A. Kazakov
@ 2011-09-19 23:35         ` Randy Brukardt
  2011-09-20 21:39           ` ytomino
  1 sibling, 1 reply; 89+ messages in thread
From: Randy Brukardt @ 2011-09-19 23:35 UTC (permalink / raw)


"ytomino" <aghia05@gmail.com> wrote in message 
news:0d272f62-67d0-4905-972c-8a7e912c5531@en1g2000vbb.googlegroups.com...
...
> Return to the first question. An access discriminant can not have
> default value.
> So I can not make smart pointer like syntax of raw access types after all.
> I want to know the reason.

The short answer is that the model of access discriminants is such that 
objects with them can never allow them to be changed. The reasons for this 
are extremely hard to explain (it has to do with accessibility checking - 
the RM text that Steve Baird has started calling the "heart of darkness" 
;-), and I'm not going to try.

If you want to try to understand it, I suggest you read the AARM notes in 
3.7, particularly those following 3.7(10).

And if you succeed at understanding this, I suggest that you immediately 
join the ARG, because we could use the help. :-)

                                         Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-18  8:50         ` Dmitry A. Kazakov
  2011-09-18 10:54           ` ytomino
@ 2011-09-20  0:01           ` Randy Brukardt
  2011-09-20  7:38             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 89+ messages in thread
From: Randy Brukardt @ 2011-09-20  0:01 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:148cxoyabima2.16mz6xwdph2hj.dlg@40tude.net...
> On Sat, 17 Sep 2011 15:55:15 -0700 (PDT), ytomino wrote:
...
>> This code is same as:
>>
>> type Reference_Type (Element : access Integer) is null record;
>
> It is not same, and I don't see the purpose of using this construct. In 
> any
> case it cannot serve as a good basis for smart pointers.

The "good reason" for using this construct (beyond the obvious one of being 
able to use the "implicit dereference" construct is one of lifetime. The 
access discriminant of this object has the same lifetime as the enclosing 
object; if that object is returned from a function, that is very short.

That's important to prevent users from creating dangling pointers to 
elements stored inside of a container (including a smart pointer container). 
What we want is for the container to be able to manage the actual objects as 
it sees fit, so it should not be possible for a user to keep an access to an 
element for any length of time.

We originally had looked at other ways of getting this safety, but 
eventually it was pointed out that we already had a way to get it with the 
existing constructs. Thus we simply used those constructs rather than 
creating more rules and cruft -- the only new things here are the aspects 
that allow dropping part of the text (the name of the discriminant).

We then went a step further and defined indexing operations that allow 
omitting even more of these calls, making them syntactically look like array 
indexing.

It should be noted that the primary purpose behind all of these things is 
making the Vector and Map containers easier to use; the others are made 
consistent but they were not the primary focus. I don't think they help much 
for the Holders (and we decided not to use them on the unbounded strings 
because writing would not have worked well).

                                          Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19 17:49       ` ytomino
@ 2011-09-20  7:29         ` Georg Bauhaus
  2011-09-20 19:50           ` ytomino
  2011-09-20  8:08         ` Dmitry A. Kazakov
  1 sibling, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-20  7:29 UTC (permalink / raw)


On 19.09.11 19:49, ytomino wrote:

> -- "count" algorithm with Ada 2005 version
> generic
>     type Element_Type (<>) is private;
>     type Cursor is private;
>     type Container is private;
>     package Iterator_Interfaces is
>        new Ada.Iterator_Interfaces (Cursor, others =>  <>);
>     with function Iterate (C : Container)
>        return Iterator_Interfaces.Forward_Iterator'Class;
>     type Constant_Reference_Type (
>        Element : not null access constant Element_Type) with private;
> <- *B*
>     with function Constant_Reference (C : Container; P : Cursor)
>        return Constant_Reference_Type;
> procedure Generic_Count (C : Container; Value : Element_Type) return
> Count_Type;
>
> There is no way to use a instance of Vectors.Constant_Reference_Type
> as *B*.

(I have taken the liberty of choosing name `Iterator` for
formal function `Iterate`, since a different `Iterate` is
already taken by the container packages.)

function Generic_Count
   (C : Container;
    Value : Element_Type)
    return Ada.Containers.Count_Type
is
    use type Ada.Containers.Count_Type;

    Sum : Ada.Containers.Count_Type := 0;
    -- overall result


    procedure Use_CRefT (Wrap : Constant_Reference_Type) is
    begin
       if Wrap.Element.all = Value then
          Sum := Sum + 1;
       end if;
    end Use_CRefT;

    procedure Search (Position : Cursor) is
       Element_To_Be_Pointed_At : Constant_Reference_Type
           renames Constant_Reference (C, Position);
    begin
       Use_CRefT(Element_To_Be_Pointed_At);
    end Search;

    Star : Iterator_Interfaces.Forward_Iterator'Class := Iterator (C);
    Pos : Cursor;

begin

    Pos := Iterator_Interfaces.First (Star);
    while Pos /= Iterator_Interfaces.No_Element loop
       Search (Pos);
       Pos := Iterator_Interfaces.Next (Star, Pos);
    end loop;

    return Sum;
end Generic_Count;


I think, though, that Query_Element will obviate the need for the
wrapping pointer types; not sure I understand why you want them.
Is this influenced by a 1:1 transport of C++ STL algorithms?

I wonder whether the C++ STL would be different if C++ could use
proper nesting or in case it had drawn more attention to function
objects.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19 20:00                       ` Maciej Sobczak
@ 2011-09-20  7:33                         ` Dmitry A. Kazakov
  2011-09-20 15:45                           ` Maciej Sobczak
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-20  7:33 UTC (permalink / raw)


On Mon, 19 Sep 2011 13:00:15 -0700 (PDT), Maciej Sobczak wrote:

> But try your idea with linked lists.

Linked list is not a container, nor need it any iterators.

We have to distinguish the interfaces and implementations, BTW.

>>> Which might mean that the concept of pointers is not completely
>>> missing the point (pun intended).
>>
>> It does. Consider a container located in a machine registers, where are the
>> pointers?
> 
> I'm not interested in impractical examples.

It is a very practical example, because the same problem arise with all
sorts of caching techniques for containers handled externally, e.g. network
peers, DB engines, hardware accelerators etc, everywhere identifying
objects is expensive and sometimes fundamentally impossible (e.g. in
relational models).

>  I don't need to know how this is done at the
> level of registers, I'm interested in high-level results.

That is why iterators fail.

> What we are interested in is not memory
> elements, but the ability of some entity (the iterator) to represent -
> and be dereferenced! - a value within the container.

See, iterator has pointer semantics, count me out.

>> The problem of pointers/iterators etc is that they require more than needed
>> (persistent element identity), which is a burden for both the container
>> designer and the user of.
> 
> Could you elaborate and why this is a problem?

You stated it already. Iterator is a pointer to the container and to an
element in it, too bad.

>> But Ada tried not fall into this.
> 
> But now we see that the idea is useful. Like in container zipping.

Again, I don't see it useful, I see it harmful.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20  0:01           ` Randy Brukardt
@ 2011-09-20  7:38             ` Dmitry A. Kazakov
  2011-09-20 11:11               ` AdaMagica
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-20  7:38 UTC (permalink / raw)


On Mon, 19 Sep 2011 19:01:05 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:148cxoyabima2.16mz6xwdph2hj.dlg@40tude.net...
>> On Sat, 17 Sep 2011 15:55:15 -0700 (PDT), ytomino wrote:
> ...
>>> This code is same as:
>>>
>>> type Reference_Type (Element : access Integer) is null record;
>>
>> It is not same, and I don't see the purpose of using this construct. In 
>> any case it cannot serve as a good basis for smart pointers.
> 
> The "good reason" for using this construct (beyond the obvious one of being 
> able to use the "implicit dereference" construct is one of lifetime. The 
> access discriminant of this object has the same lifetime as the enclosing 
> object; if that object is returned from a function, that is very short.

That is why this cannot be used for smart pointers. For them the
relationship is exactly opposite: Element always outlive the pointer except
the last one.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19 17:49       ` ytomino
  2011-09-20  7:29         ` Georg Bauhaus
@ 2011-09-20  8:08         ` Dmitry A. Kazakov
  2011-09-20 18:47           ` ytomino
  1 sibling, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-20  8:08 UTC (permalink / raw)


On Mon, 19 Sep 2011 10:49:18 -0700 (PDT), ytomino wrote:

>> As a work-around, make the second package a child or pass the first one as
>> a parameter to it.
> 
> It means that we have to write plural versions of Generic_Count for
> Vectors, for Doubly_Linked_Lists, for Ordered_Sets and more.

Note that generics poison anything they touch. Every language feature need
a generic counterpart, so not only the discriminants need to have
corresponding formal generic parameter, but also the newly added aspect
stuff. I don't know if Ada 2012 has formal generic implicit_dereference.
Does it?

Anyway the first step to do is generic package interfaces. If you want
Vectors, Doubly_Linked_Lists etc to be used in a generic manner they shall
implement an interface (a generic one, because the packages are generic).
Ada lacks means to describe generic interfaces and to match generic
packages against them.

The whole idea of generic containers used for generic programming is not
sustainable, sorry for delivering an inconvenient truth.

If you want generic programming working do it on the class-wide basis.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20  7:38             ` Dmitry A. Kazakov
@ 2011-09-20 11:11               ` AdaMagica
  2011-09-20 12:09                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: AdaMagica @ 2011-09-20 11:11 UTC (permalink / raw)


On 20 Sep., 09:38, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Mon, 19 Sep 2011 19:01:05 -0500, Randy Brukardt wrote:
>
> >>> type Reference_Type (Element : access Integer) is null record;
>
> > The "good reason" for using this construct (beyond the obvious one of being
> > able to use the "implicit dereference" construct is one of lifetime. The
> > access discriminant of this object has the same lifetime as the enclosing
> > object; if that object is returned from a function, that is very short.
>
> That is why this cannot be used for smart pointers. For them the
> relationship is exactly opposite: Element always outlive the pointer except
> the last one.

Excuse me, but that's nonsense. It is a very good reason to use this
construct.
See AdaCore Gem #107:
http://www.adacore.com/2011/06/06/gem-107-preventing-deallocation-for-reference-counted-types/



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 11:11               ` AdaMagica
@ 2011-09-20 12:09                 ` Dmitry A. Kazakov
  2011-09-20 12:31                   ` AdaMagica
  2011-09-22  3:05                   ` Randy Brukardt
  0 siblings, 2 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-20 12:09 UTC (permalink / raw)


On Tue, 20 Sep 2011 04:11:32 -0700 (PDT), AdaMagica wrote:

> On 20 Sep., 09:38, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Mon, 19 Sep 2011 19:01:05 -0500, Randy Brukardt wrote:
>>
>>>>> type Reference_Type (Element : access Integer) is null record;
>>
>>> The "good reason" for using this construct (beyond the obvious one of being
>>> able to use the "implicit dereference" construct is one of lifetime. The
>>> access discriminant of this object has the same lifetime as the enclosing
>>> object; if that object is returned from a function, that is very short.
>>
>> That is why this cannot be used for smart pointers. For them the
>> relationship is exactly opposite: Element always outlive the pointer except
>> the last one.
> 
> Excuse me, but that's nonsense. It is a very good reason to use this
> construct.
> See AdaCore Gem #107:
> http://www.adacore.com/2011/06/06/gem-107-preventing-deallocation-for-reference-counted-types/

The example just confirms what I said:

   type Smart_Pointer is private;  -- No discriminants!

It uses access discriminant for the *accessor* kludge, which is an absolute
different story (described by Randy): a short-living reference.

P.S. I also see little or no point in using "accessors". Primitive
operations Set and Get would be as good/bad. They are also cleaner, much
more efficient and, what is far more important, they are *primitive*.
Accossor is a new type which means *contravariance*. The stuff is not
composable under inheritance.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 12:09                 ` Dmitry A. Kazakov
@ 2011-09-20 12:31                   ` AdaMagica
  2011-09-20 12:57                     ` Dmitry A. Kazakov
  2011-09-22  3:05                   ` Randy Brukardt
  1 sibling, 1 reply; 89+ messages in thread
From: AdaMagica @ 2011-09-20 12:31 UTC (permalink / raw)


> The example just confirms what I said:
>
>    type Smart_Pointer is private;  -- No discriminants!

OK, I misunderstood

> It uses access discriminant for the *accessor* kludge, which is an absolute
> different story (described by Randy): a short-living reference.
>
> P.S. I also see little or no point in using "accessors". Primitive
> operations Set and Get would be as good/bad.

No, here it's you who misunderstands. Get is still present and returns
an accessor instead of an access type and thus makes accesses safe (no
way to deallocate the accessed object). And Get *is* primitive.

And with reference types and objects in Ada 2012, there is no more
need for explicit dereference:
Get (P).Data simply becomes Get (P), i.e. it is overloaded to mean
either the accessor (or reference) object or the implicit dereference.

> They are also cleaner, much
> more efficient and, what is far more important, they are *primitive*.
> Accossor is a new type which means *contravariance*. The stuff is not
> composable under inheritance.
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 12:31                   ` AdaMagica
@ 2011-09-20 12:57                     ` Dmitry A. Kazakov
  2011-09-20 23:28                       ` ytomino
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-20 12:57 UTC (permalink / raw)


On Tue, 20 Sep 2011 05:31:34 -0700 (PDT), AdaMagica wrote:

>> P.S. I also see little or no point in using "accessors". Primitive
>> operations Set and Get would be as good/bad.
> 
> No, here it's you who misunderstands. Get is still present and returns
> an accessor instead of an access type and thus makes accesses safe (no
> way to deallocate the accessed object). And Get *is* primitive.

Get that returns an independent type breaks inheritance.

Without accessor you have two hierarchies

Object : T <-- S  <-- Q
Handles : T_Handle <-- S_Handle <-- Q_Handle

with accessors you add here a third one:

Accessors : Ref_T <-- Ref_S  <-- Ref_Q

Now, because Ada does not support MD in any usable form, the above would
quickly turn into an utter mess. Get a primitive operation of T_Handle is
contravariant in its result, it will always return Ref_T or at best
Ref_T'Class. It cannot return Ref_S.

> And with reference types and objects in Ada 2012, there is no more
> need for explicit dereference:

What is wrong with Get returning the target: P.Get?

The accessor-kludge does not eliminate anything, it does dereference the
reference it has first introduced!

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20  7:33                         ` Dmitry A. Kazakov
@ 2011-09-20 15:45                           ` Maciej Sobczak
  2011-09-20 16:48                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Maciej Sobczak @ 2011-09-20 15:45 UTC (permalink / raw)


On Sep 20, 9:33 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > But try your idea with linked lists.
>
> Linked list is not a container,

We might be using different definitions, then.

http://www.adaic.org/resources/add_content/standards/05aarm/html/AA-A-18-3.html

The above page literally uses the term "list container" already in the
first paragraph. I can quote specs for several other programming
languages and their libraries if necessary.

> We have to distinguish the interfaces and implementations, BTW.

We have to take into account the physicality of computations, unless
some completely different model is invented (and delivered). That's
why it makes sense to talk about the interface of list container. It
might be different than the interface of some other container (that
is, of some container with a different access model).

> > I'm not interested in impractical examples.
>
> It is a very practical example, because the same problem arise with all
> sorts of caching techniques for containers handled externally,

That's why they will use other interfaces. Or will fail miserably.
(again: you cannot ignore the physicality of computations)

> That is why iterators fail.

You didn't show it.

> > What we are interested in is [...]
> > the ability of some entity (the iterator) to represent -
> > and be dereferenced! - a value within the container.
>
> See, iterator has pointer semantics, count me out.

See, iterator allows me to do things that are impossible otherwise,
count me in.

> Iterator is a pointer to the container and to an
> element in it, too bad.

You didn't show that it is bad.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 15:45                           ` Maciej Sobczak
@ 2011-09-20 16:48                             ` Dmitry A. Kazakov
  2011-09-20 20:19                               ` Maciej Sobczak
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-20 16:48 UTC (permalink / raw)


On Tue, 20 Sep 2011 08:45:31 -0700 (PDT), Maciej Sobczak wrote:

> On Sep 20, 9:33�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>> But try your idea with linked lists.
>>
>> Linked list is not a container,
> 
> We might be using different definitions, then.

"an object used for or capable of holding, esp for transport or storage,
such as a carton, box, etc."

Linked list is a data structure which may serve as an implementation of a
container. But the list itself is nether an object, nor is capable to
transport or store anything, just common sense. As always, reference
manuals are free to disagree with it.

>> We have to distinguish the interfaces and implementations, BTW.
> 
> We have to take into account the physicality of computations, unless
> some completely different model is invented (and delivered).

Yes, that is why forcing referential semantics is bad.

>>> I'm not interested in impractical examples.
>>
>> It is a very practical example, because the same problem arise with all
>> sorts of caching techniques for containers handled externally,
> 
> That's why they will use other interfaces.

That is why I don't care about iterators as they spoil interface with
identity.

>> Iterator is a pointer to the container and to an
>> element in it, too bad.
> 
> You didn't show that it is bad.

I don't need to, some people consider pointers harmful, some enjoy them.
That is out of the scope of this discussions. Assuming that pointers are
bad, so are the iterators.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20  8:08         ` Dmitry A. Kazakov
@ 2011-09-20 18:47           ` ytomino
  2011-09-21  8:16             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-20 18:47 UTC (permalink / raw)


> Note that generics poison anything they touch. Every language feature need
> a generic counterpart, so not only the discriminants need to have
> corresponding formal generic parameter, but also the newly added aspect
> stuff. I don't know if Ada 2012 has formal generic implicit_dereference.
> Does it?
Yes, formal type can have  [aspect_specification].
http://www.ada-auth.org/standards/12rm/html/RM-12-5.html

And it's related only to syntax. If formal type can not have aspect,
we can write ".Element.all" like Georg Bauhaus wrote.

> Anyway the first step to do is generic package interfaces. If you want
> Vectors, Doubly_Linked_Lists etc to be used in a generic manner they shall
> implement an interface (a generic one, because the packages are generic).
> Ada lacks means to describe generic interfaces and to match generic
> packages against them.
> The whole idea of generic containers used for generic programming is not
> sustainable, sorry for delivering an inconvenient truth.
> If you want generic programming working do it on the class-wide basis.

There is an illogical jump in what you say.
The problem is just that Reference/Constant_Reference can be used in
generic, or not.
And it's tiny problem. If Reference/Constant_Reference can not be used
in generic after all, I will use Element or Query_Element as before.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20  7:29         ` Georg Bauhaus
@ 2011-09-20 19:50           ` ytomino
  0 siblings, 0 replies; 89+ messages in thread
From: ytomino @ 2011-09-20 19:50 UTC (permalink / raw)


I'm glad you wrote body of Generic_Count.

> I think, though, that Query_Element will obviate the need for the
> wrapping pointer types; not sure I understand why you want them.
To be honest, I think so, too. Query_Interface is enough. ^_^;
I'm trying to use new inerface. And Constant_Reference makes code a
little easy. You do not need to divide Search and Use_CRefT differ
from Query_Interface.

    procedure Search (Position : Cursor) is
    begin
       if Constant_Reference (C, Position).Element.all = Value then
          Sum := Sum + 1;
       end if;
    end Search;

> Is this influenced by a 1:1 transport of C++ STL algorithms?
> I wonder whether the C++ STL would be different if C++ could use
> proper nesting or in case it had drawn more attention to function
> objects.

It will be wonderful supposing STL algorithms is transplantable.
But I do not feel necessity.
I just want to make my generic subprograms (it is not so general as
STL algorithms) independent of a container for conforming to the first
purpose of abstraction of STL is separation of a container and an
algorithm, but I do NOT want to make a perfect copy of C++.
Of course there is some differences. Iterator of STL mimics pointer,
but Cursor of Ada.Containers mimics index. C++0x has lambda, but Ada
has downward closure, etc. I would like to respect functions in Ada.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 16:48                             ` Dmitry A. Kazakov
@ 2011-09-20 20:19                               ` Maciej Sobczak
  2011-09-21  7:48                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Maciej Sobczak @ 2011-09-20 20:19 UTC (permalink / raw)


On Sep 20, 6:48 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> >> Linked list is not a container,
>
> > We might be using different definitions, then.
>
> "an object used for or capable of holding, esp for transport or storage,
> such as a carton, box, etc."

OK, so on the computer programming discussion group you are using a
generic definition from The Free Dictionary, which contains the
following disclaimer at the bottom of the page:

"This information should not be considered complete, up to date, and
is not intended to be used in place of a visit, consultation, or
advice of a legal, medical, or any other professional."

I have used the definition that is more in line of this:

http://en.wikipedia.org/wiki/Container_%28data_structure%29

"In computer science, a container is a class, a data structure, or an
abstract data type (ADT) whose instances are collections of other
objects. In other words; they are used for storing objects in an
organized way following specific access rules."

By "specific access rules" I understand that these rules can
distinguish some containers from the others. Like, for example, a
container that provides fast insertion in the middle, but not
necessarily fast relative jumps. Like a list container, for example.

Interestingly (from the same page),

"Containers are sometimes implemented in conjunction with iterators."

> Linked list is a data structure which may serve as an implementation of a
> container.

That depends on your definition. According to mine (cited above)
linked list is a container.

> > We have to take into account the physicality of computations, unless
> > some completely different model is invented (and delivered).
>
> Yes, that is why forcing referential semantics is bad.

Nobody is forcing referential semantics, although it might be the most
natural and efficient solution for iterators.
And you still haven't shown that it is bad.

> Assuming that pointers are
> bad, so are the iterators.

Yes, that sounds logical.
But according to the laws of logic and the above statement, we still
don't know whether iterators are bad unless we are up-front biased.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-19 23:35         ` Randy Brukardt
@ 2011-09-20 21:39           ` ytomino
  2011-09-22  3:32             ` Randy Brukardt
  0 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-20 21:39 UTC (permalink / raw)


Thank you for your suggestion. I'm reading AARM now...

For the first time, I got to know the difference between "access
discriminant" and a normal discriminant having named access type.
I am surprised at that a normal discriminant having named access type
can have default and is able to assignment.
But, in RM 4.1 (5 (2/3)), "This aspect is specified by a name that
denotes an access discriminant declared for the type T."...It seems
that a normal discriminant having named access type can not be
Implicit_Dereferene...
Close! It's regrettable.

Back to the subject, lifetime of coextension, It's interesting.
Coextension probably is one of the reason that objects with access
discriminant can never allow them to be changed.
However, I have not resulted in firm belief yet.

As another reason, default of "access discriminant" has been used for
discriminating which a formal limited type in generic is
really(immutably) limited or non-limited since Ada 95.
"immutably limited" concept is used widely. (Therefore it is hard to
change this rule.)

Is my understanding right...?

I have not been found the reason about accessibility check yet.
I'm going to read RM 3.10.2 and AI95-00230-01 at next.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 12:57                     ` Dmitry A. Kazakov
@ 2011-09-20 23:28                       ` ytomino
  2011-09-21  5:03                         ` AdaMagica
  2011-09-21  8:08                         ` Dmitry A. Kazakov
  0 siblings, 2 replies; 89+ messages in thread
From: ytomino @ 2011-09-20 23:28 UTC (permalink / raw)


(To avoid confusion, I do not use names of "Get" and "Set".)

function Element (C : Container) return Element_Type;
function Set_Element (C : Container; New_Item : Element_Type);

These functions may copy Element_Type.
It's futile cost if Element_Type'Size is large.

function Element (C : Container) return access constant Element_Type;

It's dangerous. the reason is written in AdaCore Gem #107.

procedure Query_Element (C : Container; Process : access procedure
(Item : in Element_Type));
procedure Update_Element (C : Container; Process : access procedure
(Item : in out Element_Type));

These procedures are better than above functions.
No copy, no dangerous.
But, we must make nested subprogram, so source code may be verbosity.

function Constant__Reference (C : Container) return
Constant_Reference_Type;
function Reference (C : Container) return Reference_Type;

These functions give same effects as Query_Element and Update_Element.
And These are simple to use.

In fact, Element, Set_Element, Query_Element and Update_Element are
able to be implemented with Reference.
The reverse is impossible.

Therefore I think Constant__Reference and Reference are more better
functions ... aside from primitive or not.
I also understand your feeling because the mechanism of accessor is
complex a little to call primitive.
But accessor is a nice idea, not kludge.



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 23:28                       ` ytomino
@ 2011-09-21  5:03                         ` AdaMagica
  2011-09-21  8:08                         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 89+ messages in thread
From: AdaMagica @ 2011-09-21  5:03 UTC (permalink / raw)


On 21 Sep., 01:28, ytomino <aghi...@gmail.com> wrote:
> (To avoid confusion, I do not use names of "Get" and "Set".)
>
> function Element (C : Container) return Element_Type;
> function Set_Element (C : Container; New_Item : Element_Type);
>
> These functions may copy Element_Type.
> It's futile cost if Element_Type'Size is large.
>
> function Element (C : Container) return access constant Element_Type;
>
> It's dangerous. the reason is written in AdaCore Gem #107.
>
> procedure Query_Element (C : Container; Process : access procedure
> (Item : in Element_Type));
> procedure Update_Element (C : Container; Process : access procedure
> (Item : in out Element_Type));
>
> These procedures are better than above functions.
> No copy, no dangerous.
> But, we must make nested subprogram, so source code may be verbosity.
>
> function Constant__Reference (C : Container) return
> Constant_Reference_Type;
> function Reference (C : Container) return Reference_Type;
>
> These functions give same effects as Query_Element and Update_Element.
> And These are simple to use.
>
> In fact, Element, Set_Element, Query_Element and Update_Element are
> able to be implemented with Reference.
> The reverse is impossible.

Nice synthesis.

> Therefore I think Constant__Reference and Reference are more better
> functions ... aside from primitive or not.
> I also understand your feeling because the mechanism of accessor is
> complex a little to call primitive.
> But accessor is a nice idea, not kludge.

And in Ada 2012, you write

type Accessor (Data: access T) is limited private
  with Implicit_Dereference => Data;

Get (P).Data.all := 42;  -- is then equivalent to
Get (P)          := 42;



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 20:19                               ` Maciej Sobczak
@ 2011-09-21  7:48                                 ` Dmitry A. Kazakov
  2011-09-21 20:51                                   ` Maciej Sobczak
  2011-09-22  2:52                                   ` Randy Brukardt
  0 siblings, 2 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-21  7:48 UTC (permalink / raw)


On Tue, 20 Sep 2011 13:19:32 -0700 (PDT), Maciej Sobczak wrote:

> On Sep 20, 6:48�pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>>> Linked list is not a container,
>>
>>> We might be using different definitions, then.
>>
>> "an object used for or capable of holding, esp for transport or storage,
>> such as a carton, box, etc."
> 
> OK, so on the computer programming discussion group you are using a
> generic definition from The Free Dictionary, which contains the
> following disclaimer at the bottom of the page:

Yes, because we are not discussing something well defined.

>> Linked list is a data structure which may serve as an implementation of a
>> container.
> 
> That depends on your definition. According to mine (cited above)
> linked list is a container.

According to mine, it is only if implements the interface of a container
object, e.g. has list-wide operations applied to the container as a whole.
(E.g. Ada.Containers.Doubly_Linked_Lists is indeed a container)

In general case lists, trees, graphs are not containers, because the
interface is ineffective to implement. This also reflects the use cases of
lists and graphs which are not used as containers are.

The point is that it is the usage and interface which tell if the thing is
a container, not its internal structure, e.g. doubly-linked elements.

>>> We have to take into account the physicality of computations, unless
>>> some completely different model is invented (and delivered).
>>
>> Yes, that is why forcing referential semantics is bad.
> 
> Nobody is forcing referential semantics, although it might be the most
> natural and efficient solution for iterators.

Of course it does, because the iterator refers to the container and to an
element in that container. Which is evidently fragile as any reference when
the container and its element mutate. It is also bad for generic
programming, because the semantics of the side-effects depends on the
implementation, i.e. the internal structure of the container.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 23:28                       ` ytomino
  2011-09-21  5:03                         ` AdaMagica
@ 2011-09-21  8:08                         ` Dmitry A. Kazakov
  2011-09-21 10:03                           ` Georg Bauhaus
  2011-09-22  3:21                           ` Randy Brukardt
  1 sibling, 2 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-21  8:08 UTC (permalink / raw)


On Tue, 20 Sep 2011 16:28:55 -0700 (PDT), ytomino wrote:

> (To avoid confusion, I do not use names of "Get" and "Set".)
> 
> function Element (C : Container) return Element_Type;
> function Set_Element (C : Container; New_Item : Element_Type);
> 
> These functions may copy Element_Type.
> It's futile cost if Element_Type'Size is large.

If you want referential semantics that must be specified explicitly. I
prefer to use containers of smart pointers for such purposes.

Otherwise, I bet that a controlled accessor object would cost a lot more
than copying for almost all elements. Controlled types are very expensive.

Quite often copying (by-value semantics) is even desired when dealing with
concurrency issues.

It was one of key advantages of Ada 83 which tried to stay reference vs.
value agnostic. It is sad to see, started with Ada 95, the drift towards
IMO wrong direction under the influence of Java et al.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 18:47           ` ytomino
@ 2011-09-21  8:16             ` Dmitry A. Kazakov
  2011-09-21  9:55               ` ytomino
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-21  8:16 UTC (permalink / raw)


On Tue, 20 Sep 2011 11:47:50 -0700 (PDT), ytomino wrote:

>> I don't know if Ada 2012 has formal generic implicit_dereference.
>> Does it?
> Yes, formal type can have  [aspect_specification].
> http://www.ada-auth.org/standards/12rm/html/RM-12-5.html

The key question is how formal aspects get matched by actual aspects,
literally or not.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21  8:16             ` Dmitry A. Kazakov
@ 2011-09-21  9:55               ` ytomino
  2011-09-22  3:26                 ` Randy Brukardt
  0 siblings, 1 reply; 89+ messages in thread
From: ytomino @ 2011-09-21  9:55 UTC (permalink / raw)


> The key question is how formal aspects get matched by actual aspects,
> literally or not.

Well. It's implementation-defined.

http://www.ada-auth.org/standards/12aarm/html/AA-13-3-1.html
-- There are no language-defined aspects that may be specified
-- on generic formals, but implementations might support some.

It's probably that formal aspect is ignored for matching, like pragma
Inline,
by my interpretation.
The right answer will be told by next version of GNAT with AdaCore's
interpretation.

(Incidentally, I hope next version compiler that will accept an
instantiated type as the type of discriminant of formal type.
Yesterday, I searched ACATS for this case, but nothing.
There was no test about this also in class-B. So it's perhaps not
explicitly disallowed in standard. In my guess, it's in the range of
the interpretation allowed the compiler, since formal discriminant had
been minor and unused until accessor appeared...)



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21  8:08                         ` Dmitry A. Kazakov
@ 2011-09-21 10:03                           ` Georg Bauhaus
  2011-09-21 10:29                             ` Dmitry A. Kazakov
  2011-09-22  3:21                           ` Randy Brukardt
  1 sibling, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-21 10:03 UTC (permalink / raw)


On 21.09.11 10:08, Dmitry A. Kazakov wrote:

> It was one of key advantages of Ada 83 which tried to stay reference vs.
> value agnostic. It is sad to see, started with Ada 95, the drift towards
> IMO wrong direction under the influence of Java et al.

Java and C# at least try to cover the difference between values
and references by providing semi-automatic switching between
the two.  Whether or not covering the difference between
values and references is better than to state it explicitly
is another question.

Why should Ada not provide for the same sugar?  There are two
answers, one positive, one negative.

There is market force of C++ and the fun of C++ and while it is
at odds with both the rationale and with the advantages
of the original ideas behind Ada 83, Ada++ allows people to feel
better with Ada when they can try to write C++ in Ada.  (See
anonymous pointers, avoiding nesting, abbrvt sntx.)

The language market is driven by attractors.

Accessors are in the class of very fashionable attractors.
Extending the notion only a little, Eiffel now has assigners.
Python has properties.  C# has Get/Set within definitions.
Objective-C introduced dot notation for property/setProperty:
methods. Etc etc.  And Ada?

Wait!  These features do not seem to attract all programmers
alike.  For example, Objective-C's dot notation is not welcome
by all Objective-C programmers.  So there is some resistance.

Ada accessors IMHO violate a specific tradition of Ada,
the language: that intentions should either be stated
explicitly, or else there should be some explicit syntax
directly related.  Now we see

  Function_Name (P) := ...;

Everything that we see in this statement, or rather that
we don't see, is an implication.

This is very popular. Intentions of the designers aside,
and instead the intentions of the programmers into focus:
Omissions allow clever, lazy programming, because it reduces
Ada's prodding you into explicitly stating your intention.
Accessors do so by covering mechanism, not showing it.
We do not even get

  Name [P] := ...;

which would at least follow the stipulated Ada tradition of
having special syntax for special mechanism!


Aspects increasingly help quickly work around language design.
It is cheap and effective, you can get short term market success,
follow each trend. They can always modestly extend SPARK if good
old Ada is needed for sanity, clarity, and honesty of expression ...



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21 10:03                           ` Georg Bauhaus
@ 2011-09-21 10:29                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-21 10:29 UTC (permalink / raw)


On Wed, 21 Sep 2011 12:03:21 +0200, Georg Bauhaus wrote:

> Accessors are in the class of very fashionable attractors.

Maybe, but that is an argument to irrationality...

> Wait!  These features do not seem to attract all programmers
> alike.  For example, Objective-C's dot notation is not welcome
> by all Objective-C programmers.  So there is some resistance.

Dot notation and accessors are different issues. I have nothing against
allowing users to use whatever sugar for the operations they define. This
by no means limits the interfaces and implementations they choose.

On the contrary to that, Accessor is a certain implementation imposed on
the programmer, there is no way no express user-defined operations of
certain kind otherwise. This is very bad.
 
> Now we see
> 
>   Function_Name (P) := ...;

I have no problem with this syntax because Ada never tried to syntactically
distinguish function calls vs objects and literals vs indexing. Which was
right.

> Accessors do so by covering mechanism, not showing it.

I don't see it this way. What I see is a certain pattern imposed on the
programmer. This pattern is an object-oriented one of worst kind of what
OOP is hated for, not without a reason.

It is amazing how Ada gathers worst patterns around all paradigms in the
reach:

1. Accessors = bad OOP
2. Conditional expressions = bad FP
3. Dynamic pre-/post-conditions = bad DbC
4. Generic container library = bad GP
...

> We do not even get
> 
>   Name [P] := ...;
> 
> which would at least follow the stipulated Ada tradition of
> having special syntax for special mechanism!

That is a discussion for another day. There nothing special in array
indexing.

> Aspects increasingly help quickly work around language design.

I would not be so sure about that.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21  7:48                                 ` Dmitry A. Kazakov
@ 2011-09-21 20:51                                   ` Maciej Sobczak
  2011-09-22  8:07                                     ` Dmitry A. Kazakov
  2011-09-22  2:52                                   ` Randy Brukardt
  1 sibling, 1 reply; 89+ messages in thread
From: Maciej Sobczak @ 2011-09-21 20:51 UTC (permalink / raw)


On Sep 21, 9:48 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > Nobody is forcing referential semantics, although it might be the most
> > natural and efficient solution for iterators.
>
> Of course it does, because the iterator refers to the container and to an
> element in that container.

Not necessarily.

Think about a map. Let's say a map with strings as keys.
We can say that strings are associated with values in the map and that
strings allow to obtain those values. But can we say that strings
refer to those elements? Or that they point to them? I don't think
most programmers would think about the role of some string in the map
this way.

So let's define the iterator as an entity that is associated with the
element in a container and that allows to obtain that element.
Depending on the capability of the iterator, it might also allow
traversal, but that does not change much.
The point is - at a high level, there is no need to think about
iterators as having any referential semantics. A pointer value is an
easy choice at the implementation level, but it does not have to be
visible at the high level.
So - no referential semantics is needed to define iterators.

> Which is evidently fragile as any reference when
> the container and its element mutate.

That is, the validity of an iterator is tied to the mutability of the
container. It is fragile in the same way as array indices, since they
become invalid when the array is reorganized.

Or database keys.

Or file names.

Or phone numbers.

> It is also bad for generic
> programming, because the semantics of the side-effects depends on the
> implementation, i.e. the internal structure of the container.

Not convincing - generics are supposed to have well defined specs. If
you worry about your side effects being bound to implementation, then
there is something wrong with your model of generics. Don't blame
iterators for this.

I consider iterators to be very useful and you have not convinced me
that they are evil.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21  7:48                                 ` Dmitry A. Kazakov
  2011-09-21 20:51                                   ` Maciej Sobczak
@ 2011-09-22  2:52                                   ` Randy Brukardt
  2011-09-22  8:11                                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 89+ messages in thread
From: Randy Brukardt @ 2011-09-22  2:52 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1tpl2pc36ptr4$.txv4v3wmkjlm.dlg@40tude.net...
...
>> Nobody is forcing referential semantics, although it might be the most
>> natural and efficient solution for iterators.
>
> Of course it does, because the iterator refers to the container and to an
> element in that container. Which is evidently fragile as any reference 
> when
> the container and its element mutate.

Fragile perhaps, but it is definitely possible to be safe (which is more 
important, IMHO). Ada.Containers are safe in this aspect, as any attempt to 
mutate the container ("tampering") is required to raise Program_Error. 
That's true as long as the iterator or reference exist. (Note that 
"tampering" only is an issue if the container is changed; it's not a problem 
for the individual element contents to be changed, which some exceptions 
having to do with discriminants or tags.)

                                          Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 12:09                 ` Dmitry A. Kazakov
  2011-09-20 12:31                   ` AdaMagica
@ 2011-09-22  3:05                   ` Randy Brukardt
  1 sibling, 0 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-22  3:05 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:pvjwyqljhfih.1d1hj4pze7bpl$.dlg@40tude.net...
...
> P.S. I also see little or no point in using "accessors". Primitive
> operations Set and Get would be as good/bad. They are also cleaner, much
> more efficient and, what is far more important, they are *primitive*.
> Accossor is a new type which means *contravariance*. The stuff is not
> composable under inheritance.

I agree with all of this except the part about "much more efficient". Since 
such routines require copying the entire element, they cannot be more 
efficient than a construct that does not require such copying. Get/Set 
(really Element/Replace_Element) are good, so long as copying the element is 
cheap or you only need to modify the entire element.

But if you have a large element where only a small part will be modified, 
Set simply isn't practical. All you can do is introduce an explicit access 
type, which is *exactly* what you don't want (because it forces the client 
to do all of the memory management).

You could of course just return a reference to the element in place instead, 
but that sacrifies all safety -- that might be OK in the C++ library, but it 
is unacceptable in Ada.

                                   Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21  8:08                         ` Dmitry A. Kazakov
  2011-09-21 10:03                           ` Georg Bauhaus
@ 2011-09-22  3:21                           ` Randy Brukardt
  1 sibling, 0 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-22  3:21 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1rffjj30r3vtr.1ahkfeok7ia0w.dlg@40tude.net...
...
> Otherwise, I bet that a controlled accessor object would cost a lot more
> than copying for almost all elements. Controlled types are very expensive.

That's a myth. It's implementation-dependent of course, but they don't need 
to cost much at all.

For Janus/Ada, they're a lot cheaper than returning an unconstrained String, 
for instance. Indeed, creating a controlled object costs three extra memory 
writes (a tag and two list entries), and finalizing it costs one dispatching 
call (which can be very cheap if the Finalize routine doesn't do anything).

The call to the "Finalize_Objects" routine is inserted pretty much 
everywhere whether or not you use controlled types yourself, since Janus/Ada 
uses the same mechanisms for most tasking and memory management activities. 
And it is very cheap if there is nothing to do, as it is parameterless and 
consists of a single pointer compare in that case.

The only legitimate complaint about finalization is the extra space needed 
for small objects, but even that isn't really that much.

So the marginal runtime overhead for a controlled object is three memory 
writes on initialize, two on finalize, plus a dispatching call. This doesn't 
come close to "very expensive"; it's far less than the heap allocation 
needed to return an unconstrained string, for instance.

And it should be noted that for limited controlled types in particular 
(which this is), you could do far better, generating the needed dispatching 
call directly in-line. (I know some AdaCore people were thinking about such 
an implementation in GNAT, I don't know if they ever implemented that.)

                                                         Randy.







^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21  9:55               ` ytomino
@ 2011-09-22  3:26                 ` Randy Brukardt
  0 siblings, 0 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-22  3:26 UTC (permalink / raw)


"ytomino" <aghia05@gmail.com> wrote in message 
news:f5f7af9e-0740-4466-b008-884c65f0e34e@fi7g2000vbb.googlegroups.com...
...
> (Incidentally, I hope next version compiler that will accept an
> instantiated type as the type of discriminant of formal type.
> Yesterday, I searched ACATS for this case, but nothing.
> There was no test about this also in class-B. So it's perhaps not
> explicitly disallowed in standard. In my guess, it's in the range of
> the interpretation allowed the compiler, since formal discriminant had
> been minor and unused until accessor appeared...)

To give you a useless answer, I'm not sure whether your program is legal or 
not. It *ought* to be legal, but that is a different question! I don't have 
time to research it right now, so it probably would be a reasonable idea to 
submit your example program to Ada-Comment and let the assembled experts 
decide whether or not it ought to work. And if not, then we can open an AI 
to fix the language (post-Ada 2012).

                                    Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-20 21:39           ` ytomino
@ 2011-09-22  3:32             ` Randy Brukardt
  0 siblings, 0 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-22  3:32 UTC (permalink / raw)


"ytomino" <aghia05@gmail.com> wrote in message 
news:ad6f00e2-cc67-4fa3-8268-7247ebed94b0@d14g2000yqb.googlegroups.com...
> Thank you for your suggestion. I'm reading AARM now...
>
> For the first time, I got to know the difference between "access
> discriminant" and a normal discriminant having named access type.
> I am surprised at that a normal discriminant having named access type
> can have default and is able to assignment.
> But, in RM 4.1 (5 (2/3)), "This aspect is specified by a name that
> denotes an access discriminant declared for the type T."...It seems
> that a normal discriminant having named access type can not be
> Implicit_Dereferene...
> Close! It's regrettable.
>
> Back to the subject, lifetime of coextension, It's interesting.
> Coextension probably is one of the reason that objects with access
> discriminant can never allow them to be changed.
> However, I have not resulted in firm belief yet.
>
> As another reason, default of "access discriminant" has been used for
> discriminating which a formal limited type in generic is
> really(immutably) limited or non-limited since Ada 95.
> "immutably limited" concept is used widely. (Therefore it is hard to
> change this rule.)
>
> Is my understanding right...?

Seems OK as far as it goes. But you have to bring accessibility into it (and 
the desire and in fact necessity of not having a separate accessibility 
level for an access discriminant).

Note that the accessibility of a discriminant of a named access type is that 
of the named access type, while that of an anonymous access discriminant is 
that of the enclosing object. A big difference, and it is what we need for 
safe accessors. An accessor of a discriminant of a named access type would 
make is easy to create dangling pointers (as mentioned in the GEM), and that 
would be bad. Thus no implicit dereference there.
>
> I have not been found the reason about accessibility check yet.
> I'm going to read RM 3.10.2 and AI95-00230-01 at next.

You're a glutton for punishment! :-)

If you figure it out, including all of the corner cases, please come to the 
ARG meetings and explain it to us. ;-) [I'm certain that it is still wrong 
in various ways.]

                       Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-21 20:51                                   ` Maciej Sobczak
@ 2011-09-22  8:07                                     ` Dmitry A. Kazakov
  2011-09-22 20:57                                       ` Maciej Sobczak
                                                         ` (2 more replies)
  0 siblings, 3 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-22  8:07 UTC (permalink / raw)


On Wed, 21 Sep 2011 13:51:43 -0700 (PDT), Maciej Sobczak wrote:

> On Sep 21, 9:48�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>> Nobody is forcing referential semantics, although it might be the most
>>> natural and efficient solution for iterators.
>>
>> Of course it does, because the iterator refers to the container and to an
>> element in that container.
> 
> Not necessarily.
> 
> Think about a map. Let's say a map with strings as keys.
> We can say that strings are associated with values in the map and that
> strings allow to obtain those values. But can we say that strings
> refer to those elements?

Strings alone do not. In a combination with a reference to the map, that
new object does.

> So let's define the iterator as an entity that is associated with the
> element in a container and that allows to obtain that element.

String is not an iterator according to this definition. It is also not an
index (with operations Succ, Pred, or that I in A and J in A => I+J/2 in
A).

For generic programming the properties of the index, key, iterator must be
stated.

> So - no referential semantics is needed to define iterators.

The validity of an iterator does not depend (pretends to) on other objects
(unconditional). The validity of an index is conditional to the object the
index is being applied.

This is the semantic difference between them from which the usage and other
issues like types relationships follow.

>> Which is evidently fragile as any reference when
>> the container and its element mutate.
> 
> That is, the validity of an iterator is tied to the mutability of the
> container. It is fragile in the same way as array indices, since they
> become invalid when the array is reorganized.

An index is neither valid nor invalid without a context. When index and
container are combined into an iterator bound to certain element of the
container (whereas the element's identity definition is a separate issue,
let's for a while consider that there is a way to identify the element),
then that reference might become invalid.

The point is, when you use index as an iterator you get all problems of the
latter.

Indices are *assumed* to change when the container mutates.

>> It is also bad for generic
>> programming, because the semantics of the side-effects depends on the
>> implementation, i.e. the internal structure of the container.
> 
> Not convincing - generics are supposed to have well defined specs.

I meant rather generic programming = programming in terms of sets of types.

> If
> you worry about your side effects being bound to implementation, then
> there is something wrong with your model of generics. Don't blame
> iterators for this.

I blame them because these differences, essential to container usage,
cannot be promoted at the interface level. Consider a generic
implementation of removing all elements of the container using iterators:

   This := Container.First;
   while This /= Null_Iterator loop
       Next := This.Next;
       This.Delete;
       This := Next;
   end loop;

This may work or not depending on the semantics of Delete. E.g. for a
circular list, it will loop forever.

Note that referential semantics has its place. My concern is its overuse
for things which don't require it, or even cannot provide it, e.g. arrays.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-22  2:52                                   ` Randy Brukardt
@ 2011-09-22  8:11                                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-22  8:11 UTC (permalink / raw)


On Wed, 21 Sep 2011 21:52:47 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1tpl2pc36ptr4$.txv4v3wmkjlm.dlg@40tude.net...
> ...
>>> Nobody is forcing referential semantics, although it might be the most
>>> natural and efficient solution for iterators.
>>
>> Of course it does, because the iterator refers to the container and to an
>> element in that container. Which is evidently fragile as any reference 
>> when the container and its element mutate.
> 
> Fragile perhaps, but it is definitely possible to be safe (which is more 
> important, IMHO). Ada.Containers are safe in this aspect, as any attempt to 
> mutate the container ("tampering") is required to raise Program_Error. 

Well, but iterators are especially interesting for mutating container due
to their referential semantics. Killing that also does one of key
advantages they, as pointers, have.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-22  8:07                                     ` Dmitry A. Kazakov
@ 2011-09-22 20:57                                       ` Maciej Sobczak
  2011-09-23  7:59                                         ` Dmitry A. Kazakov
  2011-09-23  9:23                                       ` Stephen Leake
  2011-09-24 12:54                                       ` Simon Wright
  2 siblings, 1 reply; 89+ messages in thread
From: Maciej Sobczak @ 2011-09-22 20:57 UTC (permalink / raw)


On Sep 22, 10:07 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> Consider a generic
> implementation of removing all elements of the container using iterators:
>
>    This := Container.First;
>    while This /= Null_Iterator loop
>        Next := This.Next;
>        This.Delete;
>        This := Next;
>    end loop;
>
> This may work or not depending on the semantics of Delete. E.g. for a
> circular list, it will loop forever.

Not convincing, for several reasons:

1. Null_Iterator as a sentinel value is not necessary, you might use
Container.Is_Empty instead.

2. Even with the above structure, This := This.Delete_And_Move_To_Next
would do the trick. It would also work for vectors.

3. You don't have to include circular lists in the same set of types
as other linear containers in the first place, so there would be no
temptation to use the generic algorithm with inappropriate container.
That is, a circular list probably deserves a different interface
anyway.

4. Are you sure that the circularity is a property of the container?
Or rather of the traversal? Do you know that I can write a circular
iterator as a wrapper for a "normal" one, for any linear container?
Will you insist on having a completely separate container type for
backwards/randomized/etc. iteration as well?

So you are blaming iterators for having badly designed generic
container interface in the first place. Not convincing.

> Note that referential semantics has its place. My concern is its overuse
> for things which don't require it,

I agree here. But we still don't know whether iterators are bad.
Because if they are good, then their referential semantics (if any)
should be... forgiven?

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-22 20:57                                       ` Maciej Sobczak
@ 2011-09-23  7:59                                         ` Dmitry A. Kazakov
  2011-09-23 10:57                                           ` Georg Bauhaus
                                                             ` (2 more replies)
  0 siblings, 3 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-23  7:59 UTC (permalink / raw)


On Thu, 22 Sep 2011 13:57:51 -0700 (PDT), Maciej Sobczak wrote:

> On Sep 22, 10:07�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> Consider a generic
>> implementation of removing all elements of the container using iterators:
>>
>> � �This := Container.First;
>> � �while This /= Null_Iterator loop
>> � � � �Next := This.Next;
>> � � � �This.Delete;
>> � � � �This := Next;
>> � �end loop;
>>
>> This may work or not depending on the semantics of Delete. E.g. for a
>> circular list, it will loop forever.
> 
> Not convincing, for several reasons:
> 
> 1. Null_Iterator as a sentinel value is not necessary, you might use
> Container.Is_Empty instead.

Is_Empty is a container-wide operation. X = Null_Iterator is an iterator
operation, same is X.Is_In. Aren't you a proponent of iterator approach?

> 2. Even with the above structure, This := This.Delete_And_Move_To_Next
> would do the trick. It would also work for vectors.

What about This.Delete? Should it be removed from the interface?

The problem here is the semantics of existing iterators upon container
manipulation, not computability of the algorithm. Iterators as pointers
have issues that operations on other pointers influence pointers apparently
not involved in the operation, while the implied contract of an iterator is
that it points its element no matter what.

Can I declare an iterator object constant? What is the meaning of its
"constantness" when the container gets manipulated? See a huge language
problem here? An iterator can be immutable only if the container is. How do
I express such stuff in the language?

> 3. You don't have to include circular lists in the same set of types
> as other linear containers in the first place, so there would be no
> temptation to use the generic algorithm with inappropriate container.
> That is, a circular list probably deserves a different interface
> anyway.

Circular lists are the most important ones among doubly-linked lists, and
are especially interesting for iterator-based approaches, because insertion
and removal in such lists can be done without knowing the list's head.

> 4. Are you sure that the circularity is a property of the container?

And being doubly linked is? That is the whole point, list of whatever
structure is not yet a container.

> Or rather of the traversal? Do you know that I can write a circular
> iterator as a wrapper for a "normal" one, for any linear container?
> Will you insist on having a completely separate container type for
> backwards/randomized/etc. iteration as well?

Now you are closer to understanding my point that list is not a container
and the interface of container is not necessarily its implementation.

> So you are blaming iterators for having badly designed generic
> container interface in the first place. Not convincing.

There are more comfortable and safe interfaces than iterators, I want them
available first. I want the language supporting implementation of such
interfaces rather than mounting kludges on kludges like accessors, limited
returns etc.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-22  8:07                                     ` Dmitry A. Kazakov
  2011-09-22 20:57                                       ` Maciej Sobczak
@ 2011-09-23  9:23                                       ` Stephen Leake
  2011-09-23  9:48                                         ` Dmitry A. Kazakov
  2011-09-24 12:54                                       ` Simon Wright
  2 siblings, 1 reply; 89+ messages in thread
From: Stephen Leake @ 2011-09-23  9:23 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Consider a generic
> implementation of removing all elements of the container using iterators:
>
>    This := Container.First;
>    while This /= Null_Iterator loop
>        Next := This.Next;
>        This.Delete;
>        This := Next;
>    end loop;
>
> This may work or not depending on the semantics of Delete. E.g. for a
> circular list, it will loop forever.

No, it will produce an invalid dereference; for a one element circular
list, This.Next = This, so Next is invalid after This.Delete.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23  9:23                                       ` Stephen Leake
@ 2011-09-23  9:48                                         ` Dmitry A. Kazakov
  2011-09-23 22:42                                           ` Randy Brukardt
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-23  9:48 UTC (permalink / raw)


On Fri, 23 Sep 2011 05:23:38 -0400, Stephen Leake wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> Consider a generic
>> implementation of removing all elements of the container using iterators:
>>
>>    This := Container.First;
>>    while This /= Null_Iterator loop
>>        Next := This.Next;
>>        This.Delete;
>>        This := Next;
>>    end loop;
>>
>> This may work or not depending on the semantics of Delete. E.g. for a
>> circular list, it will loop forever.
> 
> No, it will produce an invalid dereference; for a one element circular
> list, This.Next = This, so Next is invalid after This.Delete.

If the element is only in this list and freed upon delete, then Next is
dangling.

However a common schema is that elements of lists are actually never freed,
but rather moved to the list of unused element to reuse, when a new element
is needed. For this implementation the above loops.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23  7:59                                         ` Dmitry A. Kazakov
@ 2011-09-23 10:57                                           ` Georg Bauhaus
  2011-09-23 22:30                                           ` Randy Brukardt
  2011-09-23 22:50                                           ` Randy Brukardt
  2 siblings, 0 replies; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-23 10:57 UTC (permalink / raw)


On 23.09.11 09:59, Dmitry A. Kazakov wrote:

> Can I declare an iterator object constant? What is the meaning of its
> "constantness" when the container gets manipulated? See a huge language
> problem here? An iterator can be immutable only if the container is. How do
> I express such stuff in the language?

Well, have one more level of indirection, and one aspect (i.e., only
two more kludges ;-)  Not sure whether the aspect can be checked at
compile time, though, or to what extent.

Compiling: const.adb (source file time stamp: 2011-09-23 10:27:42)

     1. with Ada.Containers.Vectors;
     2.
     3. procedure Const is
     4.
     5.    type E is (Mon, Bin, Ter);
     6.    subtype P is Positive range 1 .. 100;
     7.
     8.    package Vec is new Ada.Containers.Vectors
     9.      (Element_Type => E,
    10.       Index_Type => P);
    11.
    12.    type Const_Vector is access constant Vec.Vector;
    13.    type Const_Cursor is new Vec.Cursor
    14.      with Invariant => Has_Element (Const_Cursor);
    15.
    16.    procedure Change (Element : in out E) is
    17.    begin
    18.       if Element = E'Last then
    19. 	 Element := E'First;
    20.       else
    21. 	 Element := E'Succ (Element);
    22.       end if;
    23.    end Change;
    24.
    25.    function Frozen (V : Vec.Vector) return Const_Vector is
    26.    begin
    27.       return V'Unchecked_Access;
    28.    end Frozen;
    29.
    30.    Container : Vec.Vector;
    31.    Position  : Vec.Cursor;
    32.    Const_Container : Const_Vector;
    33. begin
    34.    Container.Append(Mon);
    35.    Container.Append(Ter);
    36.    Position := Container.First;
    37.    Vec.Update_Element (Container,
    38. 		       Position,
    39. 		       Process => Change'Access);
    40.    Const_Container := Frozen (Container);
    41.    Vec.Update_Element (Const_Container.all,
                                               |
        >>> actual for "Container" must be a variable

    42. 		       Position,
    43. 		       Process => Change'Access);
    44.
    45. end Const;
    46.
    47.
    48.

 48 lines: 1 error
gnatmake: "const.adb" compilation error

Compilation exited abnormally with code 4 at Fri Sep 23 10:27:53



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23  7:59                                         ` Dmitry A. Kazakov
  2011-09-23 10:57                                           ` Georg Bauhaus
@ 2011-09-23 22:30                                           ` Randy Brukardt
  2011-09-23 22:50                                           ` Randy Brukardt
  2 siblings, 0 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-23 22:30 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:fsmyepvncyb2$.2ik4vw3vu74h.dlg@40tude.net...
...
>> 2. Even with the above structure, This := This.Delete_And_Move_To_Next
>> would do the trick. It would also work for vectors.
>
> What about This.Delete? Should it be removed from the interface?

It should raise an exception, of course. That's what Ada.Containers does, 
and it's the obvious solution. Compile-time checking is incompatible with 
any sort of library, and that's surely the case here. It's crazy to try to 
do everything at compile-time.

(Of course, I'm on record as saying that many OOP designers are insane, so 
draw your own conclusions as to who is insane... :-)

                                    Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23  9:48                                         ` Dmitry A. Kazakov
@ 2011-09-23 22:42                                           ` Randy Brukardt
  2011-09-24  6:56                                             ` Dmitry A. Kazakov
  2011-09-24 10:47                                             ` Stephen Leake
  0 siblings, 2 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-23 22:42 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:xumuqaannoov$.18le1ojsi30l8.dlg@40tude.net...
> On Fri, 23 Sep 2011 05:23:38 -0400, Stephen Leake wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> Consider a generic
>>> implementation of removing all elements of the container using 
>>> iterators:
>>>
>>>    This := Container.First;
>>>    while This /= Null_Iterator loop
>>>        Next := This.Next;
>>>        This.Delete;
>>>        This := Next;
>>>    end loop;
>>>
>>> This may work or not depending on the semantics of Delete. E.g. for a
>>> circular list, it will loop forever.
>>
>> No, it will produce an invalid dereference; for a one element circular
>> list, This.Next = This, so Next is invalid after This.Delete.
>
> If the element is only in this list and freed upon delete, then Next is
> dangling.
>
> However a common schema is that elements of lists are actually never 
> freed,
> but rather moved to the list of unused element to reuse, when a new 
> element
> is needed. For this implementation the above loops.

In that case, the implementation of cursors is broken (IMHO) - dangling 
cursor detection should have been manditory, and surely should be in the 
case of element reuse. So Program_Error should be raised in either case, 
nothing erroneous or looping here.

[Note that we are talking about containers, so I'm assuming that these 
things are cursors. If you are using raw access types in the user interface 
of any sort of container, you are living in the 1990s and are purposely 
destroying all of the real advantages of container usage.]

                                   Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23  7:59                                         ` Dmitry A. Kazakov
  2011-09-23 10:57                                           ` Georg Bauhaus
  2011-09-23 22:30                                           ` Randy Brukardt
@ 2011-09-23 22:50                                           ` Randy Brukardt
  2011-09-24  6:46                                             ` Dmitry A. Kazakov
  2 siblings, 1 reply; 89+ messages in thread
From: Randy Brukardt @ 2011-09-23 22:50 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:fsmyepvncyb2$.2ik4vw3vu74h.dlg@40tude.net...
...
>> So you are blaming iterators for having badly designed generic
>> container interface in the first place. Not convincing.
>
> There are more comfortable and safe interfaces than iterators, I want them
> available first. I want the language supporting implementation of such
> interfaces rather than mounting kludges on kludges like accessors, limited
> returns etc.

You seem to want to totally avoid the purpose of containers, which is to 
eliminate unsafe memory management and pointer usage. The whole point of 
accessors and the like is to provide SAFE referential access to container 
elements (as well as anything else). Ada access types or anything like them 
can never be safe, so we need an abstraction to layer on top to provide that 
safety.

The problem that comes about the accessors is that most ways to provide safe 
referential access don't really work -- they just push the problem somewhere 
else (moving the access type to a function result, for instance). The win 
with the accessors in Ada 2012 is that they actually succeed in making the 
result safe (in the absence of unchecked programming, of course). There is 
no other way to do that using Ada semantics - at least that we could find 
(see the many other attempts as this in the Ada 2005 AIs -- several are 
documented in the alternatives to AI05-0142).

Your interface ideas probably would make sense in a totally new language, 
but would be totally unimplementable in Ada (we'd have to get rid of at 
least discriminants, subtypes, general access types, and generics to have 
any chance to make them work). Please give them a rest and return to the 
real world.

                                            Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23 22:50                                           ` Randy Brukardt
@ 2011-09-24  6:46                                             ` Dmitry A. Kazakov
  2011-09-26 22:48                                               ` Randy Brukardt
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-24  6:46 UTC (permalink / raw)


On Fri, 23 Sep 2011 17:50:57 -0500, Randy Brukardt wrote:

> You seem to want to totally avoid the purpose of containers, which is to 
> eliminate unsafe memory management and pointer usage.

I thought that the purpose is organizing data in a structured way.

> Your interface ideas probably would make sense in a totally new language, 
> but would be totally unimplementable in Ada (we'd have to get rid of at 
> least discriminants, subtypes, general access types, and generics to have 
> any chance to make them work).

Reworking Ada's type system was never seriously considered since Ada 95
design.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23 22:42                                           ` Randy Brukardt
@ 2011-09-24  6:56                                             ` Dmitry A. Kazakov
  2011-09-26 22:43                                               ` Randy Brukardt
  2011-09-24 10:47                                             ` Stephen Leake
  1 sibling, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-24  6:56 UTC (permalink / raw)


On Fri, 23 Sep 2011 17:42:39 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:xumuqaannoov$.18le1ojsi30l8.dlg@40tude.net...
>> On Fri, 23 Sep 2011 05:23:38 -0400, Stephen Leake wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> Consider a generic
>>>> implementation of removing all elements of the container using 
>>>> iterators:
>>>>
>>>>    This := Container.First;
>>>>    while This /= Null_Iterator loop
>>>>        Next := This.Next;
>>>>        This.Delete;
>>>>        This := Next;
>>>>    end loop;
>>>>
>>>> This may work or not depending on the semantics of Delete. E.g. for a
>>>> circular list, it will loop forever.
>>>
>>> No, it will produce an invalid dereference; for a one element circular
>>> list, This.Next = This, so Next is invalid after This.Delete.
>>
>> If the element is only in this list and freed upon delete, then Next is
>> dangling.
>>
>> However a common schema is that elements of lists are actually never freed,
>> but rather moved to the list of unused element to reuse, when a new element
>> is needed. For this implementation the above loops.
> 
> In that case, the implementation of cursors is broken (IMHO) - dangling 
> cursor detection should have been manditory, and surely should be in the 
> case of element reuse. So Program_Error should be raised in either case, 
> nothing erroneous or looping here.

Which does not invalidate my point about difficulties of generic
programming with iterators, because the semantics of operations on
iterators is ill defined. Whether accessing the iterator Next raised
Program_Error or looped is no matter, so long it applies to a concrete
container implementation.

For generic programming you need Delete working in the same (specified) way
for all container types of the set. Its effect on all iterators must be
defined and same. My point and the purpose of the example was that this is
extremely difficult to achieve, if possible.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-23 22:42                                           ` Randy Brukardt
  2011-09-24  6:56                                             ` Dmitry A. Kazakov
@ 2011-09-24 10:47                                             ` Stephen Leake
  1 sibling, 0 replies; 89+ messages in thread
From: Stephen Leake @ 2011-09-24 10:47 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:xumuqaannoov$.18le1ojsi30l8.dlg@40tude.net...
>> On Fri, 23 Sep 2011 05:23:38 -0400, Stephen Leake wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> Consider a generic
>>>> implementation of removing all elements of the container using 
>>>> iterators:
>>>>
>>>>    This := Container.First;
>>>>    while This /= Null_Iterator loop
>>>>        Next := This.Next;
>>>>        This.Delete;
>>>>        This := Next;
>>>>    end loop;
>>>>
>>>> This may work or not depending on the semantics of Delete. E.g. for a
>>>> circular list, it will loop forever.
>>>
>>> No, it will produce an invalid dereference; for a one element circular
>>> list, This.Next = This, so Next is invalid after This.Delete.
>>
>> If the element is only in this list and freed upon delete, then Next is
>> dangling.
>>
>> However a common schema is that elements of lists are actually never 
>> freed,
>> but rather moved to the list of unused element to reuse, when a new 
>> element
>> is needed. For this implementation the above loops.
>
> In that case, the implementation of cursors is broken (IMHO) - dangling 
> cursor detection should have been manditory, and surely should be in the 
> case of element reuse. So Program_Error should be raised in either case, 
> nothing erroneous or looping here.
>
> [Note that we are talking about containers, so I'm assuming that these 
> things are cursors. If you are using raw access types in the user interface 
> of any sort of container, you are living in the 1990s and are purposely 
> destroying all of the real advantages of container usage.]

+1

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-22  8:07                                     ` Dmitry A. Kazakov
  2011-09-22 20:57                                       ` Maciej Sobczak
  2011-09-23  9:23                                       ` Stephen Leake
@ 2011-09-24 12:54                                       ` Simon Wright
  2011-09-24 14:46                                         ` Dmitry A. Kazakov
  2 siblings, 1 reply; 89+ messages in thread
From: Simon Wright @ 2011-09-24 12:54 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Consider a generic implementation of removing all elements of the
> container using iterators:
>
>    This := Container.First;
>    while This /= Null_Iterator loop
>        Next := This.Next;
>        This.Delete;
>        This := Next;
>    end loop;
>
> This may work or not depending on the semantics of Delete. E.g. for a
> circular list, it will loop forever.

I'm not sure whether to be amused by the fact that for
BC.Containers.Rings (which are logically circular), which offer

   procedure Delete_Item_At (It : in out Ring_Iterator);

you would get an exception Not_Yet_Implemented :-)

Clearly no one has encountered this in practice; I don't feel especially
motivated to fix it (mainly because a Ring has the concept of Top and
Mark, and I don't have an intuitive grasp of what should happen to Top
or Mark if either happens to be the one that's deleted!)

This particular Container seems to me to be a prime example of adding a
feature to a library for theoretical reasons rather than because someone
has a reasonable need for it and therefore a use case. My own use of the
BC containers has involved Collections (like Vectors) (plain and
ordered), Maps, Queues (plain and ordered), Sets and on one occasion
Bags; no Deques, Rings, Stacks, Graphs, Trees of any flavour ...



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-24 12:54                                       ` Simon Wright
@ 2011-09-24 14:46                                         ` Dmitry A. Kazakov
  2011-09-24 16:21                                           ` Simon Wright
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-24 14:46 UTC (permalink / raw)


On Sat, 24 Sep 2011 13:54:26 +0100, Simon Wright wrote:

> My own use of the
> BC containers has involved Collections (like Vectors) (plain and
> ordered), Maps, Queues (plain and ordered), Sets and on one occasion
> Bags; no Deques, Rings, Stacks, Graphs, Trees of any flavour ...

More complex structures than maps require more efforts before get adapted
to the task. So much, that is easier to design them from scratch each time.
Should I explain why?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-24 14:46                                         ` Dmitry A. Kazakov
@ 2011-09-24 16:21                                           ` Simon Wright
  2011-09-24 16:43                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Simon Wright @ 2011-09-24 16:21 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Sat, 24 Sep 2011 13:54:26 +0100, Simon Wright wrote:
>
>> My own use of the
>> BC containers has involved Collections (like Vectors) (plain and
>> ordered), Maps, Queues (plain and ordered), Sets and on one occasion
>> Bags; no Deques, Rings, Stacks, Graphs, Trees of any flavour ...
>
> More complex structures than maps require more efforts before get
> adapted to the task. So much, that is easier to design them from
> scratch each time.  Should I explain why?

I don't think you need bother!



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-24 16:21                                           ` Simon Wright
@ 2011-09-24 16:43                                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-24 16:43 UTC (permalink / raw)


On Sat, 24 Sep 2011 17:21:05 +0100, Simon Wright wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Sat, 24 Sep 2011 13:54:26 +0100, Simon Wright wrote:
>>
>>> My own use of the
>>> BC containers has involved Collections (like Vectors) (plain and
>>> ordered), Maps, Queues (plain and ordered), Sets and on one occasion
>>> Bags; no Deques, Rings, Stacks, Graphs, Trees of any flavour ...
>>
>> More complex structures than maps require more efforts before get
>> adapted to the task. So much, that is easier to design them from
>> scratch each time.  Should I explain why?
> 
> I don't think you need bother!

Should it remain this way?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-24  6:56                                             ` Dmitry A. Kazakov
@ 2011-09-26 22:43                                               ` Randy Brukardt
  0 siblings, 0 replies; 89+ messages in thread
From: Randy Brukardt @ 2011-09-26 22:43 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:19iim6m72b6s4$.qe1pwkufdkzn$.dlg@40tude.net...
...
> For generic programming you need Delete working in the same (specified) 
> way
> for all container types of the set. Its effect on all iterators must be
> defined and same. My point and the purpose of the example was that this is
> extremely difficult to achieve, if possible.

Humm, I wouldn't find that difficult to achieve at all. Surely if you are 
using Ada.Containers, Delete works the same way in all of them. Similarly, 
if you are building containers that are intentionally similar to 
Ada.Containers, you again will have the same effects.

I realize that there is a very wide universe of container designs out there. 
A large part of the point of Ada.Containers was to select one and 
standardize on it -- since many of the choices are essentially equivalent, 
choosing a single solution was pretty much the only way to get some leverage 
on container libraries.

So, for the vast majority of uses, Ada.Containers and extensions of it will 
be sufficient, and for those iterator semantics is well-defined. If you 
build you own iterators away from the Ada.Container model, you'll have to 
define your own semantics for things like Delete -- but one presumes that 
you have a good reason for doing that, so it should be worth the effort.

                                 Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-24  6:46                                             ` Dmitry A. Kazakov
@ 2011-09-26 22:48                                               ` Randy Brukardt
  2011-09-27  8:10                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Randy Brukardt @ 2011-09-26 22:48 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:muk0d5mdqzpv.tnxjyzn8jw6k$.dlg@40tude.net...
> On Fri, 23 Sep 2011 17:50:57 -0500, Randy Brukardt wrote:
>
>> You seem to want to totally avoid the purpose of containers, which is to
>> eliminate unsafe memory management and pointer usage.
>
> I thought that the purpose is organizing data in a structured way.


>> Your interface ideas probably would make sense in a totally new language,
>> but would be totally unimplementable in Ada (we'd have to get rid of at
>> least discriminants, subtypes, general access types, and generics to have
>> any chance to make them work).
>
> Reworking Ada's type system was never seriously considered since Ada 95
> design.

It's insufficiently broken, as any such change is going to be incompatible. 
(At this point, almost every change we consider is incompatible in some 
way -- even trivial changes like obsolescing old pragmas like Inline turned 
out to be incompatible in programs that used certain restrictions.) That's 
what I meant about the "real world"; future Ada versions cannot be 
significantly incompatible with the existing ones, and even mild 
incompatibilities need a significant benefit.

                                Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-26 22:48                                               ` Randy Brukardt
@ 2011-09-27  8:10                                                 ` Dmitry A. Kazakov
  2011-09-27 10:18                                                   ` Georg Bauhaus
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-27  8:10 UTC (permalink / raw)


On Mon, 26 Sep 2011 17:48:56 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:muk0d5mdqzpv.tnxjyzn8jw6k$.dlg@40tude.net...

>> Reworking Ada's type system was never seriously considered since Ada 95
>> design.
> 
> It's insufficiently broken, as any such change is going to be incompatible.

It would, if changes are small. It is like in mathematics, when looking for
an optimum you could not climb out of the local hollow by small steps.

Consider a type system where your precious kludges of old Ada would become
some type expressions and library implementations rather than built-in
stuff.

Ada does not need changes, it needs a generalization of its type system
accumulating things we learned about types in the recent 15+ years.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27  8:10                                                 ` Dmitry A. Kazakov
@ 2011-09-27 10:18                                                   ` Georg Bauhaus
  2011-09-27 12:14                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-27 10:18 UTC (permalink / raw)


On 27.09.11 10:10, Dmitry A. Kazakov wrote:

> Consider a type system where your precious kludges of old Ada would become
> some type expressions and library implementations rather than built-in
> stuff.

In the opposite direction, an alternative effort would set out
to find language for the field tested patterns hidden in libraries.
Of course, such language  would be made for normal programmers,
not for compiler professionals who have reason to tweak patterns.




^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27 10:18                                                   ` Georg Bauhaus
@ 2011-09-27 12:14                                                     ` Dmitry A. Kazakov
  2011-09-27 15:11                                                       ` Georg Bauhaus
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-27 12:14 UTC (permalink / raw)


On Tue, 27 Sep 2011 12:18:28 +0200, Georg Bauhaus wrote:

> On 27.09.11 10:10, Dmitry A. Kazakov wrote:
> 
>> Consider a type system where your precious kludges of old Ada would become
>> some type expressions and library implementations rather than built-in
>> stuff.
> 
> In the opposite direction, an alternative effort would set out
> to find language for the field tested patterns hidden in libraries.

No the opposite direction is to have built-in "patterns". In order to have
library-provided "patterns", they must be expressible in terms of other,
more fundamental, "patterns".

It is also interesting how non-implemented "patterns", and as I understand,
your desire is to keep them such, could be tested in the field, before
being incorporated into the language core? Was for example limited type
return tested in the field? Accessibility rules? Anonymous access types?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27 12:14                                                     ` Dmitry A. Kazakov
@ 2011-09-27 15:11                                                       ` Georg Bauhaus
  2011-09-27 15:38                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-27 15:11 UTC (permalink / raw)


On 27.09.11 14:14, Dmitry A. Kazakov wrote:
> On Tue, 27 Sep 2011 12:18:28 +0200, Georg Bauhaus wrote:
> 
>> On 27.09.11 10:10, Dmitry A. Kazakov wrote:
>>
>>> Consider a type system where your precious kludges of old Ada would become
>>> some type expressions and library implementations rather than built-in
>>> stuff.
>>
>> In the opposite direction, an alternative effort would set out
>> to find language for the field tested patterns hidden in libraries.
> 
> No the opposite direction is to have built-in "patterns". 

That's what I meant to say; to design some language for those "patterns"
being now "emulated" in libraries seems harder.  Harder because you need
to decide that (1) This is it! and (2) Though shalt not be a language
designer, but a programmer.  Even when you write reusable libraries.
These built-ins might be harder for compiler makers to implement, IIUC.

A use case:

  "Run these independent procedures concurrently.  They share
   one variable."

With a normal, practical programmer in mind, a typical "pattern"
of language extension into the domain of concurrency is to enable
writing, in pseudo code:

   concurrent procedure one (a, b: input; c: out output) is
   begin
      ...
      lock shared.do(b, 42) end lock;
      ...
   end;

This reuses the notion of "procedure", the word "concurrent" being a hint,
the lock being automatic; critical region isolated, perfectly easy!
(If lousy, but quality issues needs to be addressed with care.)
Now in Ada, they tell you to write a task,

   task one is
   begin
     ...

(interrupting) "Where do I put a, b, and c?"  "In entries, moment please!"
... "Oh, gosh, more mechanism, why can't it be easy?"  "OK, wait:

   task worker is
   begin
     one (a, b, c);
   end;

Does this look easy?" "OK, where do a, b, c come from?"  "You make
them visible, the task could be local :

   procedure one
       (a, b: input;
        c: output)
   is
       task worker is
       begin
           ...
       end;
   begin
       null;
   end;"

"OK (boring, verbose, so many ways), how about the shared variable?"
"Just define a protected object."  "What?"

... etc

The increasingly annoyed questioner might be right or wrong
from a software engineering point of view, the language design
will have to address his concerns or else he does not buy.

A library, or a pattern, might seem to help:

  task type Run_Once
    (job : access procedure (a, b: input; c : out output))
  is
     pragma Storage_Size (N);
  end Run_Once;

But when is `c` filled?  So you end up explaining tasks
and protected objects anyway.  And you might be able to explain
why seemingly advantageous "primitives" like "concurrent" and
"lock" had been preferred to a library based approach.


> It is also interesting how non-implemented "patterns", and as I understand,
> your desire is to keep them such, could be tested in the field, before
> being incorporated into the language core? Was for example limited type
> return tested in the field? Accessibility rules? Anonymous access types?

At Ada-auth, they usually say something about customer response to
implementation defined pragmas and such. I should hope that new
languages are made the way that matches the way a certain requirements
document was made, reviewed, parts dismissed, reviewed again, compared,
etc.




^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27 15:11                                                       ` Georg Bauhaus
@ 2011-09-27 15:38                                                         ` Dmitry A. Kazakov
  2011-09-27 18:06                                                           ` Georg Bauhaus
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-27 15:38 UTC (permalink / raw)


On Tue, 27 Sep 2011 17:11:03 +0200, Georg Bauhaus wrote:

> On 27.09.11 14:14, Dmitry A. Kazakov wrote:
>> On Tue, 27 Sep 2011 12:18:28 +0200, Georg Bauhaus wrote:
>> 
[...]
>  So you end up explaining tasks
> and protected objects anyway.  And you might be able to explain
> why seemingly advantageous "primitives" like "concurrent" and
> "lock" had been preferred to a library based approach.

As another example take elliptic integral of the first kind: F(x,k). Why
bother to with subprograms, accuracy of real types, real types themselves,
approximation techniques for such a simple thing?

The answer to your question was given by Occam 700 years ago.

>> It is also interesting how non-implemented "patterns", and as I understand,
>> your desire is to keep them such, could be tested in the field, before
>> being incorporated into the language core? Was for example limited type
>> return tested in the field? Accessibility rules? Anonymous access types?
> 
> At Ada-auth, they usually say something about customer response to
> implementation defined pragmas and such.

Customer response to the language standard? Are you joking?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27 15:38                                                         ` Dmitry A. Kazakov
@ 2011-09-27 18:06                                                           ` Georg Bauhaus
  2011-09-27 19:06                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-27 18:06 UTC (permalink / raw)


On 27.09.11 17:38, Dmitry A. Kazakov wrote:
> On Tue, 27 Sep 2011 17:11:03 +0200, Georg Bauhaus wrote:
> 
>> On 27.09.11 14:14, Dmitry A. Kazakov wrote:
>>> On Tue, 27 Sep 2011 12:18:28 +0200, Georg Bauhaus wrote:
>>>
> [...]
>>  So you end up explaining tasks
>> and protected objects anyway.  And you might be able to explain
>> why seemingly advantageous "primitives" like "concurrent" and
>> "lock" had been preferred to a library based approach.
> 
> As another example take elliptic integral of the first kind: F(x,k).

I had been talking about programming constructs, not specialized
mathematical functions that may or may not be expressed in terms
of more primitive mathematical functions.  The latter is quite
interesting, but might be seen as an experiment that should finally
arrive at some language, not just experimental libraries treated
as language.

That is, I'm assuming that programmers want a loop construct
in Ada, not just goto.

I'm assuming that they don't want to have to define loop in
terms of goto, even when this has certain advantages.
Or rely on libraries to supply "loop", not just the compiler.

I'm assuming that if programmers always had to build
(or have someone do it for them) specific concurrency constructs
out of concurrency primitives, than this is too time consuming.
A libraries approach seems like a kludge, too.

The of mine, quoted above, came out wrong: it should say that
"task" and "protected object" were chosen, not CAS or some such,
with libraries around it.

There is a staircase, so to speak, from very primitive features
up to more "heavy" features.  By *default*, I'd rather not
force programmers to always go down to the basement.
And hope that the libraries at upper floors are just as good as
what a language will normally make the compiler do.

Yes, in Ada 2012 we may reinvent basics in terms of more primitive
language features such as conditional goto, 'Succ/'Pred, and
and increment and decrement operations:

   type Nat is range 0 .. System.Max_Int;

   function "+" (Left, Right: in out Nat) return Nat is
      Y : Nat := 0;
   begin
      Copy (Target => Y, Source => Left);
  <<A>>
      if Right /= 0 then
         goto B;
      end if;
      goto C;
  <<B>>
      Y := Nat'Succ (Y);
      Right := Nat'Pred (Right);
      goto A;
  <<C>>
      return Y;
   end "+";


assuming a suitable definition of Copy.  I like it better
when Ada provides more than primitive built-ins. Goto and
libraries could provide a user-definable interface for defining
"loop".  I don't think programmers would ever care.

Rules for defining language primitives in libraries might
add some openness.  I truest that there will be overlap
between two sets of computer professionals, then:

 A := { Authors of compilers }
 B := { Authors of future library }

 A and B = A?

What is n in

 |A| - |A and B| = n% ?



> Why
> bother to with subprograms, accuracy of real types, real types themselves,
> approximation techniques for such a simple thing?

Ada's way of specifying fundamental types refers to concepts
relatively far away from hardware, IMO. The expression
  range 0.0 .. 100.0
is language. Thankfully, I don't have to follow some interface
of defining range types myself, interesting as it might be.
I'm also not sure that all Ada programmers will like it if
the very process of interpreting "range <x> .. <y>" is moved
to libraries.


> The answer to your question was given by Occam 700 years ago.

How much hair would the rasor have cut from Ada's definition
of its heavy concurrency primitives?

Iverson and the makers of S (and R) have begged to differ
as regards the "reach" of primitives.
The big money insurance industry says they were right.
(And, please, temporary success or failure of this or that
branch of industry is not an argument against language design
unless there is a causal relation.)

A question related to the "reach" of features: Are there patterns
of programming embedded control software that could very well
be reflected in language features?  I think they are, but not
in Ada, which is too primitive here.


>> At Ada-auth, they usually say something about customer response to
>> implementation defined pragmas and such.
> 
> Customer response to the language standard? Are you joking?

Response to experimental features such as pragma Assert; contracts
specified with pragma Precondition and such; or conditional
expressions, I think.




^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27 18:06                                                           ` Georg Bauhaus
@ 2011-09-27 19:06                                                             ` Dmitry A. Kazakov
  2011-09-29  0:01                                                               ` Georg Bauhaus
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-27 19:06 UTC (permalink / raw)


On Tue, 27 Sep 2011 20:06:35 +0200, Georg Bauhaus wrote:

> On 27.09.11 17:38, Dmitry A. Kazakov wrote:
>> On Tue, 27 Sep 2011 17:11:03 +0200, Georg Bauhaus wrote:
>> 
>>> On 27.09.11 14:14, Dmitry A. Kazakov wrote:
>>>> On Tue, 27 Sep 2011 12:18:28 +0200, Georg Bauhaus wrote:
>>>>
>> [...]
>>>  So you end up explaining tasks
>>> and protected objects anyway.  And you might be able to explain
>>> why seemingly advantageous "primitives" like "concurrent" and
>>> "lock" had been preferred to a library based approach.
>> 
>> As another example take elliptic integral of the first kind: F(x,k).
> 
> I had been talking about programming constructs, not specialized
> mathematical functions that may or may not be expressed in terms
> of more primitive mathematical functions.

A difference?

> That is, I'm assuming that programmers want a loop construct
> in Ada, not just goto.

Or recursion, or callbacks from some hidden iteration loop?

> I'm assuming that they don't want to have to define loop in
> terms of goto, even when this has certain advantages.

Do you think that they want to iterate containers using iterators?

My point is that loop as primitive should apply to user-defined stuff, like
containers. That means that the language should allow to "override" not
only the loop's body, but also its continue-or-exit part.

> I'm assuming that if programmers always had to build
> (or have someone do it for them) specific concurrency constructs
> out of concurrency primitives, than this is too time consuming.

Sorry, but this is what parallel programming is about.

> The of mine, quoted above, came out wrong: it should say that
> "task" and "protected object" were chosen, not CAS or some such,
> with libraries around it.

Tasks are not equivalent to CAS, you cannot create a task using CAS. You
need tasks independently on presence of CAS.

> There is a staircase, so to speak, from very primitive features
> up to more "heavy" features.

No. There is a huge difference between what is "heavy" 1) for machine, 2)
for programmer, 3) for customer. As an example take square root. Is it
"primitive"?

> Yes, in Ada 2012 we may reinvent basics in terms of more primitive
> language features such as conditional goto, 'Succ/'Pred, and
> and increment and decrement operations:
[...]

Don't confuse language construction with the Hilbert's program!

>> Why
>> bother to with subprograms, accuracy of real types, real types themselves,
>> approximation techniques for such a simple thing?
> 
> Ada's way of specifying fundamental types refers to concepts
> relatively far away from hardware, IMO.

While the field "pattern" is "double", it this what are you saying? Ada has
a more general concept, which is not heavier than "double", neither for the
hardware, nor for the programmer, nor for the customers. This is the right
way to design a good language.

>> The answer to your question was given by Occam 700 years ago.
> 
> How much hair would the rasor have cut from Ada's definition
> of its heavy concurrency primitives?

Heavy? Do you think that messages, channels, mutexes, events would be
lighter?

Anyway, the performance burden is not directly bound to being fundamental.
E.g. static types as a generalization of data value are for free.
 
> A question related to the "reach" of features: Are there patterns
> of programming embedded control software that could very well
> be reflected in language features?  I think they are, but not
> in Ada, which is too primitive here.

Nope, the patterns used in embedded control systems I am dealing with are
so rustic, that they better fit to an assembler or C. Ada is rocket science
compared to them.

>>> At Ada-auth, they usually say something about customer response to
>>> implementation defined pragmas and such.
>> 
>> Customer response to the language standard? Are you joking?
> 
> Response to experimental features such as pragma Assert; contracts
> specified with pragma Precondition and such; or conditional
> expressions, I think.

All three represent language design bugs, what was the point?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-27 19:06                                                             ` Dmitry A. Kazakov
@ 2011-09-29  0:01                                                               ` Georg Bauhaus
  2011-09-29  8:26                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-29  0:01 UTC (permalink / raw)


On 27.09.11 21:06, Dmitry A. Kazakov wrote:

>> I had been talking about programming constructs, not specialized
>> mathematical functions that may or may not be expressed in terms
>> of more primitive mathematical functions.
>
> A difference?

Huge difference.  A programming language such as Ada is about
a universal computing apparatus.  Mathematical language can do
without such an apparatus, an Ada program is typically written
to need one.  Also, square root has no place in the core of a
general purpose programming language, because its purpose is
not general; it is from some application domain with such a language.
Sqrt in the core of math oriented languages seems fine to me.
Same difference.

>> That is, I'm assuming that programmers want a loop construct
>> in Ada, not just goto.
>
> Or recursion, or callbacks from some hidden iteration loop?

Quite possibly recursion. OCaml marks functions as "rec" or not,
recent Fortran, too, IIRC.

>> I'm assuming that they don't want to have to define loop in
>> terms of goto, even when this has certain advantages.
>
> Do you think that they want to iterate containers using iterators?

Sequence comprehensions (with conditional) are popular, too.
Control of the control structure of comprehension is far less
frequently requested, I should think.


> My point is that loop as primitive should apply to user-defined stuff,

In a way, that's my point, too: language primitives exist if they
express common programming situations. If iterating a process for
a selection of elements of a container is a common programming situation,
then selection and iteration should be available via language primitives.

> like
> containers. That means that the language should allow to "override" not
> only the loop's body, but also its continue-or-exit part.

I'm not sure I understand. Sather iterators?  Or Lisp macros (sorry,
implementation of loop interface) for controlling in which way the
meaning of "if" becomes operational?
  

> Sorry, but this is what parallel programming is about.

Nitpick: Parallel programs do not seem so interesting insofar as parallel
programs don't communicate. Nothing fancy there.

But with tasks, perhaps I have a different meaning of "primitive" in
my mind: a task type can be a primitive of some Ada concurrency model.
But seen from the viewpoint of concurrency theory (not that I know
that much about it), insofar as it is about controlling the cooperation
of a set of "primitive" universal computers, Ada task types already
handle too much detail to be called "primitive".  (Else no one
would have discussed "abstraction inversion" in Ada tasking?)

The level of detail in a concept is the biggest factor in "heavy" IMO.
Heavy things might be useful, they might feel right, they might be
efficient (or free).

> Don't confuse language construction with the Hilbert's program!

Building upwards from "primitive thoughts" influences the way programming
languages develop, but which thoughts are allowed as primitive thoughts?

The domain of primitives is indeed not just that of formalism vs machine,
where one thinks of a formalism, and also has a machine and then these
correspond by magic with all other requirements of the (multiperson)
programming situation.  But Ada is a general purpose programming
language made for the primitive electrical things in particular.
That's a useful hint at what general purpose should mean, and how
general purpose drives the choice of core primitives of the language.

For example, in Ada, there is no built-in mechanism for scanning a database
of facts like there is in Prolog.  The built-in array operators are rather
primitive when compared to the built-in operators of APL, even though there
is overlap.
But conversely, APL's or Prolog's language cores do not let us say
'Compontent_Size, TTBOMK. Their notion of machine (and of time) is different
than that of Ada. "Delay" is a key word of Ada the language (and not in Ada
the library) whereas this is not usually the case with other languages:
their "primitive thoughts" have been different, and have not considered
the same requirements of control.

Should there be an "interface" that allows programmers to implement
the meaning of "delay" instead of the language doing it?




^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-29  0:01                                                               ` Georg Bauhaus
@ 2011-09-29  8:26                                                                 ` Dmitry A. Kazakov
  2011-09-30  1:24                                                                   ` Randy Brukardt
  2011-09-30 10:07                                                                   ` Georg Bauhaus
  0 siblings, 2 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-29  8:26 UTC (permalink / raw)


On Thu, 29 Sep 2011 02:01:44 +0200, Georg Bauhaus wrote:

> On 27.09.11 21:06, Dmitry A. Kazakov wrote:
> 
>>> I had been talking about programming constructs, not specialized
>>> mathematical functions that may or may not be expressed in terms
>>> of more primitive mathematical functions.
>>
>> A difference?
> 
> Huge difference.  A programming language such as Ada is about
> a universal computing apparatus.  Mathematical language can do
> without such an apparatus,

Come on, it is not XIX century. Mathematical language is all about such
apparatus: axiomatic frameworks + inference, nothing else. All major
achievements of XX century mathematics lay in understanding of multiplicity
and studying the limitations of such apparatuses.

> an Ada program is typically written
> to need one.  Also, square root has no place in the core of a
> general purpose programming language, because its purpose is
> not general; it is from some application domain with such a language.

I don't understand this. Has the number 12.3 general purpose, or specific
to the domain of numbers smaller than 13?

>> like
>> containers. That means that the language should allow to "override" not
>> only the loop's body, but also its continue-or-exit part.
> 
> I'm not sure I understand.

A for-loop consists of its body and its "header". In Ada you can define the
body of such loop as whatever pleases you. But the loop header Ada fails to
abstract it properly, e.g. as:

   for Index in Indicator-Set loop

>> Sorry, but this is what parallel programming is about.
> 
> Nitpick: Parallel programs do not seem so interesting insofar as parallel
> programs don't communicate.

No, communication is a solution. The key word is synchronization.
Independent components of a parallel program traverse certain states
coherently. Communication is a method to uphold the coherence.

> But with tasks, perhaps I have a different meaning of "primitive" in
> my mind: a task type can be a primitive of some Ada concurrency model.
> But seen from the viewpoint of concurrency theory (not that I know
> that much about it), insofar as it is about controlling the cooperation
> of a set of "primitive" universal computers, Ada task types already
> handle too much detail to be called "primitive".

A "primitive universal computer" runs what? [answer: one or more tasks]
Task in the meaning "subject of scheduling" is not only primitive, it is
atomic, semantically there is nothing a task could be divided into.

> (Else no one
> would have discussed "abstraction inversion" in Ada tasking?)

(In Ada 83 days I used tasks to pass subprogram as a parameter)

> The level of detail in a concept is the biggest factor in "heavy" IMO.
> Heavy things might be useful, they might feel right, they might be
> efficient (or free).

Again, "heavy" is meaningless outside one of three contexts: 1)
computational environment ("hardware language"), 2) the programming
language, 3) the problem domain.

Is sqrt "heavy"?

>> Don't confuse language construction with the Hilbert's program!
> 
> Building upwards from "primitive thoughts" influences the way programming
> languages develop, but which thoughts are allowed as primitive thoughts?

Minimal complete sets.

> But Ada is a general purpose programming
> language made for the primitive electrical things in particular.

Electrical things = electromagnetic fields? (:-))

In 40-50's there was a term for what you meant: systems of relays.
Electrical switches (tubes, transistors) is an example of.

But of course Ada was not made for that.

> That's a useful hint at what general purpose should mean, and how
> general purpose drives the choice of core primitives of the language.

Nope. General purpose means what it says, an ability to use this language
for developing a most wide set of applications.

> For example, in Ada, there is no built-in mechanism for scanning a database
> of facts like there is in Prolog.

Prolog was not made for "electrical things"? (:-))

To put it into relation, you can implement Prolog inference engine in Ada,
you also can use Prolog inference to implement, say, Ada's fixed point
arithmetic. The difference is only in how much source code it takes and how
simple would be to maintain such code. This has nothing to do with
hardware. Machine code is not general purpose language. General purpose,
see above, means that the efforts needed to complete a programming tasks
are approximately same for different application domains.

> "Delay" is a key word of Ada the language (and not in Ada
> the library) whereas this is not usually the case with other languages:
> their "primitive thoughts" have been different, and have not considered
> the same requirements of control.
> 
> Should there be an "interface" that allows programmers to implement
> the meaning of "delay" instead of the language doing it?

These are two different issues here:

1. Syntactic shape of delay
2. Its semantics (e.g. user-defined)

1. The shape of delay is irrelevant (e.g. can be a subprogram) IF delay is
not composable. As you know delay do participate in things which cannot be
expressed by means of procedural decomposition. Example: timed entry call.

2. The semantics of delay is fixed in real-time systems and need not to be
redefined. But, considering simulation systems, where time is simulated, it
would be thinkable to have Duration, Time user-defined and delay
overridden.

What was the point?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-29  8:26                                                                 ` Dmitry A. Kazakov
@ 2011-09-30  1:24                                                                   ` Randy Brukardt
  2011-09-30  8:10                                                                     ` Dmitry A. Kazakov
  2011-09-30 10:07                                                                   ` Georg Bauhaus
  1 sibling, 1 reply; 89+ messages in thread
From: Randy Brukardt @ 2011-09-30  1:24 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1vb9afcggqs8b$.prrlzbnf51p$.dlg@40tude.net...
> On Thu, 29 Sep 2011 02:01:44 +0200, Georg Bauhaus wrote:
...
>> I'm not sure I understand.
>
> A for-loop consists of its body and its "header". In Ada you can define 
> the
> body of such loop as whatever pleases you. But the loop header Ada fails 
> to
> abstract it properly, e.g. as:
>
>   for Index in Indicator-Set loop

Huh? That's exactly what Ada 2012 allows you to do - redefine the meaning of 
the loop header. And you get two forms:
    for Index in Indicator_Set loop -- Index is a cursor (or whatever index 
type you like)
    for Element of Indicator_Set loop -- Element represents each of the 
elements of the set, no index needed (or provided). Element can be a 
variable in some circumstances, so this form can be used to update the set 
without any viisible use of indexes (cursors).

Someone of course has to define the "iterator type" and "iterator object" 
which provides that, and those can do anything that fits into the pattern. 
(One possibility that was discussed was iterating a construct-on-use data 
structure.)

This is a powerful new abstraction for Ada, making it much easier to treat a 
container in the same way as a primitive array type. (Array types also get 
the new element syntax so there consistency with that.)

                                 Randy.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-30  1:24                                                                   ` Randy Brukardt
@ 2011-09-30  8:10                                                                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-30  8:10 UTC (permalink / raw)


On Thu, 29 Sep 2011 20:24:23 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1vb9afcggqs8b$.prrlzbnf51p$.dlg@40tude.net...
>> On Thu, 29 Sep 2011 02:01:44 +0200, Georg Bauhaus wrote:
> ...
>>> I'm not sure I understand.
>>
>> A for-loop consists of its body and its "header". In Ada you can define the
>> body of such loop as whatever pleases you. But the loop header Ada fails to
>> abstract it properly, e.g. as:
>>
>>   for Index in Indicator-Set loop
> 
> Huh? That's exactly what Ada 2012 allows you to do - redefine the meaning of 
> the loop header. And you get two forms:
>     for Index in Indicator_Set loop -- Index is a cursor (or whatever index 
> type you like)
>     for Element of Indicator_Set loop

That rather is

   for Element of Set loop

(Indicator set is a set of things indicating elements of another set, e.g.
a set of indices, like range, singleton etc.)

> -- Element represents each of the 
> elements of the set, no index needed (or provided). Element can be a 
> variable in some circumstances, so this form can be used to update the set 
> without any viisible use of indexes (cursors).
> 
> Someone of course has to define the "iterator type" and "iterator object" 
> which provides that, and those can do anything that fits into the pattern.

Which is potentially a problem, because for native arrays you can get the
related types directly from the array. There is a cloud of types around the
container type. The interface of an abstract container should include
operations/aspects/attributes to get at these types (like T'Class gets
class T from T). E.g.

   for Index in Container'Range loop -- Indicator set
   for Element in Container loop -- The set itself

> This is a powerful new abstraction for Ada, making it much easier to treat a 
> container in the same way as a primitive array type. (Array types also get 
> the new element syntax so there consistency with that.)

Maybe, however other issues are the behavior under inheritance: from the
container type, from the index type, from the type of the sets of indices
(absent). How these types can be constrained to subtypes. Objects of index
sets (ranges, singletons, diagonals etc). Subsets of the container sets
(slices). All these types and subtypes coherently passed to a generics.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-29  8:26                                                                 ` Dmitry A. Kazakov
  2011-09-30  1:24                                                                   ` Randy Brukardt
@ 2011-09-30 10:07                                                                   ` Georg Bauhaus
  2011-09-30 12:38                                                                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-30 10:07 UTC (permalink / raw)


On 29.09.11 10:26, Dmitry A. Kazakov wrote:

>> Huge difference.  A programming language such as Ada is about
>> a universal computing apparatus.  Mathematical language can do
>> without such an apparatus,
>
> Come on, it is not XIX century. Mathematical language is all about such
> apparatus: axiomatic frameworks + inference, nothing else. All major
> achievements of XX century mathematics lay in understanding of multiplicity
> and studying the limitations of such apparatuses.

Back on track: my question was whether or not a language should
enable programmers to implement or override what is built into the
language core. Consequently, whether or not additions to Ada
should be made such that programmers can implement language
by following the rules of a "feature's interface".

Whether or not programmers should be able to correctly manipulate
language features.


Where should we draw a line, if any?

(Mathematics is insufficient as a model. Its vocabulary and focus,
that is, its language, do not describe the same objects as does
programming language design.
In one direction mathematics is more inclusive, but in another
it looses sight of the "electrical things", and tends to ignore
time and space, and quite reasonably so, when mathematicians hope
for inspiration to come from something other than algorithmic
work.

(This is why I think that mathematics provides for inspiration,
but is leading the wrong way as the sole inspiration for language.
Just recalling the commercial, organizational, electrical, etc
contexts that you and I have been stating more than once.)

> Has the number 12.3 general purpose, or specific
> to the domain of numbers smaller than 13?

The sqrt operation is not general purpose in that there is only
a selection of programs that ever use it. Whether the sqrt operation
has a purpose in and of itself I do not know.  If Sqrt is not
ubiquitous in programs, then it should not be part of the very core
of a general purpose language.

There is no simple yes-or-no scheme that can determine whether or not
an operation fits a general purpose. More below.

> A "primitive universal computer" runs what? [answer: one or more tasks]
> Task in the meaning "subject of scheduling" is not only primitive, it is
> atomic, semantically there is nothing a task could be divided into.

This definition of task cannot serve the goal of establishing
program construction facilities of programming languages, and
of Ada in particular:

it is lifting the point of view too high; we don't see the
vocabulary any longer; when I write a program, it is precisely
the divisions of a "subject of scheduling" that should be
expressible using built-in language. (Similarly for the
communications.)  Why be concerned with built-in language?
Because built-ins are important, more important than other modes
of dividing insofar as programmers find them more important.
Insofar as program change management finds them important.

I'll also prefer "task" to mean something that Ada programmers would
recognize.


>> The level of detail in a concept is the biggest factor in "heavy" IMO.
>> Heavy things might be useful, they might feel right, they might be
>> efficient (or free).
>
> Again, "heavy" is meaningless outside one of three contexts: 1)
> computational environment ("hardware language"), 2) the programming
> language, 3) the problem domain.

Plus: 4) compiler making business requirements, 5) programmers, customers,
already mentioned, and further ingredients of the programming situation.

A general purpose programming language will IMHO either
be a panacea that includes, in its definition, every mechanism ever
invented, or tries to be minimal in some sense. To clarify, the notion
of general purpose language can be set against special purpose language
or domain specific language.

Should a language like Prolog be defined such that implementers
must provide for programmers who wish to override the database
scanning implementation? Or replace the backtracking implementation with
one of their own? Alternatively, the customer/programmer can just have
a Prolog shop make an implementation the meets their special requirements.
This will leave the implementations of scanning and backtracking
inaccessible by programmers, but the programmers will achieve their goals.
Seems healthy to me, because programmers should not be concerned with
adjusting implementations.

They should use the tools, not manipulate them.


We also need to know what "minimal set" is, regarding 1) - 5).
Also, completeness of a minimal set, regarding 1) - 5).
The interactions, the conflicting conclusions, etc. that will affect
choices of language features.

One data point is that "general purpose" (G) vs "special purpose" (S)
can refer to effort it takes to write a program in G or S language
that has a given effect.

Indeed, another "difference is ... how much source code it takes and how
simple would be to maintain such code."


>> "Delay" is a key word of Ada the language (and not in Ada
>> the library) whereas this is not usually the case with other languages:
>> their "primitive thoughts" have been different, and have not considered
>> the same requirements of control.
>>
>> Should there be an "interface" that allows programmers to implement
>> the meaning of "delay" instead of the language doing it?
>
> These are two different issues here:
>
> 1. Syntactic shape of delay
> 2. Its semantics (e.g. user-defined)
>
> 1. The shape of delay is irrelevant (e.g. can be a subprogram)

I beg to differ, the shape of "delay" signifies that "delay" is
important, with or without the reasons that follow from the language
formalism. I'd rather not see it replaced with something that looks
ordinary and simply hides compiler magic.


> 2. The semantics of delay is fixed in real-time systems and need not to be
> redefined. But, considering simulation systems, where time is simulated, it
> would be thinkable to have Duration, Time user-defined and delay
> overridden.
>
> What was the point?

As outlined in the Prolog case, I prefer such changes to be the
subject of creating a suitably adapted implementation. Not my job,
not the programmer's job.  There is also a matter of choice: should
every effective feature of the language be a type?

I see two cases:

(1) the polymorphic "delay" does not change overall behavior.
For example, the intention is to scale time logarithmically,
for the purpose of simulating a technical process that takes long.
This keeps relative timings.  But we can just wrap the scaling
into some function that returns durations depending on configuration.
This does not need new or polymorphic duration/time[_span].

(2) the behavior of "delay" is to change, for example, relative
timings and or order would differ from the timings of the real thing
even when, by the LRM, they should not.

Ideally, (2) would not be portable at the syntax level. After all,
program behavior changes. Such a change is surprising when seen from
an Ada perspective, and therefore assuming that certain features of
the language are not even polymorphic.





^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-30 10:07                                                                   ` Georg Bauhaus
@ 2011-09-30 12:38                                                                     ` Dmitry A. Kazakov
  2011-09-30 17:40                                                                       ` Georg Bauhaus
  0 siblings, 1 reply; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-30 12:38 UTC (permalink / raw)


On Fri, 30 Sep 2011 12:07:53 +0200, Georg Bauhaus wrote:

> Back on track: my question was whether or not a language should
> enable programmers to implement or override what is built into the
> language core.

It should not.

> Whether or not programmers should be able to correctly manipulate
> language features.

They should not. 

The idea of extensible language was popular in 60s, but then was quickly
ditched.

>> Has the number 12.3 general purpose, or specific
>> to the domain of numbers smaller than 13?
> 
> The sqrt operation is not general purpose in that there is only
> a selection of programs that ever use it.

I bet that practically no program uses the number -435167342. Is it not
general purpose?

>> A "primitive universal computer" runs what? [answer: one or more tasks]
>> Task in the meaning "subject of scheduling" is not only primitive, it is
>> atomic, semantically there is nothing a task could be divided into.
> 
> This definition of task cannot serve the goal of establishing
> program construction facilities of programming languages, and
> of Ada in particular:

I don't understand this.
 
> I'll also prefer "task" to mean something that Ada programmers would
> recognize.

As something, which is not a task?

I don't understand what you are trying to say. Task is fundamental to
concurrent computing, they cannot be expressed in any other terms.

>>> The level of detail in a concept is the biggest factor in "heavy" IMO.
>>> Heavy things might be useful, they might feel right, they might be
>>> efficient (or free).
>>
>> Again, "heavy" is meaningless outside one of three contexts: 1)
>> computational environment ("hardware language"), 2) the programming
>> language, 3) the problem domain.
> 
> Plus: 4) compiler making business requirements,

Irrelevant.

> 5) programmers, customers,

Programmers /= customers

Anyway, you didn't answer which category is supposed to decide what is
"heavy".

> A general purpose programming language will IMHO either
> be a panacea that includes, in its definition, every mechanism ever
> invented,

That would be just a poorly designed language.

> or tries to be minimal in some sense.

This applies to *any* language.

> Should a language like Prolog be defined such that implementers
> must provide for programmers who wish to override the database
> scanning implementation? Or replace the backtracking implementation with
> one of their own?

Yes, if Prolog designers wished it survive... but they didn't.

> Alternatively, the customer/programmer can just have
> a Prolog shop make an implementation the meets their special requirements.

See above. It didn't work in 60s, it has less than zero chances now. For
same reasons we are buying industrially produced things, even if it is
relatively inexpensive things like food or clothing.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-30 12:38                                                                     ` Dmitry A. Kazakov
@ 2011-09-30 17:40                                                                       ` Georg Bauhaus
  2011-09-30 18:55                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 89+ messages in thread
From: Georg Bauhaus @ 2011-09-30 17:40 UTC (permalink / raw)


On 30.09.11 14:38, Dmitry A. Kazakov wrote:
> On Fri, 30 Sep 2011 12:07:53 +0200, Georg Bauhaus wrote:
> 
>> Back on track: my question was whether or not a language should
>> enable programmers to implement or override what is built into the
>> language core.
> 
> It should not.

Aha!

>> Whether or not programmers should be able to correctly manipulate
>> language features.
> 
> They should not. 

So that's a no.

Then:

>> Should a language like Prolog be defined such that (...)
>> replace the backtracking implementation with one of their own?

> Yes, if Prolog designers wished it survive... but they didn't.

And that's a yes.

Can the contradiction be resolved?

The example about Prolog and its struggle for existence
would emphasize my point. The example would show one way
in which compiler making and language making are not
independent in some situations. The aspect being that economic
rationality would suggest programmer-defined language built-ins.
(If it sells, ...)


> I bet that practically no program uses the number -435167342. Is it not
> general purpose?

It is not, if no purpose can be specified, and I suppose that
few language standards talk about the number -435167342.
(Maybe the telephone directory of Eckernf�rde does :-)
Numeric types will more likely match general purpose.

Anyway, a language standard may define a set of operations,
such as Sqrt, and say that they are available in the core language.
Array concatenation is one such operation, Sqrt isn't.


>> I'll also prefer "task" to mean something that Ada programmers would
>> recognize.
> 
> As something, which is not a task?
> 
> I don't understand what you are trying to say. Task is fundamental to
> concurrent computing, they cannot be expressed in any other terms.


The notion of Ada tasks is a composite notion. A task has ...
A task operates this way [sequence of conceptual steps] ...
A task type is ...  Hence, seen as a notion, a task is not atomic.
Typical facilities of an Ada task can be built from other primitives
of concurrent programming, if one were to do this in another language.
Compiler writer must do this. For programmers, Ada has much of it in
the language, Java programmers will find little in the language,
but a fair bit in java.util.concurrent.*, i.e. a library.
And the necessary discipline.
Coming back to the selection of built-ins for a language,
communicating tasks are an important building block. The importance
is reflected in its special presence in Ada, the language.
It has special syntax. Ada tasks do not come from some library.

Since the Ada notion of task incorporates many facilities
that can be taken for granted, I call tasks heavy, in this
sense.

Since we have protected objects, sometimes qualified to be
light weight, there must have been another notion of "heavy"
associated with task. (I.e., in another sense.)

>> Plus: 4) compiler making business requirements,
> Irrelevant.
Practically, compiler making business is rather decisive.
Just look at who is active on behalf of the ARG; Google is paying
... for Python, Go ...,  MS is paying ... for language research
(including standardized languages like C++ or Javascript), the
WGs being  staffed by ...

>> 5) programmers, customers,
> Programmers /= customers
Yes.

> Anyway, you didn't answer which category is supposed to decide what is
> "heavy".

People from all of the categories try to move decisions in certain
directions. That's necessarily my point. To learn about why a feature
should go into a language, it takes an interdisciplinary approach,
not just because it might be desirable, but because this is what
happens as soon as a language starts to have a significant number
of users.  I should add 6), which is fashion, which sometimes
facilitates (and funds!) a language effort in the first place.

For example, Douglas Crockford has commented on the pressure that
Microsoft (and others?) are exercising on the development process of
Javascript. They want the language such that their other languages
would have a better backend (i.e. Javascript being the target language).


>> A general purpose programming language will IMHO either
>> be a panacea that includes, in its definition, every mechanism ever
>> invented,
> That would be just a poorly designed language.
OK

>> or tries to be minimal in some sense.
> 
> This applies to *any* language.

Being minimal applies to any language only if one trivializes
"minimal in some sense", which is a trap. The "some sense"
part is the interesting part.


>> Alternatively, the customer/programmer can just have
>> a Prolog shop make an implementation the meets their special requirements.
> 
> See above. It didn't work in 60s,

It works for some of the Ada business now, if I'm not mistaken.
A nice thing is that programmers can still write core Ada by the
book and talk to the compiler guys about what their run-time
should do.




^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: discriminant questions
  2011-09-30 17:40                                                                       ` Georg Bauhaus
@ 2011-09-30 18:55                                                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 89+ messages in thread
From: Dmitry A. Kazakov @ 2011-09-30 18:55 UTC (permalink / raw)


On Fri, 30 Sep 2011 19:40:01 +0200, Georg Bauhaus wrote:

> On 30.09.11 14:38, Dmitry A. Kazakov wrote:
>> On Fri, 30 Sep 2011 12:07:53 +0200, Georg Bauhaus wrote:
>> 
>>> Whether or not programmers should be able to correctly manipulate
>>> language features.
>> 
>> They should not. 
> 
> So that's a no.
> 
> Then:
> 
>>> Should a language like Prolog be defined such that (...)
>>> replace the backtracking implementation with one of their own?
> 
>> Yes, if Prolog designers wished it survive... but they didn't.
> 
> And that's a yes.
> 
> Can the contradiction be resolved?

There is no contradiction. It is like Ada storage pools, by providing a
custom storage pool you don't manipulate language features.

>> I bet that practically no program uses the number -435167342. Is it not
>> general purpose?
> 
> It is not, if no purpose can be specified, and I suppose that
> few language standards talk about the number -435167342.
> (Maybe the telephone directory of Eckernf�rde does :-)
> Numeric types will more likely match general purpose.

That has implications, once you add an integer type you must provide
-435167342 with it. In fact, 435167342 is an integral part of Ada syntax
(as a literal, all possible literals are).

>>> I'll also prefer "task" to mean something that Ada programmers would
>>> recognize.
>> 
>> As something, which is not a task?
>> 
>> I don't understand what you are trying to say. Task is fundamental to
>> concurrent computing, they cannot be expressed in any other terms.
> 
> The notion of Ada tasks is a composite notion.

No, Ada tasks is a possible implementation of abstract task. The components
of Ada tasks are as composite as the components of Ada subprograms, Ada
gotos etc.

> ...  Hence, seen as a notion, a task is not atomic.

That does not follow. In order to show it you have to demonstrate how to
implement a task without using tasks.

> Typical facilities of an Ada task can be built from other primitives
> of concurrent programming, if one were to do this in another language.

There is no such primitives. The corresponding OS primitives (e.g. threads)
or ones of the Ada RTL, are already tasks, albeit non-Ada tasks.

> Since the Ada notion of task incorporates many facilities
> that can be taken for granted, I call tasks heavy, in this
> sense.

This definition of "heavy" makes no sense.

> Since we have protected objects, sometimes qualified to be
> light weight, there must have been another notion of "heavy"
> associated with task. (I.e., in another sense.)

The protected object has no less "facilities" than the task.

The light weight of protected object refer to its application to certain
concurrency problems under certain machine architectures *in addition* to
tasks. These very problems can be solved without protected objects using
tasks only. The opposite is wrong: no concurrency problem can be solved by
protected objects alone without tasks (and interrupts, which is a special
case of task).
 
>>> Plus: 4) compiler making business requirements,
>> Irrelevant.
> Practically, compiler making business is rather decisive.
> Just look at who is active on behalf of the ARG; Google is paying
> ... for Python, Go ...,  MS is paying ... for language research
> (including standardized languages like C++ or Javascript), the
> WGs being  staffed by ...

So? Do you sincerely believe the result depends on who pays? Commercial
languages are equally poor, because the market of languages is
dysfunctional, dead.

>> Anyway, you didn't answer which category is supposed to decide what is
>> "heavy".
> 
> People from all of the categories try to move decisions in certain
> directions.

People here have different influence. There is no consensus on what is
"heavy", so your model just does not work.

>>> or tries to be minimal in some sense.
>> 
>> This applies to *any* language.
> 
> Being minimal applies to any language only if one trivializes
> "minimal in some sense", which is a trap. The "some sense"
> part is the interesting part.

See above. 

>>> Alternatively, the customer/programmer can just have
>>> a Prolog shop make an implementation the meets their special requirements.
>> 
>> See above. It didn't work in 60s,
> 
> It works for some of the Ada business now, if I'm not mistaken.

You are. There is no competing Ada clones. Deviations are considered as
flaws not as special features. Would by buy a DVD burner that produces
unreadable DVDs? Anybody prefer, maybe, suboptimal, but most compatible and
versatile product.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 89+ messages in thread

end of thread, other threads:[~2011-09-30 18:55 UTC | newest]

Thread overview: 89+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-17 16:30 discriminant questions ytomino
2011-09-17 17:19 ` Dmitry A. Kazakov
2011-09-17 17:46   ` ytomino
2011-09-17 19:41     ` Dmitry A. Kazakov
2011-09-17 22:55       ` ytomino
2011-09-18  8:50         ` Dmitry A. Kazakov
2011-09-18 10:54           ` ytomino
2011-09-18 11:35             ` Dmitry A. Kazakov
2011-09-18 12:41               ` ytomino
2011-09-18 13:17                 ` Dmitry A. Kazakov
2011-09-18 16:22                   ` ytomino
2011-09-18 16:32                   ` ytomino
2011-09-18 18:15                     ` Dmitry A. Kazakov
2011-09-18 23:44                       ` ytomino
2011-09-19  7:27                         ` Dmitry A. Kazakov
2011-09-18 14:43               ` Dmitry A. Kazakov
2011-09-18 16:46               ` Robert A Duff
2011-09-18 18:01                 ` Dmitry A. Kazakov
2011-09-18 19:20                   ` Maciej Sobczak
2011-09-19  7:39                     ` Dmitry A. Kazakov
2011-09-19 20:00                       ` Maciej Sobczak
2011-09-20  7:33                         ` Dmitry A. Kazakov
2011-09-20 15:45                           ` Maciej Sobczak
2011-09-20 16:48                             ` Dmitry A. Kazakov
2011-09-20 20:19                               ` Maciej Sobczak
2011-09-21  7:48                                 ` Dmitry A. Kazakov
2011-09-21 20:51                                   ` Maciej Sobczak
2011-09-22  8:07                                     ` Dmitry A. Kazakov
2011-09-22 20:57                                       ` Maciej Sobczak
2011-09-23  7:59                                         ` Dmitry A. Kazakov
2011-09-23 10:57                                           ` Georg Bauhaus
2011-09-23 22:30                                           ` Randy Brukardt
2011-09-23 22:50                                           ` Randy Brukardt
2011-09-24  6:46                                             ` Dmitry A. Kazakov
2011-09-26 22:48                                               ` Randy Brukardt
2011-09-27  8:10                                                 ` Dmitry A. Kazakov
2011-09-27 10:18                                                   ` Georg Bauhaus
2011-09-27 12:14                                                     ` Dmitry A. Kazakov
2011-09-27 15:11                                                       ` Georg Bauhaus
2011-09-27 15:38                                                         ` Dmitry A. Kazakov
2011-09-27 18:06                                                           ` Georg Bauhaus
2011-09-27 19:06                                                             ` Dmitry A. Kazakov
2011-09-29  0:01                                                               ` Georg Bauhaus
2011-09-29  8:26                                                                 ` Dmitry A. Kazakov
2011-09-30  1:24                                                                   ` Randy Brukardt
2011-09-30  8:10                                                                     ` Dmitry A. Kazakov
2011-09-30 10:07                                                                   ` Georg Bauhaus
2011-09-30 12:38                                                                     ` Dmitry A. Kazakov
2011-09-30 17:40                                                                       ` Georg Bauhaus
2011-09-30 18:55                                                                         ` Dmitry A. Kazakov
2011-09-23  9:23                                       ` Stephen Leake
2011-09-23  9:48                                         ` Dmitry A. Kazakov
2011-09-23 22:42                                           ` Randy Brukardt
2011-09-24  6:56                                             ` Dmitry A. Kazakov
2011-09-26 22:43                                               ` Randy Brukardt
2011-09-24 10:47                                             ` Stephen Leake
2011-09-24 12:54                                       ` Simon Wright
2011-09-24 14:46                                         ` Dmitry A. Kazakov
2011-09-24 16:21                                           ` Simon Wright
2011-09-24 16:43                                             ` Dmitry A. Kazakov
2011-09-22  2:52                                   ` Randy Brukardt
2011-09-22  8:11                                     ` Dmitry A. Kazakov
2011-09-20  0:01           ` Randy Brukardt
2011-09-20  7:38             ` Dmitry A. Kazakov
2011-09-20 11:11               ` AdaMagica
2011-09-20 12:09                 ` Dmitry A. Kazakov
2011-09-20 12:31                   ` AdaMagica
2011-09-20 12:57                     ` Dmitry A. Kazakov
2011-09-20 23:28                       ` ytomino
2011-09-21  5:03                         ` AdaMagica
2011-09-21  8:08                         ` Dmitry A. Kazakov
2011-09-21 10:03                           ` Georg Bauhaus
2011-09-21 10:29                             ` Dmitry A. Kazakov
2011-09-22  3:21                           ` Randy Brukardt
2011-09-22  3:05                   ` Randy Brukardt
2011-09-19 23:35         ` Randy Brukardt
2011-09-20 21:39           ` ytomino
2011-09-22  3:32             ` Randy Brukardt
2011-09-18 16:32 ` ytomino
2011-09-19 14:46   ` ytomino
2011-09-19 15:14     ` Dmitry A. Kazakov
2011-09-19 17:49       ` ytomino
2011-09-20  7:29         ` Georg Bauhaus
2011-09-20 19:50           ` ytomino
2011-09-20  8:08         ` Dmitry A. Kazakov
2011-09-20 18:47           ` ytomino
2011-09-21  8:16             ` Dmitry A. Kazakov
2011-09-21  9:55               ` ytomino
2011-09-22  3:26                 ` Randy Brukardt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox