April 30, 2012
On 04/30/12 02:33, Simen Kjaeraas wrote:
> On Sat, 28 Apr 2012 22:40:10 +0200, Artur Skawina <art.08.09@gmail.com> wrote:
> 
>> On 04/28/12 22:02, Walter Bright wrote:
>>> On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
>>>> Also there's mixin templates. What exactly is the difference between mixin templates and regular templates?
>>>
>>> A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point.
>>>
>>> This becomes relevant when looking up symbols that are not defined within the template.
>>
>> Yeah, but this was actually the only suggestion so far in this thread that i could agree with... The issue is
>>
>>    template t1() { int a = b; }
>>    int main() { int b; mixin t1; return a; }
>>
>> which is currently accepted - and would enforcing the mixin annotation really help anything?
>>
>> artur
> 
> At least some of us want mixin templates to be marked mixin at declaration point, and usable without 'mixin':
> 
> mixin template A( ) {
>     int n;
> }
> 
> struct S {
>     A!();
> }

Yes, that's the other possible use for marking a template as a mixin. Unlike my above example it wouldn't then be redundant; the question is however if this functionality really is desirable...

   mixin template t1() { auto _ = a = b; }
   int main() { int a, b=1; t1!(); return a; }

This program would now return '1', which can be non-obvious if you don't know the definition of 't1'. Right now you have to write that as

   template t1() { auto _ = a = b; }
   int main() { int a, b=1; mixin t1!(); return a; }

so the mixin is clearly visible.

These kind of template macros would be useful and i'd like to have them too, but there is a cost, and i'm not yet sure that being able to omit the 'mixin' keyword would be worth it.

artur
April 30, 2012
On Sun, Apr 29, 2012 at 01:23:17PM +0200, Timon Gehr wrote:
> On 04/29/2012 11:31 AM, foobar wrote:
> >On Sunday, 29 April 2012 at 08:58:24 UTC, Timon Gehr wrote:
[...]
> >>It is not. For example, code that is only executed during CTFE does never have to behave gracefully if the input is ill-formed.
> >
> >I disagree - you should make sure the input is valid or all sorts of bad things could potentially happen such as a compiler can get stuck in an infinite loop.
> 
> It could fail in a number of other ways. I don't think that this example can be used to invalidate the statement.

Like if the Ackermann function was evaluated in CTFE for very large arguments. Technically it isn't an infinite loop, but you probably wouldn't like the results.


T

-- 
If I were two-faced, would I be wearing this one? -- Abraham Lincoln
April 30, 2012
On Sun, Apr 29, 2012 at 04:43:12PM +0200, Jacob Carlborg wrote:
> On 2012-04-28 21:36, Andrej Mitrovic wrote:
[...]
> >Another feature I'm curious about is .dup/.idup. It's basically hardcoded for a couple of types, but why not instead use UFCS and implement .dup/.idup in std.array as a free function? Then you might even use it for user-types by requiring a type to implement .dup/.idup functions.
> 
> Agree with this one as well.
[...]

+1. This would make generic code easier to write. Which is good, because the less we have to rewrite code that's been written a hundred times in the past already, the better.


T

-- 
A linguistics professor was lecturing to his class one day.
"In English," he said, "A double negative forms a positive. In some
languages, though, such as Russian, a double negative is still a
negative. However, there is no language wherein a double positive can
form a negative."
A voice from the back of the room piped up, "Yeah, yeah."
April 30, 2012
On Sun, Apr 29, 2012 at 01:46:25AM -0700, Jonathan M Davis wrote:
> On Sunday, April 29, 2012 10:37:10 Timon Gehr wrote:
> > Well, what if the programmer "knows" that foo does not change 'aa', but it actually does? Then there would possibly be a segmentation fault.  This implies that the 'in' operator cannot be used in @safe code. (Or there would have to be a special case, that allows 'in' if the result is directly cast to bool.)
> 
> It's exactly as safe as any iterator or range which could be invalidated - both of which can occur in safe code. Any of those could blow up in entertaining ways if you use them after they've been invalidated.
> 
> Pointers are considered safe. It's pointer arithmetic which isn't.
[...]

I get that this discussion is about what type 'in' should return, but taking a step back, isn't it all moot because you could just use the .get() method?


T

-- 
Let's not fight disease by killing the patient. -- Sean 'Shaleh' Perry
April 30, 2012
On Sun, Apr 29, 2012 at 10:21:19PM +0200, Alex Rønne Petersen wrote:
> On 29-04-2012 00:49, H. S. Teoh wrote:
> >On Sun, Apr 29, 2012 at 12:39:03AM +0200, Timon Gehr wrote:
[...]
> >>- 'in' operator returning a pointer to the element.
> >
> >Yeah that one elicited a WAT from me when I first started using it. Surprisingly enough, it sounded OK when I read it in TDPL, but when I started using it I realized just how b0rken it is.
[...]
> 
> How so? It's seemed entirely reasonable to me.
[...]

I was expecting it to return bool.

It also precludes bool-valued AA's from being implemented using bit arrays, since you can't return a pointer to a bit.


T

-- 
In order to understand recursion you must first understand recursion.
April 30, 2012
On Sun, Apr 29, 2012 at 10:40:03PM +0200, Alex Rønne Petersen wrote:
> On 29-04-2012 00:04, H. S. Teoh wrote:
[...]
> >Yeah, .sort is redundant, and besides shouldn't be an array "property" to begin with.
[...]
> Let's not forget .reverse. Why these are properties (and .dup/.idup)
> is seriously beyond me.....
[...]

AFAIK, it's a historical accident. These "properties" date from before people decided to distinguish between methods and properties.


T

-- 
"A man's wife has more power over him than the state has." -- Ralph Emerson
April 30, 2012
On Sun, Apr 29, 2012 at 11:18:12PM +0200, deadalnix wrote: [...]
> C don't have out parameters as D have. C have pointer to do kind of out parameters, and D have pointers too, this is a non issue.

I argue that using 'out' vs. a pointer is a good thing, because it clarifies intent. When you see a pointer, it's far from clear whether it's an input parameter, an output parameter, or both.

More and more, I'm leaning towards the opinion that all code should reveal intent, preferably in a language-supported way. Unclear intent is what leads to subtle bugs caused by people calling functions with wrong assumptions. (You'd think this should be a non-problem with programmers, who are presumably smart enough to figure things out without being told in the face, but I've seen too much "enterprise" code by now to not be cynical about it.)


T

-- 
Heuristics are bug-ridden by definition. If they didn't have bugs, they'd be algorithms.
April 30, 2012
On Sun, Apr 29, 2012 at 08:42:23PM +0200, Andrej Mitrovic wrote:
> On 4/29/12, Jacob Carlborg <doob@me.com> wrote:
> > In principle I agree with you. But in practice this doesn't always work.  Take this for example: Prints "0" and "1" as expected. If we now change "point" to a property like this: It will now print "0" and "0". This is a silently breaking change. Sure you can change "point" to return by reference..
> 
> This is a great point and an issue I've ran into and talked about before. The compiler really ought to try and convert a call like this:
> 
> foo.property++;
> foo.property+=10;
> 
> into e.g.:
> foo.property = foo.property.opAdd(1);
> foo.property = foo.property.opAdd(10);
> 
> It would make for some really nice APIs if this feature was available.
[...]

To me, the compiler needs to be fixed so that anytime the return value of a @property is used as an lvalue, it should always try to call the setter function, or some kind of setter function, instead of the getter (unless there's no setter, in which case it's OK to call the getter).

I chalk this up to a compiler issue, not a language issue.


T

-- 
Let X be the set not defined by this sentence...
April 30, 2012
On Sunday, April 29, 2012 19:37:50 H. S. Teoh wrote:
> On Sun, Apr 29, 2012 at 08:42:23PM +0200, Andrej Mitrovic wrote:
> > On 4/29/12, Jacob Carlborg <doob@me.com> wrote:
> > > In principle I agree with you. But in practice this doesn't always work.  Take this for example: Prints "0" and "1" as expected. If we now change "point" to a property like this: It will now print "0" and "0". This is a silently breaking change. Sure you can change "point" to return by reference..
> > 
> > This is a great point and an issue I've ran into and talked about before. The compiler really ought to try and convert a call like this:
> > 
> > foo.property++;
> > foo.property+=10;
> > 
> > into e.g.:
> > foo.property = foo.property.opAdd(1);
> > foo.property = foo.property.opAdd(10);
> > 
> > It would make for some really nice APIs if this feature was available.
> 
> [...]
> 
> To me, the compiler needs to be fixed so that anytime the return value of a @property is used as an lvalue, it should always try to call the setter function, or some kind of setter function, instead of the getter (unless there's no setter, in which case it's OK to call the getter).
> 
> I chalk this up to a compiler issue, not a language issue.

Well, it's both really. If the language spec was exact enough, it would say _exactly_ what the correct behavior is here, in which case, either the compiler is currently doing the right thing or it's not, depending on the spec. But the spec isn't that exact, so in some respects, the compiler _is_ the spec. Certainly, the way that this behaves in the language right now is a matter of how the compiler behaves.

Ideally though, there would be zero difference between using a property and a public member variable save for taking its address (which should probably just be illegal for @property functions). I've been tempted to add an enhancement request for putting @property on public member variables to make it so that anything which would would break code if it were switched to a property function wouldn't be legal (such as taking its address). Unfortunately, right now that would include stuff like ++.

- Jonathan M Davis
April 30, 2012
On Sun, Apr 29, 2012 at 03:06:53AM +0200, bearophile wrote:
> Jonathan M Davis:
> 
> >* foreach_reverse is essentially redudant at this point (not to
> >mention
> >confusing if combined with delegates), since we have retro.
> 
> retro() can't replace foreach_reverse until the front-end
> demonstrability produces asm code equally efficient.
> Loops _must_ be fully efficient, they are a basic language
> construct, this is very important. Even foreach() is sometimes not
> equally efficient as a for() in some cases...
[...]

IMO, the compiler needs to _aggressively_ inline opApply() delegates, unless it's impossible (e.g. opApply is recursive), or perhaps exceeds some reasonable size limit for loop inlining). It's rather disheartening to design a great abstract type for manipulating collections, only to have opApply always incur the overhead of allocating and invoking a delegate _every loop iteration_, even when opApply is as simple as:

	int opApply(int delegate(ref T arg) dg) {
		someSetupCode();
		for (i=0; i<n; i++) {
			dg(element[i]);
		}
		someCleanupCode();
	}

As far as I'm concerned, the compiler *should* just inline the whole thing (both opApply and the delegate body) when you write foreach(c; container) {...}. There's no reason for such a trivial loop to incur a call to a delegate every iteration.

Powerful abstractions such as opApply need to be optimized to the max, so that D's generic programming capabilities can be a strong selling point.


T

-- 
Nearly all men can stand adversity, but if you want to test a man's character, give him power. -- Abraham Lincoln