December 29, 2002
Walter wrote:
> "Burton Radons" <loth@users.sourceforge.net> wrote in message
> news:aul9s3$1pkf$1@digitaldaemon.com...
> 
>>Walter wrote:
>>
>>>"Burton Radons" <loth@users.sourceforge.net> wrote in message
>>>
>>>
>>>>Howsabout the builtin types have an attribute ".zero" that we can put
>>>>into our user types as static variables/constants.  Then that line would
>>>
>>>be:
>>>
>>>All types have an attribute .init which gives their default initalizer
>>>value.
>>
>>float.init is not zero.
> 
> 
> That's right. I must have misunderstood your point then!

You read right over it, unless if you're randomly accessing messages.

Take a sum template:

    T sum (T [] list)
    {
        T result = 0;

        for (T *c = list, e = c + list.length; c < e; c ++)
            result += *c;

        return c;
    }

The problem is that this depends upon 0 meaning something in the context of T, which is simply not possible in D, and I don't want to depend upon this kind of thing as contextual identification of common forms infects C++ and partly makes it the mess it is with operator overloading.  Just "T result;" won't work, as that shouldn't be initialised.  "T result = T.zero;", on the other hand, works nicely, clearly means only one thing, and shouldn't mess up anything else.  Daniel also noted that we need a .one.

December 29, 2002
"Walter" <walter@digitalmars.com> escreveu na mensagem news:aunk3v$be4$1@digitaldaemon.com...
>
> "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:as8274$hck$1@digitaldaemon.com...
> > But let us keep the discussion level
> > high and the ideas flowing, maybe we can give this problem a simple,
fast
> > and safe solution.
>
> Yes, I enjoy this discussion quite a bit.
>
>

I'm waiting for the 0.51 compiler before continuing with this discussion. Maybe new features in it will drive this conversation to other areas. Just a wish: join delegates and function pointers under a single syntax for function types, so we can write a single template for both kinds of functions. Also a convenient way to express function types is needed, because writing:


instance myTemplate(int (*fp)(int, int)) int_int_int;


is very strange.


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.434 / Virus Database: 243 - Release Date: 25/12/2002


January 07, 2003
Ok, I'll have to think about that some more. I want to be careful adding in more . properties, as it could easilly get out of hand.

"Burton Radons" <loth@users.sourceforge.net> wrote in message news:aunkbe$bni$1@digitaldaemon.com...
> Walter wrote:
> > "Burton Radons" <loth@users.sourceforge.net> wrote in message news:aul9s3$1pkf$1@digitaldaemon.com...
> >
> >>Walter wrote:
> >>
> >>>"Burton Radons" <loth@users.sourceforge.net> wrote in message
> >>>
> >>>
> >>>>Howsabout the builtin types have an attribute ".zero" that we can put into our user types as static variables/constants.  Then that line
would
> >>>
> >>>be:
> >>>
> >>>All types have an attribute .init which gives their default initalizer value.
> >>
> >>float.init is not zero.
> >
> >
> > That's right. I must have misunderstood your point then!
>
> You read right over it, unless if you're randomly accessing messages.
>
> Take a sum template:
>
>      T sum (T [] list)
>      {
>          T result = 0;
>
>          for (T *c = list, e = c + list.length; c < e; c ++)
>              result += *c;
>
>          return c;
>      }
>
> The problem is that this depends upon 0 meaning something in the context of T, which is simply not possible in D, and I don't want to depend upon this kind of thing as contextual identification of common forms infects C++ and partly makes it the mess it is with operator overloading.  Just "T result;" won't work, as that shouldn't be initialised.  "T result = T.zero;", on the other hand, works nicely, clearly means only one thing, and shouldn't mess up anything else.  Daniel also noted that we need a
.one.
>


January 09, 2003
Walter wrote:
> Ok, I'll have to think about that some more. I want to be careful adding in
> more . properties, as it could easilly get out of hand.

We could entertain extensions:

       extension FloatNumeric (type)
       {
           type sqrt () { return intrinsic.sqrt (*this); }
       }

       extension SignedNumeric (type)
       {
           static bit signable () { return true; }
       }

       extension UnsignedNumeric (type)
       {
           static bit signable () { return false; }
       }

       extension Numeric (type)
       {
           bit signed () { return *this < type.zero; }
           int sign () { return signed () ? -1 : 1; }
       }

       extend FloatNumeric for float, double, extended, complex;
       extend SignedNumeric for byte, short, int, long, float, double,
extended, complex;
       extend UnsignedNumeric for bit, ubyte, ushort, uint, ulong;
       extend Numeric for ...;

       bit.signable; /* Calls UnsignedNumeric.signable */

       int x;

       x.signed; /* Calls SignedNumeric.signed */

Extending a type gives it these properties for the purpose of
compilation - all static or final, any overlap is an error (except
perhaps that typedef defines a new layer that allows overlapping any
previous instantiations?  What scopes are used becomes an issue), no
fields.  This doesn't handle instancing an extension for any type of
array, but as it's easy to do so manually it's not so much a problem.
Then again, being able to move everything into Phobos, including .sort,
indexing, and resizing, would have some advantages.  How about:

       instance ArraySortExtension (* []);

The problem is that this becomes unimplementable:

       extension ArrayIndexExtension (type)
       {
           XXX getitem (int index)
           {
               assert (index > 0 && index < type.length);
               return type.data [index];
           }
       }

So it could be:

       extension ArrayIndexExtension (type [])
       ...
       instance ArraySortExtension (*);

Or:

       extension ArrayIndexExtension (type)
       {
           type.next getitem (int index)
       }

Which would allow user structs to be extended, so I like that best.

I feel like I'm dancing around a simpler, more elegant solution, but I
can't quite grasp it.

January 09, 2003
This line of reasoning looks promising.  This has been requested before, as a way to add custom methods to classes defined elsewhere, such as in the standard library;  possibly even to basic types.

Seems eminently doable, probably not that difficult to implement aside from hiding the extensions inside modules so that different modules can provide similarly named extensions that don't clash with each other.  I think normal module scoping will handle that.  The extensions have scope of the module they're defined in, but are otherwise conceptually part of the type that they extend.  Within said module they appear "embedded" into the extended type, exactly like a normal member.  Elsewhere they'd have to be imported or explicitly called maybe like module.type.extendedmember()

Sean

"Burton Radons" <loth@users.sourceforge.net> wrote in message news:avimh0$vks$2@digitaldaemon.com...
> Walter wrote:
> > Ok, I'll have to think about that some more. I want to be careful adding
in
> > more . properties, as it could easilly get out of hand.
>
> We could entertain extensions:
>
>         extension FloatNumeric (type)
>         {
>             type sqrt () { return intrinsic.sqrt (*this); }
>         }
>
>         extension SignedNumeric (type)
>         {
>             static bit signable () { return true; }
>         }
>
>         extension UnsignedNumeric (type)
>         {
>             static bit signable () { return false; }
>         }
>
>         extension Numeric (type)
>         {
>             bit signed () { return *this < type.zero; }
>             int sign () { return signed () ? -1 : 1; }
>         }
>
>         extend FloatNumeric for float, double, extended, complex;
>         extend SignedNumeric for byte, short, int, long, float, double,
> extended, complex;
>         extend UnsignedNumeric for bit, ubyte, ushort, uint, ulong;
>         extend Numeric for ...;
>
>         bit.signable; /* Calls UnsignedNumeric.signable */
>
>         int x;
>
>         x.signed; /* Calls SignedNumeric.signed */
>
> Extending a type gives it these properties for the purpose of compilation - all static or final, any overlap is an error (except perhaps that typedef defines a new layer that allows overlapping any previous instantiations?  What scopes are used becomes an issue), no fields.  This doesn't handle instancing an extension for any type of array, but as it's easy to do so manually it's not so much a problem. Then again, being able to move everything into Phobos, including .sort, indexing, and resizing, would have some advantages.  How about:
>
>         instance ArraySortExtension (* []);
>
> The problem is that this becomes unimplementable:
>
>         extension ArrayIndexExtension (type)
>         {
>             XXX getitem (int index)
>             {
>                 assert (index > 0 && index < type.length);
>                 return type.data [index];
>             }
>         }
>
> So it could be:
>
>         extension ArrayIndexExtension (type [])
>         ...
>         instance ArraySortExtension (*);
>
> Or:
>
>         extension ArrayIndexExtension (type)
>         {
>             type.next getitem (int index)
>         }
>
> Which would allow user structs to be extended, so I like that best.
>
> I feel like I'm dancing around a simpler, more elegant solution, but I can't quite grasp it.
>


January 09, 2003
"Burton Radons" <loth@users.sourceforge.net> escreveu na mensagem news:avimh0$vks$2@digitaldaemon.com...
> Walter wrote:
> > Ok, I'll have to think about that some more. I want to be careful adding
in
> > more . properties, as it could easilly get out of hand.
>
> We could entertain extensions:
>
>         extension FloatNumeric (type)
>         {
>             type sqrt () { return intrinsic.sqrt (*this); }
>         }
>
>         extension SignedNumeric (type)
>         {
>             static bit signable () { return true; }
>         }
>
>         extension UnsignedNumeric (type)
>         {
>             static bit signable () { return false; }
>         }
>
>         extension Numeric (type)
>         {
>             bit signed () { return *this < type.zero; }
>             int sign () { return signed () ? -1 : 1; }
>         }
>
>         extend FloatNumeric for float, double, extended, complex;
>         extend SignedNumeric for byte, short, int, long, float, double,
> extended, complex;
>         extend UnsignedNumeric for bit, ubyte, ushort, uint, ulong;
>         extend Numeric for ...;
>
>         bit.signable; /* Calls UnsignedNumeric.signable */
>
>         int x;
>
>         x.signed; /* Calls SignedNumeric.signed */
>
> Extending a type gives it these properties for the purpose of compilation - all static or final, any overlap is an error (except perhaps that typedef defines a new layer that allows overlapping any previous instantiations?  What scopes are used becomes an issue), no fields.  This doesn't handle instancing an extension for any type of array, but as it's easy to do so manually it's not so much a problem. Then again, being able to move everything into Phobos, including .sort, indexing, and resizing, would have some advantages.  How about:
>
>         instance ArraySortExtension (* []);
>
> The problem is that this becomes unimplementable:
>
>         extension ArrayIndexExtension (type)
>         {
>             XXX getitem (int index)
>             {
>                 assert (index > 0 && index < type.length);
>                 return type.data [index];
>             }
>         }
>
> So it could be:
>
>         extension ArrayIndexExtension (type [])
>         ...
>         instance ArraySortExtension (*);
>
> Or:
>
>         extension ArrayIndexExtension (type)
>         {
>             type.next getitem (int index)
>         }
>
> Which would allow user structs to be extended, so I like that best.
>
> I feel like I'm dancing around a simpler, more elegant solution, but I can't quite grasp it.
>

Hi,

    This could be used to add new methods to objects too, so we can define a
sqrt method, slices for collection types, etc.. We could even merge
extension and template semantics, allowing of safe templates to add methods
to objects:


template TQuantifiers(T : TIterable(T)) {
    /*quantifications like find, filter, any, all, etc.*/
}

extension ArrayIterable(T) {
    /* defines a iterator struct for arrays*/
}

instance TQuantifiers(int) using ArrayIterable(int);

if (array.find(&predicate)) {
    ...
}


    Leaving out all explicit instantiation verbosity of templates. Would be
really nice to extend the templates expressiveness.
    Current deimos implementation provides classes with Matrix semantics
instead of structs, because IMHO classes provide a better semantics for
defining true ADTs. But with extensions I could define all operations as
extensions of a matrix type provided by the user, so people who prefer
structs could use them and provide the correct extension/template instance
in their own module.
    I think this is the correct direction for us to follow.

    Best regards,
    Daniel Yokomiso.


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.435 / Virus Database: 244 - Release Date: 30/12/2002


January 09, 2003
Couldn't have said it better myself. Though I'd like to add that many, many applications have portions of them that require system programming features. The need to dip into assembler now and then is one of them.


January 09, 2003
"Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:ase4eq$4tk$1@digitaldaemon.com...
> I prefer to remove all primitives in the D standard, and have a bunch of classes with standardized semantics.

One difficulty with that approach is that the compiler will be unable to produce coherent error messages, sort of like what happens when you use C++ STL incorrectly. Build the basics into the compiler, such as strings, and it'll be a lot easier to develop user code.


January 09, 2003
"Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in message news:asi0nc$1v8i$1@digitaldaemon.com...
> You can't put a class on
> the stack, or embed a class directly in another class except by
inheritance.
> Seems a needless restriction.

The reason for that is to eliminate the need for copy constructors, assignment operator overloading, and the proposed C++ "move" constructors. Many C++ classes are dominated by such various bookkeeping functions that obscure the point of the class and leave many opportunities for bugs.

This is also why structs do not have constructors.


January 09, 2003
"Walter" <walter@digitalmars.com> escreveu na mensagem news:avktc3$28b7$2@digitaldaemon.com...
>
> "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:ase4eq$4tk$1@digitaldaemon.com...
> > I prefer to remove all primitives in the D standard, and have a bunch of classes with standardized semantics.
>
> One difficulty with that approach is that the compiler will be unable to produce coherent error messages, sort of like what happens when you use
C++
> STL incorrectly. Build the basics into the compiler, such as strings, and it'll be a lot easier to develop user code.
>
>

Which kinds of incoherent error messages we could get with a value class Int32 instead of a int primitive? Or an array template instead of a basic array? Standardized classes are better for understanding types and operations, an implementer could assume anything allowed by the spec in his implementation.


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.435 / Virus Database: 244 - Release Date: 30/12/2002