View mode: basic / threaded / horizontal-split · Log in · Help
December 09, 2006
Re: DMD 0.177 release
Chris Nicholson-Sauls wrote:
> Burton Radons wrote:
>> - Casting a value v to a struct S is now rewritten as S(v).
>>
>> I'm 100% against this. This is what C++ does, and it conflates 
>> construction and casting; with some VERY simple examples (such as the 
>> first one we think of when we think of additional types, bignums), 
>> there's an ambiguous conflict because one of the constructors should 
>> have a count of how many digits you want - and one of the casters 
>> takes an integer for a value to initialise to. My solution at the time 
>> was to add a dummy argument to the constructor so that the compiler 
>> didn't try to match them, which is absurd.
>>
>> I don't know why C++ was designed like this when its error was so 
>> blatant, but D doesn't need to replicate its mistake. "S.opCastFrom 
>> (v)" please, except that it shouldn't be static either.
> 
> Essentially agreed.  I'm not entirely fond of the "silent" new opAssign 
> either, because of the visual ambiguity it can lead to.  (Its worth 
> noting that, even though '='->opAssign is listed in the spec, the bottom 
> of the same page still lists '=' among the operators which will not be 
> given overloads.  Hm.)

Same.  And frankly, I'm having trouble coming up with a practical use 
for the new opAssign.  For one thing, it isn't commutative:

    auto c = new MyClass;
    int  i = 5;
    c = i; // will work
    i = c; // won't work

And now structs have an opAssign but still have binary copy semantics 
and no ctor/dtor support.  The result is totally confusing.  What was 
the use case for this feature?


Sean
December 09, 2006
Re: DMD 0.177 release
Jarrett Billingsley wrote:
> "Walter Bright" <newshound@digitalmars.com> wrote in message 
> news:ele2k9$2hr5$1@digitaldaemon.com...
> 
>>More ABI changes, and implicit [] => * no longer allowed.
>>
>>http://www.digitalmars.com/d/changelog.html
>>
>>http://ftp.digitalmars.com/dmd.175.zip
> 
> 
> No offense, but would it honestly kill you to allow ctors in structs?  We've 
> been using static opCall as a _workaround_ for the lack of struct ctors, and 
> making it part of the language doesn't really seem to be addressing the 
> problem.  That, and it doesn't make any sense that classes use "this()" and 
> structs use "static S opCall()".  We're starting to get into "overloading 
> indexing in C++" territory.
> 
> That, and which would be more efficient?  The static opCall needs to return 
> an instance of the struct on the stack, which could be very inefficient for 
> large structs.  With a true ctor, the struct is passed by reference to the 
> ctor and has its fields set directly.
> 
> And I also can't figure out how to make the implicit opCall work with more 
> than one parameter.  :P
> 
> I'm also a little wary about opAssign.  Not that I don't find it useful, 
> just that you've been vehemently opposed to overloading it in D for how many 
> years, and three weeks before 1.0 you reverse your opinion.  What does that 
> mean?
> 

The thing with opAssign, I realised after reading the spec, is that it 
explicitly doesn't allow copy assignment. This reduces it from the level 
of a powerful feature to a mere toy, or at most a form of implicit casting.

Assigning one struct to another still guarantees a bitwise copy, and 
reference assignment for class instances cannot be stepped on. This 
removes essentially all of the danger that opAssign might have introduced.

> But complaints aside, thanks for removing the []=>* implicit cast and the 
> bugfixes.  Man, this last month has been an exciting time for D :) 
> 
> 


-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://pyd.dsource.org
December 09, 2006
Re: DMD 0.177 release
Sean Kelly schrieb:
> Chris Nicholson-Sauls wrote:
>> Burton Radons wrote:
>>> - Casting a value v to a struct S is now rewritten as S(v).
>>>
>>> I'm 100% against this. This is what C++ does, and it conflates 
>>> construction and casting; with some VERY simple examples (such as the 
>>> first one we think of when we think of additional types, bignums), 
>>> there's an ambiguous conflict because one of the constructors should 
>>> have a count of how many digits you want - and one of the casters 
>>> takes an integer for a value to initialise to. My solution at the 
>>> time was to add a dummy argument to the constructor so that the 
>>> compiler didn't try to match them, which is absurd.
>>>
>>> I don't know why C++ was designed like this when its error was so 
>>> blatant, but D doesn't need to replicate its mistake. "S.opCastFrom 
>>> (v)" please, except that it shouldn't be static either.
>>
>> Essentially agreed.  I'm not entirely fond of the "silent" new 
>> opAssign either, because of the visual ambiguity it can lead to.  (Its 
>> worth noting that, even though '='->opAssign is listed in the spec, 
>> the bottom of the same page still lists '=' among the operators which 
>> will not be given overloads.  Hm.)
> 
> Same.  And frankly, I'm having trouble coming up with a practical use 
> for the new opAssign.  For one thing, it isn't commutative:
> 
>     auto c = new MyClass;
>     int  i = 5;
>     c = i; // will work
>     i = c; // won't work
> 
> And now structs have an opAssign but still have binary copy semantics 
> and no ctor/dtor support.  The result is totally confusing.  What was 
> the use case for this feature?
> 
> 
> Sean

Why are opAssign overloads possible for structs? They lead to a bad 
style like the example above: It's possible to assign a primitive type 
to an aggregate type, without showing what is done in the code.
December 09, 2006
Re: DMD 0.177 release
Walter Bright wrote:

> More ABI changes, and implicit [] => * no longer allowed.
> 
> http://www.digitalmars.com/d/changelog.html
> 
> http://ftp.digitalmars.com/dmd.175.zip


opAssing not mentioned here, but anyway I like what I have read in Docs!

Finally I can use more user friendly and compact syntax for assigning values
to Any
(http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D.announce&artnum=4827):

auto v=new Any;

Was:
v.assign(5);

Now:
v=5;

Very good syntax for this kind of container! I just miss templatized
constructors and following will be available:

void varFunc(Any[] arr ...) {
       foreach(v; arr) {
               writefln(v.type);
       }
}

void main() {
       bool test;
#       varFunc(new Any(5), new Any("tekst"[]), new Any(&variadicFunction));
#       varFunc(new Any(5.6), new Any(&test));
}

(Currently it is necessary to write:
# varFunc((new Any).assign(5.6), (new Any).assign(&test));
)


I will send updated version of Any soon...

-- 
Regards
Marcin Kuszczak
(Aarti_pl)
December 09, 2006
Re: DMD 0.177 release
Jarrett Billingsley wrote:
> No offense, but would it honestly kill you to allow ctors in structs?  We've 
> been using static opCall as a _workaround_ for the lack of struct ctors, and 
> making it part of the language doesn't really seem to be addressing the 
> problem.  That, and it doesn't make any sense that classes use "this()" and 
> structs use "static S opCall()".  We're starting to get into "overloading 
> indexing in C++" territory.

It turns out that static opCall() and this() are equivalent. C++ has 
some obscure rules to try to disambiguate them. I wished to avoid that 
problem, and since static opCall() is routinely in use, picked them.

> That, and which would be more efficient?  The static opCall needs to return 
> an instance of the struct on the stack, which could be very inefficient for 
> large structs.  With a true ctor, the struct is passed by reference to the 
> ctor and has its fields set directly.

The optimizer removes the redundant copy, and builds the result directly 
into the target.

> And I also can't figure out how to make the implicit opCall work with more 
> than one parameter.  :P

S(1,2,3)

> I'm also a little wary about opAssign.  Not that I don't find it useful, 
> just that you've been vehemently opposed to overloading it in D for how many 
> years, and three weeks before 1.0 you reverse your opinion.  What does that 
> mean?

The problem I have, and still have, is the identity assignment. This is 
specifically disallowed with opAssign. I can go into the reasons why if 
you like.

Having opAssign for foreign types turns out to be needed for things 
like, say I want to build a ranged integer. This is an integer that can 
only have values between m and n. Without opAssign, I'd have to use a 
property:
	RangedInt!(m,n) r;
	r.value = 6;
It's just not right.

> But complaints aside, thanks for removing the []=>* implicit cast and the 
> bugfixes.  Man, this last month has been an exciting time for D :) 

For me as well!
December 09, 2006
Re: DMD 0.177 release
Chris Miller wrote:
> On Sat, 09 Dec 2006 13:59:24 -0500, Walter Bright 
> <newshound@digitalmars.com> wrote:
> 
>> Chris Miller wrote:
>>> Allow static opAssign to return an instance of the class that will be 
>>> assigned to the lvalue:
>>
>> This wasn't done because there are several use cases where you 
>> wouldn't want to erase all previous contents of the struct being 
>> assigned to.
> 
> But if it's optional it's up to the struct writer to use void as the 
> return or not.

I don't think that'll work. He'll wind up being forced to set all the 
fields.
December 09, 2006
Re: DMD 0.177 release
"Walter Bright" <newshound@digitalmars.com> wrote in message 
news:elf9mn$snp$1@digitaldaemon.com...

> It turns out that static opCall() and this() are equivalent. C++ has some 
> obscure rules to try to disambiguate them. I wished to avoid that problem, 
> and since static opCall() is routinely in use, picked them.

For classes they're not.  Why should structs be any different?  And even if 
static opCalls are routinely in use, are they the best solution?

And are they _really_ equivalent?  Where's the 'this' pointer in a static 
opCall()?

> The optimizer removes the redundant copy, and builds the result directly 
> into the target.

Wouldn't it be easier to just have ctors, so implementations don't have to 
worry about writing an optimizer just to support this behavior?

>> And I also can't figure out how to make the implicit opCall work with 
>> more than one parameter.  :P
>
> S(1,2,3)

Oh.  I was thinking more along the lines of being able to do "S s(1, 2, 
3);".

> The problem I have, and still have, is the identity assignment. This is 
> specifically disallowed with opAssign. I can go into the reasons why if 
> you like.
>
> Having opAssign for foreign types turns out to be needed for things like, 
> say I want to build a ranged integer. This is an integer that can only 
> have values between m and n. Without opAssign, I'd have to use a property:
> RangedInt!(m,n) r;
> r.value = 6;
> It's just not right.

That makes sense.  It gives the utility of opAssign in most cases without 
the scary stuff.

Though as was mentioned elsewhere, it's not commutative, so it's still not 
possible to do

RangedInt!(m, n) r;
r = 5;
int x = r; // error

:/

>> But complaints aside, thanks for removing the []=>* implicit cast and the 
>> bugfixes.  Man, this last month has been an exciting time for D :)
>
> For me as well!
December 09, 2006
Re: DMD 0.177 release
Walter Bright wrote:
> Jarrett Billingsley wrote:
>> No offense, but would it honestly kill you to allow ctors in structs?  
>> We've been using static opCall as a _workaround_ for the lack of 
>> struct ctors, and making it part of the language doesn't really seem 
>> to be addressing the problem.  That, and it doesn't make any sense 
>> that classes use "this()" and structs use "static S opCall()".  We're 
>> starting to get into "overloading indexing in C++" territory.
> 
> It turns out that static opCall() and this() are equivalent. C++ has 
> some obscure rules to try to disambiguate them. I wished to avoid that 
> problem, and since static opCall() is routinely in use, picked them.

Just because someone at some time in the distant pass realized that 
opCall() simulates constructor-like behavior, it doesn't make it 'ok'; 
it makes it 'an ok work around'.

Think back over the last year.. how many people have asked how to create 
a constructor for structs?  How much you wanna bet none of them would 
have had to ask if 'this' wasn't misspelled as 'opCall'?

Since the desired behavior is construction, let's stop kidding ourselves 
and actually give structs both the behavior and the syntax of 
construction, please?  And while you're in there.. how about destruction 
and RAII?  I guess I'm in the camp that would like to see structs be 
closer to classes but am ok with them not supporting inheritance and 
other features that lead to vtables.

Later,
Brad
December 09, 2006
Re: DMD 0.177 release - Clearifications Please?
Walter Bright wrote:
> More ABI changes, and implicit [] => * no longer allowed.
> 
> http://www.digitalmars.com/d/changelog.html
> 
> http://ftp.digitalmars.com/dmd.175.zip

# Casting a value v to a struct S is now rewritten as S(v).
# Initializing a struct S from a value v is now rewritten as S(v).

Can you clarify more what that means?

# TypeInfo now always generated for enum, struct, and typedef's, to 
enable more thorough rtti.

So, can we get a string version of enum values? and can we get struct names?

# hidden feature?

Why is everyone talking about opAssign? I don't see it mentioned in the 
change log.
December 09, 2006
Re: DMD 0.177 release
Walter Bright wrote:

>> I'm also a little wary about opAssign.  Not that I don't find it useful,
>> just that you've been vehemently opposed to overloading it in D for how
>> many years, and three weeks before 1.0 you reverse your opinion.  What
>> does that mean?
> 
> The problem I have, and still have, is the identity assignment. This is
> specifically disallowed with opAssign. I can go into the reasons why if
> you like.
> 

I wonder if it is not possible to make D, working as a base with values not
with references. 

In such a case references would be hidden from programmers and only values
would be visible at first. Assigning would always mean assign value, and
when there should be passed reference the special syntax would be
necessary, so references would be special case.

To disambiguate you can make something like this:

auto v := new Any; // special assignment operator ':=' for references
auto z := new Any;

v = 5; // Standard opAssign
z = v; // No problem here, opAssign can be used as usually
z :=v; // Reference copy - opAssign is not used here

Additionally when passing arguments to function, which demands references,
there could be used implicit conversion from values to references (so that
for user it would be visible as sending values). Below example almost works
now (almost because constructors can not be templatized):

void varFunc(Any[] arr ...) {
        foreach(v; arr) writefln(v.type);
}

void main() {
#       varFunc(new Any(5), new Any("tekst"[]), new Any(&variadicFunction));
}

In language in which everything is consider as an object you could just
write:

void main() {
       bool test;
#       varFunc(Any(5), Any("tekst"[]), Any(&variadicFunction));
#       varFunc(Any(5.6), Any(&test));
}

If there should be send reference(pointer) it should be done explicitly.
E.g.

void varFunc(Any*[] arr ...) {
....
}
void main() {
#       varFunc(new Any(5), new Any("tekst"[]), new Any(&variadicFunction));
}

Does it make any sense? Please comment...


> Having opAssign for foreign types turns out to be needed for things
> like, say I want to build a ranged integer. This is an integer that can
> only have values between m and n. Without opAssign, I'd have to use a
> property:
> RangedInt!(m,n) r;
> r.value = 6;
> It's just not right.

the same in case of boost::Any port to D.

-- 
Regards
Marcin Kuszczak
(Aarti_pl)
1 2 3 4 5 6 7 8
Top | Discussion index | About this forum | D home