May 12, 2012
On Saturday, May 12, 2012 11:26:37 Timon Gehr wrote:
> On 05/12/2012 10:13 AM, Manu wrote:
> > On 11 May 2012 21:28, Mehrdad <wfunction@hotmail.com
> > 
> > <mailto:wfunction@hotmail.com>> wrote:
> >     Yes, I agree, but consider that D users should NOT have to work with
> >     pointers to do something so basic
> > 
> > I'd like to think this were true, but the fact that 'ref' barely works makes this almost immediately false when trying to write any non-trivial program.
> 
> It depends on the coding style.

I rarely end up passing by either ref or pointer, and the only issues that I've ever had with ref relate to the fact that you can't pass it rvalues. Obviously both pointers and ref have their uses, but I'd definitely have to concur that it depends on your coding style and what you're doing. Also, I really don't know what's wrong with ref such that anyone could say that it "barely works" other than the issues with rvalues and functions which take ref or const ref.

- Jonathan M Davis
May 12, 2012
On 12 May 2012 12:26, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 05/12/2012 10:13 AM, Manu wrote:
>
>> On 11 May 2012 21:28, Mehrdad <wfunction@hotmail.com <mailto:wfunction@hotmail.com>**> wrote:
>>
>>    Yes, I agree, but consider that D users should NOT have to work with
>>    pointers to do something so basic
>>
>>
>> I'd like to think this were true, but the fact that 'ref' barely works makes this almost immediately false when trying to write any non-trivial program.
>>
>
> It depends on the coding style.
>

If the distinction is whether one likes to have data structures in their code or not, I reckon there's a reasonably large user base in the former? :) Once you use 'struct' you can't avoid pointers, given that ref just doesn't work in many (perhaps most) situations.


May 12, 2012
On Saturday, May 12, 2012 12:37:12 Manu wrote:
> On 12 May 2012 12:26, Timon Gehr <timon.gehr@gmx.ch> wrote:
> > On 05/12/2012 10:13 AM, Manu wrote:
> >> On 11 May 2012 21:28, Mehrdad <wfunction@hotmail.com
> >> 
> >> <mailto:wfunction@hotmail.com>**> wrote:
> >>    Yes, I agree, but consider that D users should NOT have to work with
> >>    pointers to do something so basic
> >> 
> >> I'd like to think this were true, but the fact that 'ref' barely works makes this almost immediately false when trying to write any non-trivial program.
> > 
> > It depends on the coding style.
> 
> If the distinction is whether one likes to have data structures in their code or not, I reckon there's a reasonably large user base in the former? :) Once you use 'struct' you can't avoid pointers, given that ref just doesn't work in many (perhaps most) situations.

Since structs are generally value types, it's extremely common to just pass them by value - so no refs or pointers are involved. I _rarely_ need pointers for structs, and I don't need ref for them all that often either. And aside from the need to duplicate functions which take const ref so that they work with rvalues, I don't know what about ref you could think doesn't work.

- Jonathan M Davis
May 12, 2012
On 05/12/2012 08:04 AM, Nick Sabalausky wrote:
> "Timon Gehr"<timon.gehr@gmx.ch>  wrote in message
> news:jok96k$l7t$1@digitalmars.com...
>>
>> Properties of a 'good IDE', as I see it:
>>
>> some essential properties:
>> - starts up instantaneously
>> - uses the screen space efficiently
>> - supports editing text efficiently
>> - accepts keyboard input as given by the user.
>> - reasonable support for auto-indentation
>> - supports searching the code for some text efficiently
>> - keeps all code _readable_, especially the one that has been written
>> recently
>> - pattern recognition based code completion
>>
>> - ... by default!
>>
>> some 'nice to have' properties:
>> - code analysis based code completion
>> - navigate-to-declaration
>> - for those languages that require it: automatic generation of
>> boilerplate.
>> - integrated debugger
>> - useful refactoring tools
>> - visualization of compilation errors (but please don't nag me)
>> - actual support for detecting semantic errors as they happen (extremely
>> difficult to do properly)
>> - any other argument that is commonly used to advertise IDEs
>>
>> - ... _responsive_ on halfway recent hardware!
>>
>> some anti-features:
>> - splash screen
>> - cannot run code if there is no 'project/solution file'
>> - sometimes messes up those files
>> - build fails - restart IDE - build works
>> - fancy GUI
>> - requires pointing device
>> - accidental hit of obscure keyboard combination ...
>>    =>  permanent, extremely annoying configuration change
>>    =>  no way to tell what happened
>>    =>  no undo operation
>> - termination of the debugged program kills the output console
>>
>>
>> As long as IDEs fail to satisfy every single point in the 'essential'
>> category and strive to have all of the stated anti-features, they don't
>> have much value for me anyway.
>>
>
> Hear hear!
>
> Although I'd swap the positions of "pattern recognition based code
> completion" and "_responsive_ on halfway recent hardware!".

The - ... points were meant to apply to all the other points in their group. Eg. navigate-to-declaration is extremely annoying if after the click, there is a pause of multiple seconds.

> In fact, I'd put "responsive" at the top of the "essential" list.
>

I have to agree. It could be argued that responsiveness was included in 'starts up instantaneously'/'supports editing text efficiently'.

May 12, 2012
On 12 May 2012 12:37, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Saturday, May 12, 2012 11:26:37 Timon Gehr wrote:
> > On 05/12/2012 10:13 AM, Manu wrote:
> > > On 11 May 2012 21:28, Mehrdad <wfunction@hotmail.com
> > >
> > > <mailto:wfunction@hotmail.com>> wrote:
> > >     Yes, I agree, but consider that D users should NOT have to work
> with
> > >     pointers to do something so basic
> > >
> > > I'd like to think this were true, but the fact that 'ref' barely works makes this almost immediately false when trying to write any
> non-trivial
> > > program.
> >
> > It depends on the coding style.
>
> I rarely end up passing by either ref or pointer, and the only issues that
> I've ever had with ref relate to the fact that you can't pass it rvalues.
> Obviously both pointers and ref have their uses, but I'd definitely have to
> concur that it depends on your coding style and what you're doing. Also, I
> really don't know what's wrong with ref such that anyone could say that it
> "barely works" other than the issues with rvalues and functions which take
> ref
> or const ref.
>

struct X
{
int i;

X opBinary(string op)(const ref X b) if(op == "+") { return X(i + b.i); }
ref X opOpAssign(string op)(const ref X b) if(op == "+") { i += b.i; return
this; }
...etc
}

ref X func(ref X x)
{
return x;
}

bool maybe()
{
return (time() & 1) != 0;
}

void test()
{
X a,b,c;
X v[];

func(a); // this is basically the only expression that works
X t = a + (b + c); // fail
a += b + c; // fail
ref X t = func(a); // fail
func(a + b); // fail
func(maybe() ? a : b); // this generates bad code:
http://forum.dlang.org/thread/cnwpmhihmckpjhlaszzy@forum.dlang.org
ref X t = v[some + complex * (expression + that_i_dont_want_to_repeat())];
// fail

foreach(i; 0..10)
{
ref X t = v[some + expression * involving - i]; // fail
}
}

Just a couple of extremely common usage patterns that come to mind. I'm sure there are many more...


May 12, 2012
On Saturday, May 12, 2012 13:03:26 Manu wrote:
> On 12 May 2012 12:37, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > On Saturday, May 12, 2012 11:26:37 Timon Gehr wrote:
> > > On 05/12/2012 10:13 AM, Manu wrote:
> > > > On 11 May 2012 21:28, Mehrdad <wfunction@hotmail.com
> > > > 
> > > > <mailto:wfunction@hotmail.com>> wrote:
> > > >     Yes, I agree, but consider that D users should NOT have to work
> > 
> > with
> > 
> > > >     pointers to do something so basic
> > > > 
> > > > I'd like to think this were true, but the fact that 'ref' barely works makes this almost immediately false when trying to write any
> > 
> > non-trivial
> > 
> > > > program.
> > > 
> > > It depends on the coding style.
> > 
> > I rarely end up passing by either ref or pointer, and the only issues that
> > I've ever had with ref relate to the fact that you can't pass it rvalues.
> > Obviously both pointers and ref have their uses, but I'd definitely have
> > to
> > concur that it depends on your coding style and what you're doing. Also, I
> > really don't know what's wrong with ref such that anyone could say that it
> > "barely works" other than the issues with rvalues and functions which take
> > ref
> > or const ref.
> 
> struct X
> {
> int i;
> 
> X opBinary(string op)(const ref X b) if(op == "+") { return X(i + b.i); }
> ref X opOpAssign(string op)(const ref X b) if(op == "+") { i += b.i; return
> this; }
> ...etc
> }
> 
> ref X func(ref X x)
> {
> return x;
> }
> 
> bool maybe()
> {
> return (time() & 1) != 0;
> }
> 
> void test()
> {
> X a,b,c;
> X v[];
> 
> func(a); // this is basically the only expression that works
> X t = a + (b + c); // fail
> a += b + c; // fail
> ref X t = func(a); // fail
> func(a + b); // fail
> func(maybe() ? a : b); // this generates bad code:
> http://forum.dlang.org/thread/cnwpmhihmckpjhlaszzy@forum.dlang.org
> ref X t = v[some + complex * (expression + that_i_dont_want_to_repeat())];
> // fail
> 
> foreach(i; 0..10)
> {
> ref X t = v[some + expression * involving - i]; // fail
> }
> }
> 
> Just a couple of extremely common usage patterns that come to mind. I'm sure there are many more...

So, basically it's just the issue with neither ref nor const ref taking lvalues. If you duplicate the functions (or use auto ref if they're templated functions), then it's not an issue. It sucks to have to duplicate stuff, but ref works just fine as long as you don't assume that it's going to allow you to pass rvalues to it. Personally, I almost always just have functions take structs by value, so it's a non-issue except for stuff like opEquals, which requires const ref (for at least one overload anyway).

However, given the ridiculousness of having to duplicate functions to make ref usuable for any case where you're specifically trying to avoid a copy rather than use it to pass a value out, Andrei and Walter are looking at making ref work with rvalues. They just have to sort out how to avoid the issues that C++ has due to allow const& to take rvalues (which is why const ref in D doesn't currently take rvalues). So, there's a good chance that the situation will improve considerably sometime soon.

- Jonathan M Davis
May 12, 2012
On 05/12/2012 08:53 AM, SomeDude wrote:
> On Saturday, 12 May 2012 at 06:19:37 UTC, Jonathan M Davis wrote:
>>
>> I do have to say that I find it somewhat funny that this is your set of
>> requirements for an IDEA and yet "integrated debugger" is in the "some
>> 'nice
>> to have' features" section. Doesn't an IDE _have_ to have an integrated
>> debugger or it's only a code editor (since it lacks the whole
>> integrated part
>> of Integrated Development Environment).
>>
>> - Jonathan M Davis
>
>
> Indeed, and Timon forgot the best feature of IDEs for bytecode compilers
> imho: they compile in the background, so that errors are detected while
> you type.

Probably I didn't express myself properly, but this was meant to be included at the

' - visualization of compilation errors (but please don't nag me)'

point.

> There is no annoying "write-correct" cycle as compile-time
> errors are shown in real time. That's a *huge* productivity boost.

* When I fail to write code that actually compiles, a few seconds of additional waiting time seem to be deserved. (it might be a longer time for eg. C++ though, so there this argument might not apply). If a programmer usually cannot write code that compiles, what are the chances that his code will be correct when it is run?

* The write-correct cycle is still there (actually it is a write-run-correct cycle), because current IDEs only catch trivial errors.

> It's actually better than with interpreted or scripted languages,
> because once you've finished writing code, it will run !
> Basically, with modern IDEs, the productivity with languages like Java/C# is comparable
> to Python.
>

If I have to develop in Java, emacs or even gedit usually do just fine.

> Background compiling shouldn't be too hard to implement for an editor, I
> guess: run the compiler in background on the current module every other
> second (or only when a set of simple syntaxic conditions like
> parentheses/accolades matching are matched, conditions which can easily
> be checked by the editor itself), and display the error messages in semi
> real time on screen where they appear.

This is too simplistic and very wasteful. The same data will be processed all over again. I don't know how IDEs manage to make modern >2GHZ quad-core systems appear slow, but it might well be that kind of coding.
May 12, 2012
On 05/12/2012 12:13 PM, Jonathan M Davis wrote:
> On Saturday, May 12, 2012 13:03:26 Manu wrote:
>> On 12 May 2012 12:37, Jonathan M Davis<jmdavisProg@gmx.com>  wrote:
>>> On Saturday, May 12, 2012 11:26:37 Timon Gehr wrote:
>>>> On 05/12/2012 10:13 AM, Manu wrote:
>>>>> On 11 May 2012 21:28, Mehrdad<wfunction@hotmail.com
>>>>>
>>>>> <mailto:wfunction@hotmail.com>>  wrote:
>>>>>      Yes, I agree, but consider that D users should NOT have to work
>>>
>>> with
>>>
>>>>>      pointers to do something so basic
>>>>>
>>>>> I'd like to think this were true, but the fact that 'ref' barely works
>>>>> makes this almost immediately false when trying to write any
>>>
>>> non-trivial
>>>
>>>>> program.
>>>>
>>>> It depends on the coding style.
>>>
>>> I rarely end up passing by either ref or pointer, and the only issues that
>>> I've ever had with ref relate to the fact that you can't pass it rvalues.
>>> Obviously both pointers and ref have their uses, but I'd definitely have
>>> to
>>> concur that it depends on your coding style and what you're doing. Also, I
>>> really don't know what's wrong with ref such that anyone could say that it
>>> "barely works" other than the issues with rvalues and functions which take
>>> ref
>>> or const ref.
>>
>> struct X
>> {
>> int i;
>>
>> X opBinary(string op)(const ref X b) if(op == "+") { return X(i + b.i); }
>> ref X opOpAssign(string op)(const ref X b) if(op == "+") { i += b.i; return
>> this; }
>> ...etc
>> }
>>
>> ref X func(ref X x)
>> {
>> return x;
>> }
>>
>> bool maybe()
>> {
>> return (time()&  1) != 0;
>> }
>>
>> void test()
>> {
>> X a,b,c;
>> X v[];
>>
>> func(a); // this is basically the only expression that works
>> X t = a + (b + c); // fail
>> a += b + c; // fail
>> ref X t = func(a); // fail
>> func(a + b); // fail
>> func(maybe() ? a : b); // this generates bad code:
>> http://forum.dlang.org/thread/cnwpmhihmckpjhlaszzy@forum.dlang.org
>> ref X t = v[some + complex * (expression + that_i_dont_want_to_repeat())];
>> // fail
>>
>> foreach(i; 0..10)
>> {
>> ref X t = v[some + expression * involving - i]; // fail
>> }
>> }
>>
>> Just a couple of extremely common usage patterns that come to mind. I'm
>> sure there are many more...
>
> So, basically it's just the issue with neither ref nor const ref taking
> lvalues. If you duplicate the functions (or use auto ref if they're templated
> functions), then it's not an issue. It sucks to have to duplicate stuff, but
> ref works just fine as long as you don't assume that it's going to allow you to
> pass rvalues to it. Personally, I almost always just have functions take
> structs by value, so it's a non-issue except for stuff like opEquals, which
> requires const ref (for at least one overload anyway).
>
> However, given the ridiculousness of having to duplicate functions to make ref
> usuable for any case where you're specifically trying to avoid a copy rather
> than use it to pass a value out, Andrei and Walter are looking at making ref
> work with rvalues. They just have to sort out how to avoid the issues that C++
> has due to allow const&  to take rvalues (which is why const ref in D doesn't
> currently take rvalues). So, there's a good chance that the situation will
> improve considerably sometime soon.
>
> - Jonathan M Davis

I don't see why 'const' should make a difference there anyway. It is completely orthogonal. It could be argued that the callee might assume that his changes will be visible for the caller, but if the point of passing an rvalue by reference is to gain performance, forbidding the callee to use it as scratch space is just ridiculous.
May 12, 2012
On 05/12/2012 11:37 AM, Manu wrote:
> On 12 May 2012 12:26, Timon Gehr <timon.gehr@gmx.ch
> <mailto:timon.gehr@gmx.ch>> wrote:
>
>     On 05/12/2012 10:13 AM, Manu wrote:
>
>         On 11 May 2012 21:28, Mehrdad <wfunction@hotmail.com
>         <mailto:wfunction@hotmail.com>
>         <mailto:wfunction@hotmail.com <mailto:wfunction@hotmail.com>>__>
>         wrote:
>
>             Yes, I agree, but consider that D users should NOT have to
>         work with
>             pointers to do something so basic
>
>
>         I'd like to think this were true, but the fact that 'ref' barely
>         works
>         makes this almost immediately false when trying to write any
>         non-trivial
>         program.
>
>
>     It depends on the coding style.
>
>
> If the distinction is whether one likes to have data structures in their
> code or not,

Classes and dynamic arrays can be used to build data structures as well, so whether or not you usually use pointers is a matter of style. (FWIW, I use them too.)

> I reckon there's a reasonably large user base in the former? :)
> Once you use 'struct' you can't avoid pointers, given that ref just
> doesn't work in many (perhaps most) situations.

The assertion was

"Yes, I agree, but consider that D users should NOT *have to* work with pointers *to do something so basic*"
May 12, 2012
On 12 May 2012 13:13, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> So, basically it's just the issue with neither ref nor const ref taking lvalues.


And the local references, and the bug.

If you duplicate the functions (or use auto ref if they're templated
> functions), then it's not an issue.


Yes it is. Passing by value is NOT passing by reference, it's a totally
different operation. And what about non-const ref?
'in ref' would be very nice if it worked. It would basically replace 'const
ref'.

It sucks to have to duplicate stuff, but
> ref works just fine as long as you don't assume that it's going to allow
> you to
> pass rvalues to it.


Well there's the bugs we've seen in optimised codegen.
Duplicating with non-ref is not a solution. It's not even a workaround. The
only workaround is to receive a pointer, which ruins all those cases in
terms of syntax anyway.

Personally, I almost always just have functions take
> structs by value, so it's a non-issue except for stuff like opEquals, which requires const ref (for at least one overload anyway).
>

Well I think it's safe to say most people pass data structs by reference.
If I saw someone pass a struct by val, I'd consider it a bug/typo and fix
it.
You might say to use a class in D, but classes aren't a pure data structure
like they are in C; I see them as being for fundamentally different
purposes, and I wouldn't use a class to express a struct.
Classes also ruin strict data layout and alignment of members. I don't
think that's a valid workaround either, it's effectively abusing the very
_concept_ of classes in D.

However, given the ridiculousness of having to duplicate functions to make
> ref
> usuable for any case where you're specifically trying to avoid a copy
> rather
> than use it to pass a value out, Andrei and Walter are looking at making
> ref
> work with rvalues.


Awesome, although it doesn't end there. Local references are also very important.

They just have to sort out how to avoid the issues that C++
> has due to allow const& to take rvalues (which is why const ref in D
> doesn't
> currently take rvalues). So, there's a good chance that the situation will
> improve considerably sometime soon.
>

What are these issues I keep hearing about? I'm not aware of any
fundamental problem with ref in C++...
Can you show an example of the problem the design is trying to avoid?

> That's not a solution, it's not even a work around, it's a totally
> > different operation. I may not want to, or can't, pass my data by value.
>
> Whether passing by value makes sense depends on the struct. If it has lots
> of
> members, then no, passing by value doesn't work very well (though still
> not as
> badly as C++98 thanks to the fact that D can move structs far more often
> due
> to its different copy semantics). But almost all of the structs that I deal
> with only have a handful of member variables at most, so the cost of
> passing
> by value isn't high. In most cases, if I have a lot, I probably wanted a
> reference type anyway, in which case, I'm almost certainly going to use a
> class.
>

Well, in my line of work, if the cost of passing by value is greater than
the cost of passing by reference, then the correct thing to do is to pass
by reference. There is zero tolerance for wasting memory accesses on such a
trivial operation.
The only case where the cost of passing by value is ever less than by
reference is if the struct contains a single primitive value for which the
CPU has a dedicated register type. This is the only time we would ever
tolerate passing by value.

But there's no question that the situation with const ref needs to be
> improved
> (it was discussed quite a bit on the beta list during the last beta).
> Fortunately, that's likely to happen sometime soon.


That's a shame, it's been coming up every day for me the last couple of weeks. I have workarounds in almost every source file, and some cases where a workaround is impossible, which pollutes the code at the point of use.