Jump to page: 1 2 3
Thread overview
Concrete Types/Argument Passing
Sep 03, 2001
Rui Ferreira
Sep 03, 2001
Axel Kittenberger
Sep 03, 2001
Walter
Sep 03, 2001
Walter
Sep 03, 2001
Axel Kittenberger
Sep 03, 2001
Walter
Sep 04, 2001
Axel Kittenberger
Sep 05, 2001
Walter
Sep 06, 2001
Axel Kittenberger
Sep 07, 2001
Walter
Sep 07, 2001
Axel Kittenberger
Sep 07, 2001
Axel Kittenberger
Sep 09, 2001
Walter
Sep 05, 2001
Axel Kittenberger
Sep 04, 2001
Dan Hursh
Sep 04, 2001
Rui Ferreira
Sep 05, 2001
Dan Hursh
Sep 05, 2001
Rui Ferreira
Sep 04, 2001
Rui Ferreira
Sep 04, 2001
Walter
September 03, 2001
Interesting language spec. Property fields and the super() constructor scheme are two things that should have been in c++ for a long time now.

But I'm wondering, what is D's support for concrete classes. I can see structs are supported but are member functions allowed on them ? What about derivation of concrete classes, is there any ?

Do not underestimate the need for concrete classes. I can see some threads on operator overloading but if you think about it the real benefit for such sugary comes precisely from the use of concrete classes to model small conceptual models.

Class trees are a totally different beast to me. If in D every function is virtual by default, do I need to use a vtable for a vector3f class ? That sounds overkill, a simple struct would do. But C structs aren't as expressive as a c++ non virtual class can be. It lacks members functions and operator overloading.

I like to see that function arguments semantics are clean for once. The 'const' keyword usage on c++ is mostly a cancer, born from the need to apply read permissions to arguments, so we can pass large enough objects without performance degradation and the assurance it will not change value. Quite the hack.

The 'in', 'out' and 'inout' keyword are just the right way to do the argument passing, but what do these keywords mean when applied to a struct ? Does this mean structs are ALWAYS by value by default ? That also sounds overkill. I've always thought that this should be addressed by the language itself.

Compilers, and Visual Studio in particular is keen to make a memcpy of a
struct passed by value if it is more than 4 words long, if not, it will use
the registers to do the grunt work. Now, for me this is the key point to be
on the lookout to decide if a class should be passed by value or by
reference. Most of the time there is no need to change the value, this is
the most useful and frequent usage of an argument, if there is a need then
it will act as a local variable. Maybe that can happen to an int or two that
goes into a for loop, but not needed on most of the concrete "types" I
know -- They really shouldn't be called classes.

So I think this should be taken into account by the compiler itself. If a copy is expensive for any given argument the compiler will use by reference passing to optimize the access if and only if the argument IS ONLY USED ON CONST SEMANTICS, that is if the function does not change the argument then the implementation can use a pointer safely to make an efficient 'in' argument. If the function does change the value, then it will use the copy by value instead to preserve local usage.

Another solution : Perhaps change to 'in' values shouldn't be allowed at all and the user should be forced to copy to local variables if there is any need to use a temporary storage for 'in' arguments. This doesn't sound impressively limited to me and it can probably be considered good code design.

Standard classes will be passed by reference as always. OOP demands it, they are not stack objects at all. But concrete types are.... they are different. It would be a good thing to divide and enforce these two concepts separately.

Maybe we can have class {} with all the wonders of vtables, and type {} or an enhanced struct {} to handle all the necessities of a good concrete type. Operator overloading only makes good sense on them, so maybe they should be banned from standard classes altogether and take advantage of the vtable absence to implement some serious operator overloading like handle multiple sums of vector the correct way or to avoid spurious temporaries.

This would be indeed a language I would like to code in.

-Rui Ferreira



September 03, 2001
Thats the reason why I in example decided -not- to use 'in', 'out' and 'thru'. What does 'in' to an object type mean? can we change it fields? Does the caller feel that? Can we members of the object that change it fields? Okay on an 'out' we can change the "pointer" to the class itself and the callers also receives a new pointer, but actually there are many different levels between in and out. 100% reference the callee can change the actual value of it, in the next 'itermediate' level it can change the fields of the object, but not the pointer to itself, and then the lowest level with 'const' in C++ grammar it can neither change the object nor the pointer to it. How does this fit to 'in', 'out', 'thru'?

Okay there are even more finer access levels if you've an an array of objects. The whole array root pointer itself may be changed, the content pointers of the  array may be changed, only the object fields may be changed, nothing at all may be changed.

A lot of people writing userspace applications on pc's, say let's scrap that const, or simply don't bother using it correctly. However on embedded systems you're always lurking to put as much into ROM instead of RAM as possible, and that means 'const'. Beside normal programmer idioty security correct const decleartations provides a lot of hints for the optimizer, so (ofcourse in my personal impression only) leaving it away or not handling it correctly is reducing yourself from to professional programming language to a teaching language for scools, or as better script language.

- Axel
September 03, 2001
Rui Ferreira wrote in message <9mvvkn$1gd8$1@digitaldaemon.com>...
>But I'm wondering, what is D's support for concrete classes. I can see structs are supported but are member functions allowed on them ?

No. Structs are simply C'ish aggregations.

> What about
>derivation of concrete classes, is there any ?

What's a "concrete" class?

>Class trees are a totally different beast to me. If in D every function is virtual by default, do I need to use a vtable for a vector3f class ? That sounds overkill, a simple struct would do. But C structs aren't as expressive as a c++ non virtual class can be. It lacks members functions
and
>operator overloading.


The vtable overhead is slight, and I think a reasonable tradeoff.

>I like to see that function arguments semantics are clean for once. The 'const' keyword usage on c++ is mostly a cancer, born from the need to
apply
>read permissions to arguments, so we can pass large enough objects without performance degradation and the assurance it will not change value. Quite the hack.

D gets rid of "const" as part of the typing system, although you can still declare constants.


>The 'in', 'out' and 'inout' keyword are just the right way to do the argument passing, but what do these keywords mean when applied to a struct
?
>Does this mean structs are ALWAYS by value by default ? That also sounds overkill. I've always thought that this should be addressed by the language itself.


Structs are by value, and classes are by reference. 'out' and 'inout' parameters are always passed by reference.




September 03, 2001
Axel Kittenberger wrote in message <9n015m$1h3u$1@digitaldaemon.com>...
>Beside normal programmer idioty security
>correct const decleartations provides a lot of hints for the optimizer, so
>(ofcourse in my personal impression only) leaving it away or not handling
>it correctly is reducing yourself from to professional programming language
>to a teaching language for scools, or as better script language.

In actual practice, const doesn't help the optimizer much. Too many programs cast away const, plus some other subtleties of it, conspire to make it worthless.

Hence, in D, const is not a type modifier, but a storage class. A const storage class means the declarations in it can be put in ROM, the compiler can fold multiple instances together, and the compiler can do constant folding on them.


September 03, 2001
> What's a "concrete" class?

When I understood corectly he means classes that are normally handled like they would be aggregate type, 'Point' would be a classic example, in graphic code the Point class is often used in a way it feels as it just a normal primitive datatype.

> The vtable overhead is slight, and I think a reasonable tradeoff.

So you're defintly targeting to be a userspace application only? In my eyes these tougher uses like emmbeded (os-less) applications or kernelspace were the main benefit the industry saw in C over Pascal (in the 90ies) and led over the years  to displacement of Pascal also in userspace, but well this of course a subjective view only.

> D gets rid of "const" as part of the typing system, although you can still declare constants.

but not constant strings, or? I'm a little confused, say a function takes 'char *' as in parameter, 'in' on arrays mean we cannot change it's values it would be 'const char *' in C speak. Okay so array I want to modify are 'out' so it would be normal 'char *' in C speak. Now how do I secify a function which returns a pointer to an string as out parameter? Like strtol() in example. It might just be that I did not understand things correctly as I never used Eiffel or where the in/out/thru paradigm came frome.

Hmmm, could you maybe point out how in in/out/inout way following classical C functions would be coded?

size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
long int strtol(const char *nptr, char **endptr, int base);

I think these examples suite well to be a pretty universal answer :o) (well for arrays at least)

- Axel
September 03, 2001
Axel Kittenberger wrote in message <9n0n3a$1v21$1@digitaldaemon.com>...
>>So you're defintly targeting to be a userspace application only?

I don't understand why you conclude that from structs not having vtables and classes having.

>>but not constant strings, or?

Sure:

    const char*p = "hello";


> I'm a little confused, say a function takes
'char *' as in parameter, 'in' on arrays mean we cannot change it's values it would be 'const char *' in C speak.

Not really. The in only applies to what is passed on the stack, which would be the pointer, not the data.

> Okay so array I want to modify are
'out' so it would be normal 'char *' in C speak. Now how do I secify a function which returns a pointer to an string as out parameter? Like strtol() in example.

void func(out char* foo);

>>Hmmm, could you maybe point out how in in/out/inout way following
classical
C functions would be coded?
size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
long int strtol(const char *nptr, char **endptr, int base);
I think these examples suite well to be a pretty universal answer :o)
(well for arrays at least)

size_t strlen(char* s);
char* strcpy(char* dest, char* src);
int strtol(char* nptr, out char* endptr, in int base);





September 04, 2001
Walter wrote:
> 
> Rui Ferreira wrote in message <9mvvkn$1gd8$1@digitaldaemon.com>...
> >But I'm wondering, what is D's support for concrete classes. I can see structs are supported but are member functions allowed on them ?
> 
> No. Structs are simply C'ish aggregations.
> 
> > What about
> >derivation of concrete classes, is there any ?
> 
> What's a "concrete" class?

From Stroustrup's "The C++ Programming Language"

	The intention of a concrete type is to do a single, relatively small
thing well and efficiently.  It is not usually the aim to provide the
user with facilities to modify the behavior of a concrete type.  In
particular, concrete type are not intended to display polymorphic
behavior.
	If you don't like some detail of a concrete type, you build a new one
with the desired behavior.  If you want to "reuse" a concrete type, you
use it in the implementation of your new type exactly as you would have
used an int.



	He gives a number of examples elsewhere in the book of concrete type
like date, vector, BCD characters, (value, unit) pairs, scaled fixed
point number, etc.  I've always consider concrete type to be one of
those things taught as a discipline, but not really anything you gave
thought to.
	I'm glad Rui spoke up!  I never considered this.  Perhaps, if D could
support a form of concrete type, it could control the abuse of
overloads.  It would also help cut down on virtual calls when they are
truly over kill.  How about this?


1)  Concrete types are a form of data aggregation like a C structs, but with methods associated.  (I would like to say they can be passed in place of C structs to make writing OpenGL wrappers a little friendlier. Would that be too difficult?)

2)  They can be declared locally.

3)  They cannot be inherited from.  They cannot inherit from other types.  There is nothing polymorphic about them, hence method are not virtual.

4)  They can have constructors and a destructor.  There is no guarantee that the destructor will be run immediately when a variable goes out of scope, but it will be run.  (I don't want to go to the extreme of saying they can't allocate resources.)

5)  I think we might want to say they can have private/public style protection on members, since you probably would want people messing with the internal of some Date implementations.  The same might be true of other types.

6)  They are the only user defined types that support any form of operator overloading.  (This is assuming that we can find a form of operator overloading that isn't too much trouble.)


	It would help in library implementations of simple types, and it would
allow user defined vector math type that will be useful in tight loops.
I care about that.  :-)  I do think it could lead to a useful, safe
compromise.  It could also make for a nicer standard library.
	I'm not sure if there should be any consideration with regard to
potential problems with generic programming (templates), if D ever
supports something like that.  Also, some folks might want to see a way
to interface such types with switch.  Since we probably won't have a way
to declare literal, this is probably unreasonable.
	I do know that I don't like concrete as a keyword.  We'd need a better
name for it.  I think it should be usable anywhere a struct is, but I
get the gut feeling that it should be separate from a struct, but I
don't have a good reason for that.

Thoughts?
Dan
September 04, 2001
> size_t strlen(char* s);
> char* strcpy(char* dest, char* src);

Okay then there is nothing that checks for const violations?
like mismatched arguments will result for you into a runtime segfault:

char *foo;
strcpy("hallo", foo);

from where a normal C comiler is perfectly able to warn/error for.

- Axel
September 04, 2001
>> No. Structs are simply C'ish aggregations.

And why should they be in D ? Public data aggregation is against the very principle of information hiding. You provide those wonderful property fields and yet you preclude them for use in your basic data structure. C structs are your primary means of a program assembly, a composite type that acquires a new meaning once it is defined, it is a piece of my logical program, one that maps directly to the hardware.

Your fundamental data structure is the memory block not the class.

Concrete types take this a step further by using data hiding to ensure a consistent view of whatever concept we're supposed to be modeling. A unit of knowledge if you will.

I do not see any benefit to introduce vtables and polymorphism into a otherwise, by definition; simple and to the point data structure.

>> What's a "concrete" class?

Dan below gave some good examples.

>> The vtable overhead is slight, and I think a reasonable tradeoff.

That doesn't sound 0-overhead to me.

I consistently use concrete types, both for storage and as local variables to allow local computation of temporaries, mostly as arguments to a function. These are more common that you think. Once you acknowledge how your building blocks of data work you will use them to forward information to a function directly instead of separating the components to pass them to a function. That's old school C -  a jumble of arguments of diverse nature. Not OOP - 2,3 arguments of concrete types.

The way you handle your local variables should be clear and with well defined semantics. Basic types are not just your stock integer and floating point numbers. That is just the foundation layer, nothing else.

Judging by your statement than you might as well retrofit 'int' with a vtable! The point is -- concrete types are exactly like them, whatever you call them, they are data types.

>> D gets rid of "const" as part of the typing system, although you can
still declare constants.

Amen to that.

>> Structs are by value, and classes are by reference. 'out' and 'inout'
parameters are always passed by reference.

Why structs by value only, does this mean that, if I have a large enough block of information it will not be accessed by indirection ?

D wants to restrict the usage of pointers. That doesn't mean to lose them on your implementation.

I want to access memory not copy it.

-Rui Ferreira



September 04, 2001
>> I've always consider concrete type to be one of those things taught as a
discipline, but not really anything you gave
thought to.

Perhaps if you are only using Struct as a means of implementation to an interface you should forgo discipline. In fact, come to think of it, I think this is Walter's reasoning behind the current C Structs usage.

The thing is that concrete types are much more than an implementation detail -- although they can be, and with organized results.  They are more usefully used directly, exposing their public interface to provide a memory block on the form of a data model.

>> 3)  They cannot be inherited from

Well, I have found some uses to inheritance, here it mostly serves the purpose of code reuse.

A pragmatic role I guess, but not terribly important.

>> They can have constructors and a destructor.  There is no guarantee that
the destructor will be run immediately when a >>variable goes out of scope, but it will be run.  (I don't want to go to the extreme of saying they can't allocate >>resources.)

Yes, perhaps we can make some compromises regarding c++ here. A destructor is generally used on a concrete type to provide the "resource acquisition is initialization" paradigm.

I am used to this, so I'm biased, but we may find a better alternative.

I am not experienced enough to know if the 'finally' clause is a good one, but the auto-magical properties of a local concrete "handle" that releases its resources at the end of a block are very alluring.

---

Regarding the rest, data hiding with protection keywords is a must, and yes, operator overloading only on these types of data structures is a very good "force the users to use it" design compromise.

>>and it would allow user defined vector math type that will be useful in
tight loops.

And you know we need them... :]

-Rui Ferreira



« First   ‹ Prev
1 2 3