June 02, 2004
Walter wrote:

> In such cases, an auto class should fill the bill instead of a struct.

Can references to auto classes be handled (copied, used as argument, returned, etc.) at all? I have not tried it, but from what I understand, an auto-object would have to be bound to exactly one reference variable, otherwise, it will not be clear when it should be deleted.

Thinking about it, I realize, that I do not really understand auto variables at all: is it correct that only that object is deleted which is referenced the moment in which the variable goes out of scope? So, if I create an object of an auto class and then assign zero to the variable, the object will stay on the heap to be garbage-collected? So the "auto" keyword would not give you any security except for saving you the explicit "delete" at every exit point of the block?

One more reason to abolish the concept of auto-classes! Auto-variables are a nice convenience, but if they don't add any security that the object really is deleted, then auto-classes are a pure nuisance, restricting the use of a class without adding value in terms of security.
June 03, 2004
In article <c9k15j$10kr$1@digitaldaemon.com>, Norbert Nemec says...
>
>Kevin Bealer wrote:
>
>> 99% agreed, but objects that hold an open file, mmap, etc might want to at least handle the "I've been dupped" case, i.e. make a note not to close the file.
>
>There are two ways to interpret this statement:
>
>1. If you are talking about structs, then this approach would mean that you also need struct destructors. This again means lots of overhead and complications when copying around data (like for arguments, etc)
>
>2. If you are talking about classes, this may either mean
>   a) keeping track of references - again lots of overhead when copying
>      around
>   b) copying objects - in this case it is no problem keeping track of
>      copies. Every construction and destruction of an object goes along
>      with the call of constructors and destructors.

I would stipulate to classes.

Okay... I was actually thinking of manually calling "close()", but I thought that the .dup was provided as a "byte level copy" for all object types, but I just checked and you have to define a property if you want that on your own classes.

My bad.  My hypothetical "file" class could define ".dup" to do a "dup2()" on the file descriptor if necessary.

Kevin



June 04, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9la0f$2rpa$1@digitaldaemon.com...
> In the latest version I've actually removed the copy constructor and dup
from
> Int, so you can't deep copy it any more. I did this because you don't need
to
> deep copy it, ever, and I realized (in the end, after some prompting) that
the
> presence of those functions might mislead people into thinking
copy-by-value for
> this class did anything useful.

I've been thinking about the issue of BigInteger being implemented as a class, but desiring copy-by-value semantics. If you adopt the paradigm of copy-on-write for the internal array, wouldn't that achieve cbv semantics?


June 04, 2004
"Norbert Nemec" <Norbert.Nemec@gmx.de> wrote in message news:c9ldq4$39$1@digitaldaemon.com...
> Walter wrote:
>
> > In such cases, an auto class should fill the bill instead of a struct.
>
> Can references to auto classes be handled (copied, used as argument, returned, etc.) at all? I have not tried it, but from what I understand,
an
> auto-object would have to be bound to exactly one reference variable, otherwise, it will not be clear when it should be deleted.

An auto reference can be passed as a function argument.

> Thinking about it, I realize, that I do not really understand auto
variables
> at all: is it correct that only that object is deleted which is referenced the moment in which the variable goes out of scope?

Yes.

> So, if I create an
> object of an auto class and then assign zero to the variable, the object
> will stay on the heap to be garbage-collected? So the "auto" keyword would
> not give you any security except for saving you the explicit "delete" at
> every exit point of the block?

The compiler will insert a 'delete' on the reference at every exit point of the block, including exception unwinding. However, if you're clever and manage to have a copy of that reference 'leak' beyond the close of the local scope, it will be pointing to deleted data, and will cause a crash.

> One more reason to abolish the concept of auto-classes! Auto-variables are
a
> nice convenience, but if they don't add any security that the object
really
> is deleted, then auto-classes are a pure nuisance, restricting the use of
a
> class without adding value in terms of security.

They're just as secure as class objects on the stack in C++ are, in fact, even more secure.


June 04, 2004
In article <c9p8hq$2ja9$1@digitaldaemon.com>, Walter says...
>
>
>I've been thinking about the issue of BigInteger being implemented as a class, but desiring copy-by-value semantics. If you adopt the paradigm of copy-on-write for the internal array, wouldn't that achieve cbv semantics?

Yes, you're probably right. I've been thinking the same thing. But I wouldn't have agreed with you until a few days' ago.

You see, until a few days' ago, I would have considered that it *HAD* to be a class, because it is _unbelievably_ important to me that I am able to wipe memory after use (though only in a version(Secure) build, obviously - no need to give that performance hit to those who don't need it). Until a few days ago, I believed that having a destructor was the way to achieve that.

But things have changed. You've told me that a destructor need not run. (In which case, I still don't see the point of allowing them! I'd still like for you to expand on this)

Now that I know that, the decision to use a class becomes less clear. It is apparent that in the future I will have to write my own secure memory handler. That's ok - I've stuff like that before. But given that such a rewrite is on the cards, there is no longer any reason to keep it as a class. So yes, I could fairly easily change it to a struct - and this would have the added benefit of allowing me to implement +=, -=, ++ and so forth.

But, Walter - structs don't have constructors, remember? So, that would leave me with no choice but to overload static opCall() to achieve the same effect. And while this would have the (rather nice) benefit of causing the word "new" to disappear from people's source code in relevant places - I rather thought you didn't like this approach. I mean, we're ending up with SOME things getting constructed with the syntax A(), OTHER things getting constructed with new A(), and YET MORE things offering both options. This is surely going to be confusing to people. Perhaps you might consider adopting my suggestion of making the keyword "new" optional in all cases, merging the functions of this() and static opCall(), and allowing structs to have constructors?

Jill


June 04, 2004
what if you have a struct holding an item it was templatized on

struct holder(T){
T value;
holder opAdd(...) {...}
}
then each time you assign to the struct you have to do some sort of templatized
copy of it that's specialized for each kind of T it can hold
perhaps it holds a capital Int, perhaps some other class that needs some
duplication... perhaps a long or an int or float.
suddenly you need a million different specializations to construct the class

template Constructor(T) {
T  makeSomething(T inp) {
return new T(inp);
}
}
template Constructor (T:mystruct) {
T makeSomething(T inp) {
return T(inp);
}
}
template Constructor (T:float) {
float makeSoemthing (float inp) {
return inp;
}
...
and then the list goes on for all floats, ints, structs you might use...
each time a new primitive type is added you have to update your template
specializations.

is there any way we could templatize on construction mechanism
or on whether it's a class
or on whether it's a reference.

Another problem I'm facing is that my BigRational struct cannot have valid
values initially: it's faced with 2 null Integers, because a struct cannot be
assigned a class in its initial assignment phase.
I would enjoy having some sort of constructor run when the struct was created so
I could make  the numerator a new Int(0) and the denominator a new Int(1);
there's no no way to do this using the
struct Rational (T){
T numerator= ...;
T denom = ...;
..
};
it has been the source of a number of bugs... especially in the case that T
happens to be a long--because since it has to work for Int as well as Long, the
denominator gets assigned an (illegal) value of zero since I cannot assign the
denom to a default value of Constructor!(T).makeValue(1);

any ideas for a good solution to this y'all? it would be nice if the language offered me something like this. it seems as if structs are simply incomplete without a way to set a reasonable default value that the compiler does not deign to see as a "constant value"

In article <c9p8hq$2ja9$1@digitaldaemon.com>, Walter says...
>
>
>"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9la0f$2rpa$1@digitaldaemon.com...
>> In the latest version I've actually removed the copy constructor and dup
>from
>> Int, so you can't deep copy it any more. I did this because you don't need
>to
>> deep copy it, ever, and I realized (in the end, after some prompting) that
>the
>> presence of those functions might mislead people into thinking
>copy-by-value for
>> this class did anything useful.
>
>I've been thinking about the issue of BigInteger being implemented as a class, but desiring copy-by-value semantics. If you adopt the paradigm of copy-on-write for the internal array, wouldn't that achieve cbv semantics?
>
>


June 04, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9p9ut$2lbr$1@digitaldaemon.com...
> In article <c9p8hq$2ja9$1@digitaldaemon.com>, Walter says...
> >
> >
> >I've been thinking about the issue of BigInteger being implemented as a class, but desiring copy-by-value semantics. If you adopt the paradigm of copy-on-write for the internal array, wouldn't that achieve cbv semantics?
>
> Yes, you're probably right. I've been thinking the same thing. But I wouldn't have agreed with you until a few days' ago.
>
> You see, until a few days' ago, I would have considered that it *HAD* to be a class, because it is _unbelievably_ important to me that I am able to wipe memory after use (though only in a version(Secure) build, obviously - no need
to
> give that performance hit to those who don't need it). Until a few days ago, I believed that having a destructor was the way to achieve that.
>
> But things have changed. You've told me that a destructor need not run. (In which case, I still don't see the point of allowing them! I'd still like for
you
> to expand on this)

If your class is auto, then it will.

However, auto currently has quite a restrictive use. Although that's likely to be relaxed in the future, it still may not be as general purpose as you require.



June 04, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9p9ut$2lbr$1@digitaldaemon.com...
> You see, until a few days' ago, I would have considered that it *HAD* to
be a
> class, because it is _unbelievably_ important to me that I am able to wipe
> memory after use (though only in a version(Secure) build, obviously - no
need to
> give that performance hit to those who don't need it). Until a few days
ago, I
> believed that having a destructor was the way to achieve that.
>
> But things have changed. You've told me that a destructor need not run.
(In
> which case, I still don't see the point of allowing them! I'd still like
for you
> to expand on this)

Lazy destruction, which happens in gc, is pretty much useless for things that *must* be deleted. A more aggressive scheme is required, such as I outlined before. But lazy destructors still are very handy for debugging and logging purposes.


> But, Walter - structs don't have constructors, remember? So, that would
leave me
> with no choice but to overload static opCall() to achieve the same effect.
And
> while this would have the (rather nice) benefit of causing the word "new"
to
> disappear from people's source code in relevant places - I rather thought
you
> didn't like this approach. I mean, we're ending up with SOME things
getting
> constructed with the syntax A(), OTHER things getting constructed with new
A(),
> and YET MORE things offering both options. This is surely going to be
confusing
> to people. Perhaps you might consider adopting my suggestion of making the keyword "new" optional in all cases, merging the functions of this() and
static
> opCall(), and allowing structs to have constructors?

The trouble with allowing structs to have constructors, is then there's the issue of overloadable assignment operators and the default copy constructor, both of which I avoid. Then if there are constructors, why not destructors, and the whole complicated C++ mess appears (think what happens when you pass a struct as a function parameter).

If everyone would be satisfied with 1) no destructors and 2) bit copies for assignment and copy constructor and 3) no RAII for structs, I would be much more amenable to adding them in <g>.


June 04, 2004
In article <c9qiqn$1i01$1@digitaldaemon.com>, Walter says...
>
>The trouble with allowing structs to have constructors, is then there's the issue of overloadable assignment operators and the default copy constructor, both of which I avoid. Then if there are constructors, why not destructors, and the whole complicated C++ mess appears (think what happens when you pass a struct as a function parameter).

Forgive me - I don't understand the problem. The way I see it, a struct constructor would just be an initialization function. It would function pretty much exactly like static opCall() does now.

Overloadable assignment operators? You're talking about the much-discussed opAssign(), right? Ok - I *DO* see the problem. (I get there in the end). This is about parameter passing, right? If you pass a struct by value to a function, anything more complex than bit-copying is a pain in the neck. So you don't want opAssign(). Is that the problem?.


>If everyone would be satisfied with 1) no destructors and 2) bit copies for assignment and copy constructor and 3) no RAII for structs, I would be much more amenable to adding them in <g>.

I don't have a problem with that at all. Structs should not have destructors, and I can think of a lot of reasons to justify that, but I don't see a problem with CONstructors. Like I said, people are using static opCall() for that very purpose right now, just to overcome that limitation (with the result of a nicer syntax even).

And of course, if you ban destructors, then you also implicitly ban RAII. Goes without saying.

Well, the way I see it is, if you give us constructors for structs, nobody is going to complain. (They might want more, but that's irrelevant).

But wait - there's still something I'm not getting. Even if you do provide constructors for structs, why should anyone bother with them? What's the advantage over static opCall()? I mean, consider the following two lines:

>       A a = A(parameters);
>       A a = new A(parameters);

There are undoubtedly people who are going to prefer the first syntex. (I'm one of them). Now I'm starting to wonder why I should bother with constructors even for classes, when I can get the nicer syntax for those, too, with static opCall() instead.

What's worse, though, is that it is currently possible for people to implement both syntaxes in a class AND HAVE THEM DO COMPLETELY DIFFERENT THINGS. I think this is a dangerous idea, and that the two functions really should be merged into one, so that "new" then becomes optional at the whim of the caller, instead of (as now) optional at the whim of the class designer.

I hope this helps. I'm not just nitpicking because I don't like "new".

Jill


June 04, 2004
In article <c9qkjv$1ko4$1@digitaldaemon.com>, Arcane Jill says... ..
>What's worse, though, is that it is currently possible for people to implement both syntaxes in a class AND HAVE THEM DO COMPLETELY DIFFERENT THINGS. I think this is a dangerous idea, and that the two functions really should be merged into one, so that "new" then becomes optional at the whim of the caller, instead of (as now) optional at the whim of the class designer.
>
>I hope this helps. I'm not just nitpicking because I don't like "new".
>
>Jill

Using opCall for non-new applications is only confusing if you typically overload the opCall to mean "new".  The normal use of opCall (in my opinion) is as a "functor", i.e. "operator()" in C++.  Suppose I have a function:

flip(int a)
{
..
}

..and code that calls it.  I can make it into an object, which is then used as a function, but also holds state and may have other methods.

This ability to tack state, ie member vars, onto a function by converting into a class and using it as a functor is useful to a lot of folks.  The C++ STL for example is designed to allow functors in almost all places where a function would otherwise be used.  Your opCall syntax conflicts with that idiom.

If the conflict between syntaxes is dangerous, then maybe you should switch to the side of the road that (almost) everyone else is driving on?

Kevin