April 30, 2012
On Sun, Apr 29, 2012 at 10:03:43AM +0400, Dmitry Olshansky wrote:
> On 29.04.2012 5:06, bearophile wrote:
[...]
> >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...
> >
> Doesn't have to do anything with the LANGUAGE.
> Yesterday I tried GDC. Damn I didn't regret it :)
[...]

Unfortunately, even GDC doesn't inline opApply and its delegate for the simplest of loops:

	struct S {
		int data[];
		int opApply(int delegate(ref int) dg) {
			foreach (d; data) {
				if (auto r = dg(d))
					return r;
			}
			return 0;
		}
	}
	void main() {
		S s;
		foreach (e; s) {
			writeln(e);
		}
	}

I think it's because the front-end always generates the full delegate passing code without inlining anything. IMO, this case *need* to be aggressively inlined in order to make D's generic programming capabilities a stronger selling point.


T

-- 
"Computer Science is no more about computers than astronomy is about telescopes." -- E.W. Dijkstra
April 30, 2012
On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
> Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
> >D unit tests were never really useful for anything beyond single-library projects IMHO. They don't scale for large, real-world application projects with lots of libraries and executables.
> >
> 
> +1 A good std.unittest + attributes is probably a better approach.

The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all.

I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda the point, 'cos in my experience the act of writing a unittest automatically makes you think about corner cases in the code you just wrote (or just about to write), which means there will be less bugs from the get-go.

Also, unittest is just that: for _unit_ tests. If you start needing an entire framework for them, then you're no longer talking about _unit_ tests, you're talking about module- or package-level testing frameworks, and you should be using something more suitable for that, not unittest.


T

-- 
Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder
April 30, 2012
On 30-04-2012 04:37, 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.
>
>
> T
>

What you just talked about = semantics. So, it is a language issue.

-- 
- Alex
April 30, 2012
On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
> On Sunday, April 29, 2012 17:50:48 Don wrote:
>> * package. I have no idea how a failed Java experiment got incorporated
>> into D.
>
> Really? In some cases, it's indispensable. For instance, once std.datetime has
> been split up, it will require it, or it would have duplicate a bunch of
> implementation-specific stuff which has no business in the public API.
>
> - Jonathan M Davis

It's entirely dependent on your coding style. For example, when you look at Phobos you rarely (if ever?) see package functions. This is because it's entirely module based with a strong degree of separation between modules.

However, for someone coming from C#, removing package would be awful. I personally use package quite often. For the most part, I stick to one major class per file, and separate things across library. There are plenty of things that I want other classes in the package/static-library to use, but don't want to expose to the public, and thus use package for.
April 30, 2012
On Sunday, April 29, 2012 20:03:44 H. S. Teoh wrote:
> On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
> > Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
> > >D unit tests were never really useful for anything beyond single-library projects IMHO. They don't scale for large, real-world application projects with lots of libraries and executables.
> > 
> > +1 A good std.unittest + attributes is probably a better approach.
> 
> The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all.
> 
> I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda the point, 'cos in my experience the act of writing a unittest automatically makes you think about corner cases in the code you just wrote (or just about to write), which means there will be less bugs from the get-go.
> 
> Also, unittest is just that: for _unit_ tests. If you start needing an entire framework for them, then you're no longer talking about _unit_ tests, you're talking about module- or package-level testing frameworks, and you should be using something more suitable for that, not unittest.

One common term for those is "component tests." Unit tests are for testing individual functions and types, whereas component tests test inter-module and inter-program interactions.

What D has with regards to unit tests works _very_ well for basic unit tests but does not attempt to support component tests at all beyond where unittest blocks could be used for the same purpose. The main place that D's unit test framework becomes problematic is when you need to run a subset of tests - it's designed to run everything at once. But compiling and running each module separately for unit tests allows you to control that through you build system or whatnot.

As Walter has stated on several occasions, D's built-in unit testing framework is designed to be incredibly simple and easy so that they're so easy and convenient to use that you have no excuse not to. If you want more complicated unit testing frameworks, there's nothing stopping you from making your own like has to be done in other languges. For instance, cppunit and junit aren't built-in to their associated languages at all; they're 3rd party projects. You can do the same in D if you want fancier unit testing facilities.

- Jonathan M Davis
April 30, 2012
On Sun, Apr 29, 2012 at 02:26:12PM +0200, David Nadlinger wrote: [...]
>  - Comma operator: Kill it with extreme prejudice, it is an
>  anti-feature (allow it in for loop expressions if you really want to,
>  but I think there are better solutions).

+1. The voice of reason.


[...]
>  - HexString, DelimitedString, r""-WysiwigString, TokenString: I
> didn't ever use the former two (for including binary data in the
> program, ImportExpression is imho much easier than generating a
> source file containing a HexString).

I found hexstrings useful for writing unittests for testing Unicode handling (I wanted to test both big- and little-endian UTF-16 and UTF-32, whereas currently string literals can only produce native endian). It might also be useful for unittesting code that takes binary input.


> As for r"", every time I actually need WysiwigString, I use backticks, because such strings often contain quotes anyway.

+1. I think r"" and `` should be merged. Having both is too much.


> Regarding TokenString(i.e. q{}) – it is certainly a very nice idea, especially regarding syntax highlighting, and I occasionally use them for CTFE code generation.

I use tokenstrings a lot for mixins. But arguably that use case would be obsolete when D finally finds a good macro system.


[...]
>  - Concatenation of adjacent strings: Also an anti-feature, imho.

I personally find them useful for nicely-formatting code that contains lots of long strings. But YMMV.


>  - Floating point comparison operators like !<>= (yes, that _is_ valid
>  D code): I must admit that I seldom write code relying on the finer
>  details of IEEE-754 semantics, but can't they just be »lowered« to a
>  combination of the more common ones?

Yeah when I was writing a D lexer (just as an exercise) I was flabbergasted at the sheer amount of comparison operators D has. I mean, I don't know if I will ever use *half* of them in my lifetime. After a while my eyes were just glazing over from all the ASCII UFO's that somehow flew into my code from outer space.

If IEEE-754 support is what the intention was, I'd recommend putting them in std.math instead of loading the language with a bunch of apparently-oxymoronic operators like !<> and !<>=, that probably nothing outside of IEEE-754 buffs will ever even care about.


[...]
>  - Built-in arrays and AAs: They are convenient to use, but as far as
>  I can see the single biggest GC dependency in the language. Why not
>  lower array and AA literals to expression tuples (or whatever) to
>  make the convenient syntax usable with custom (possibly non-GC safe)
>  containers as well? A GC'd default implementation could then be
>  provided in druntime, just like today's arrays and AAs.
[...]

AA's are moving into druntime. Yours truly is supposed to make that happen eventually, but lately time hasn't been on my side. :-/

This is an interesting idea, though... once we've fully excised AA's from dmd (aside from convenient lowerings from native syntax), it will open up the possibility of writing a GC-less druntime replacement that also provides an alternate implementation of AA's that don't depend on the GC.


T

-- 
This is not a sentence.
April 30, 2012
On 30-04-2012 05:03, H. S. Teoh wrote:
> On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
>> Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
>>> D unit tests were never really useful for anything beyond
>>> single-library projects IMHO. They don't scale for large, real-world
>>> application projects with lots of libraries and executables.
>>>
>>
>> +1 A good std.unittest + attributes is probably a better approach.
>
> The only reason I actually write unittests for D code is because
> unittest{} is so convenient. If I had to import std.unittest, most
> likely my code will have no unittests at all.
>
> I find that because unittest{} makes it so convenient to write
> unittests, it's just embarrassing to not write them. Which is kinda the
> point, 'cos in my experience the act of writing a unittest automatically
> makes you think about corner cases in the code you just wrote (or just
> about to write), which means there will be less bugs from the get-go.
>
> Also, unittest is just that: for _unit_ tests. If you start needing an
> entire framework for them, then you're no longer talking about _unit_
> tests, you're talking about module- or package-level testing frameworks,
> and you should be using something more suitable for that, not unittest.
>
>
> T
>

The problem with D's unit test support is that it doesn't integrate well into real world build processes. I usually have debug and release configurations, and that's it. No test configuration; not only does that over-complicate things, but it also isn't really useful. I want my unit testing to be exhaustive; i.e. I want to test my code in debug and release builds, because those are the builds people are going to be using. Not a test build.

So, this means that writing unit tests inline is a no-go because that would require either always building with unit tests in all configurations (madness) or having a test configuration (see above).

Given the above, I've resorted to having a "tester" executable which links in all libraries in my project and tests every module. This means that I have to write my unit tests inside this helper executable, making much of the gain in D's unittest blocks go away.

And no, the fact that I link libraries into the helper executable doesn't mean that I can just write the unit tests in the libraries in the first place. Doing so would require building them twice: Once for the normal build and once for the "tester" executable.

(And yes, build times matter when your project gets large enough, even in D.)

-- 
- Alex
April 30, 2012
On 30-04-2012 05:12, Jonathan M Davis wrote:
> On Sunday, April 29, 2012 20:03:44 H. S. Teoh wrote:
>> On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
>>> Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
>>>> D unit tests were never really useful for anything beyond
>>>> single-library projects IMHO. They don't scale for large, real-world
>>>> application projects with lots of libraries and executables.
>>>
>>> +1 A good std.unittest + attributes is probably a better approach.
>>
>> The only reason I actually write unittests for D code is because
>> unittest{} is so convenient. If I had to import std.unittest, most
>> likely my code will have no unittests at all.
>>
>> I find that because unittest{} makes it so convenient to write
>> unittests, it's just embarrassing to not write them. Which is kinda the
>> point, 'cos in my experience the act of writing a unittest automatically
>> makes you think about corner cases in the code you just wrote (or just
>> about to write), which means there will be less bugs from the get-go.
>>
>> Also, unittest is just that: for _unit_ tests. If you start needing an
>> entire framework for them, then you're no longer talking about _unit_
>> tests, you're talking about module- or package-level testing frameworks,
>> and you should be using something more suitable for that, not unittest.
>
> One common term for those is "component tests." Unit tests are for testing
> individual functions and types, whereas component tests test inter-module and
> inter-program interactions.
>
> What D has with regards to unit tests works _very_ well for basic unit tests
> but does not attempt to support component tests at all beyond where unittest
> blocks could be used for the same purpose. The main place that D's unit test
> framework becomes problematic is when you need to run a subset of tests - it's
> designed to run everything at once. But compiling and running each module
> separately for unit tests allows you to control that through you build system
> or whatnot.
>
> As Walter has stated on several occasions, D's built-in unit testing framework
> is designed to be incredibly simple and easy so that they're so easy and
> convenient to use that you have no excuse not to. If you want more complicated
> unit testing frameworks, there's nothing stopping you from making your own
> like has to be done in other languges. For instance, cppunit and junit aren't
> built-in to their associated languages at all; they're 3rd party projects. You
> can do the same in D if you want fancier unit testing facilities.
>
> - Jonathan M Davis

Except we can't do:

@test
void myTest()
{
    // ...
}

due to the current lack of annotations and discovery-based reflection. ;)

*hint hint...*

-- 
- Alex
April 30, 2012
On Monday, April 30, 2012 05:12:27 Kapps wrote:
> On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
> > On Sunday, April 29, 2012 17:50:48 Don wrote:
> >> * package. I have no idea how a failed Java experiment got
> >> incorporated
> >> into D.
> > 
> > Really? In some cases, it's indispensable. For instance, once
> > std.datetime has
> > been split up, it will require it, or it would have duplicate a
> > bunch of
> > implementation-specific stuff which has no business in the
> > public API.
> > 
> > - Jonathan M Davis
> 
> It's entirely dependent on your coding style. For example, when you look at Phobos you rarely (if ever?) see package functions. This is because it's entirely module based with a strong degree of separation between modules.
> 
> However, for someone coming from C#, removing package would be awful. I personally use package quite often. For the most part, I stick to one major class per file, and separate things across library. There are plenty of things that I want other classes in the package/static-library to use, but don't want to expose to the public, and thus use package for.

It's a question of how inter-dependent your modules are (which is partly a question of style). If you have a bunch of closely related functionality that should be in separate modules, then it can be quite easy for it to need have stuff which it needs to share but shouldn't be public. This happens much more easily if you follow a style of putting one class per module as you _must_ do in Java and C# but don't have to do in D.

Phobos doesn't have all that many types in it (though that's changing as it grows). Historically, it's been (and mostly still is) a collection of free functions which have been organized in modules with related functions sharing modules. However, free functions tend to be quite independent. At most, they may share some private helpers. They rarely need to share stuff across modules. On top of that, Phobos has historically avoided creating sub-modules in favor of a flat hierarchy (though that's starting to change) The result of this is that package hasn't been needed in Phobos. I suspect that Don's take on things comes from that (and he probably hasn't needed package in his own stuff either).

But I don't think that it's very hard at all to come up with examples where package level access can be invaluable.

- Jonathan M Davis
April 30, 2012
On Monday, April 30, 2012 05:20:21 Alex Rønne Petersen wrote:
> Except we can't do:
> 
> @test
> void myTest()
> {
>      // ...
> }
> 
> due to the current lack of annotations and discovery-based reflection. ;)
> 
> *hint hint...*

What would that buy you? That's what unittest blocks are for. Yes, getting custom annotations would be great, and then you could use @test for whatever you need it for, but unittest blocks are the test functions, so I'm not quite sure what @test would buy you. You _could_ just put a particular string in a name though (e.g. start all unit test functions with test) and use compile- time reflection to find them if you really want to though (much as that isn't as nice as a user-defined attribute would be).

- Jonathan M Davis