Re: Software validation

2018-06-05 Thread Kagamin via Digitalmars-d

On Monday, 4 June 2018 at 15:48:35 UTC, DigitalDesigns wrote:
Just curious if something exists that allows for mathematical 
validation such code in an relatively canonical way. This isn't 
too hard for pure functions but dealing with non-pure functions 
can be a pain.


Something like HACL? https://github.com/mitls/hacl-c


Can anyone explain this?

2018-06-05 Thread Shachar Shemesh via Digitalmars-d
I set up to find out what happens if the assert string throws. I have to 
admit I did not expect the result:


$ cat test.d
import std.stdio;
import core.exception;

void main() {
scope(failure) {
writeln("Not gonna happen");
}

try {
static string throwingFunc() {
throw new Exception("An exception");
}
assert(0==1, throwingFunc());
} catch(Exception ex) {
writeln("Exception");
} catch(AssertError ex) {
writeln("Assert");
}
}

$ ldc2 --version
LDC - the LLVM D compiler (1.8.0):
  based on DMD v2.078.3 and LLVM 5.0.1
...

$ ./test
Not gonna happen
object.Exception@test.d(11): An exception

??:? [0x3728941e]
??:? [0x372903aa]
??:? [0x3727b15c]
??:? [0x3724991d]
??:? [0x372496c9]
??:? [0x3727aecf]
??:? [0x3727addb]
??:? [0x3724a124]
??:? __libc_start_main [0xed8b01c0]
??:? [0x372495c9]

$ dmd --version
DMD64 D Compiler v2.080.0
Copyright (C) 1999-2018 by The D Language Foundation, All Rights 
Reserved written by Walter Bright


$ ./test
Not gonna happen
object.Exception@test.d(11): An exception

??:? pure @safe immutable(char)[] test.main().throwingFunc() [0xe9b1c2b3]
??:? _Dmain [0xe9b1c1ad]


Re: Software validation

2018-06-05 Thread DigitalDesigns via Digitalmars-d
On Tuesday, 5 June 2018 at 06:45:31 UTC, Petar Kirov [ZombineDev] 
wrote:

On Monday, 4 June 2018 at 15:48:35 UTC, DigitalDesigns wrote:
Does D have any methods of validating code in a natural manner 
besides unit tests and contracts?


I'm specifically thinking of validating mathematical 
calculations and boolean operations that could depend on very 
improbable scenarios but are technically invalid logic.


These issues tend to creep up in calculations that involve 
floating points due to various reasons or comparisons that 
mistakenly use > for >= or vice versa.


If I have a variable such as a buffer which has a length and 
an offset in to that buffer is calculated using double 
precision then rounding errors could cause the offset to 
except the length and create an access violation.


To be able to theoretically test all the possibilities all 
valid inputs would need to be checked. One can setup unit 
tests to test these possibilities but it can be difficult to 
cover all cases in even a semi-complex program.


Just curious if something exists that allows for mathematical 
validation such code in an relatively canonical way. This 
isn't too hard for pure functions but dealing with non-pure 
functions can be a pain.


Perhaps not quite what you're looking for, but I think you 
would be interested in the LLVM fuzzing part of Johan Engelen's 
talk at DConf 2018:

https://www.youtube.com/watch?v=GMKvYrjaaoU (at around 34:30).


Sorta, but not fuzzing because that is too spare. Rather than 
picking a random point in a billion dimensional vector space bit 
is sort of works only on the surface of possible values. Which he 
addresses initially being the problem and is similar to what I'm 
looking for.


The idea though is problems almost always occur on edge cases so 
there is no need to check everything inside an interval but only 
the edge cases.


if (x < 10)

one only needs to check if x = 9, 10, 11 but not 4, 5, etc.

Of course, in more complex cases it might be difficult to 
determine this so maybe the method in the video is more general 
purpose. It seems to have the capabilities to have a bit more 
intelligent checking though so yeah, this seems to be what I was 
looking for!


Thanks!



In any case





Re: Can anyone explain this?

2018-06-05 Thread Nicholas Wilson via Digitalmars-d

On Tuesday, 5 June 2018 at 08:12:54 UTC, Shachar Shemesh wrote:
I set up to find out what happens if the assert string throws. 
I have to admit I did not expect the result:


$ cat test.d
import std.stdio;
import core.exception;

void main() {
scope(failure) {
writeln("Not gonna happen");
}

try {
static string throwingFunc() {
throw new Exception("An exception");
}
assert(0==1, throwingFunc());
} catch(Exception ex) {
writeln("Exception");
} catch(AssertError ex) {
writeln("Assert");
}
}

$ ldc2 --version
LDC - the LLVM D compiler (1.8.0):
  based on DMD v2.078.3 and LLVM 5.0.1
...

$ ./test
Not gonna happen
object.Exception@test.d(11): An exception


applying a bit of lowering

int Dmain (int arc, const char** argv)
{
try return main();
catch (...) dumpThrowable(); // 3 dumps exception
}
void main() {
try {
try {
 static string throwingFunc() {
throw new Exception("An exception");
}
 __assert_fail(throwingFunc(),...); // 1 throws 
before assert throws

} catch(Exception ex) {
   writeln("Exception"); // Why is this not caught? 
I've no idea

   } catch(AssertError ex) {
  writeln("Assert"); // this is not caught because 
the thrown throwable is not an exception

  }
 }
 catch(...)
 {
writeln("Not gonna happen"); // 2 scope failure is run
  throw;
 }

}


Re: Can anyone explain this?

2018-06-05 Thread Andrea Fontana via Digitalmars-d

On Tuesday, 5 June 2018 at 08:12:54 UTC, Shachar Shemesh wrote:

I set up to find out what happens if the assert string throws.


From here: 
https://dlang.org/spec/expression.html#assert_expressions


[...]
8. Undefined Behavior: Once in an Invalid State the behavior of 
the continuing execution of the program is undefined.

[...]

[...]
Best Practices:
- Do not have side effects in either AssignExpression that 
subsequent code depends on.
- AssertExpressions are intended to detect bugs in the program, 
do not use for detecting input or environmental errors.
- Do not attempt to resume normal execution after an Assert 
Failure.

[...]

Anyway you can try to catch "Throwable" to understand what is 
going to happen (but it's not a good idea at all to keep it in a 
program)


Andrea


Re: Can anyone explain this?

2018-06-05 Thread Shachar Shemesh via Digitalmars-d

On 05/06/18 11:26, Nicholas Wilson wrote:
    writeln("Exception"); // Why is this not caught? I've no 
idea


That's the part I was referring to.


Re: Can anyone explain this?

2018-06-05 Thread Simen Kjærås via Digitalmars-d

On Tuesday, 5 June 2018 at 08:26:22 UTC, Nicholas Wilson wrote:
writeln("Assert"); // this is not caught because the thrown 
throwable is not an exception


Now that's plain false - If you replace the call to 
throwingFunc() with a string literal, you'll see it's properly 
caught. Also, the catch clause explicitly specifies AssertError, 
which as the name implies, is an Error, not an Exception.



This might just be a case of undefined behavior. According to 
https://dlang.org/spec/contracts.html:


"As a contract, an assert represents a guarantee that the code 
must uphold. Any failure of this expression represents a logic 
error in the code that must be fixed in the source code. A 
program for which the assert contract is false is, by definition, 
invalid, and therefore has undefined behaviour."


In short, what you're doing is UB, and the nasal demons are 
printing 'not gonna happen' to your console.


That also makes some sense with Andrea Fontana's comments:
- Do not have side effects in either AssignExpression that 
subsequent code depends on.
- Do not attempt to resume normal execution after an Assert 
Failure.



However, if we add catch (Throwable ex) to the list of catch 
statements, that *does* catch a regular object.Exception. Moving 
the catch (Exception) statement down the list does nothing. 
Adding another layer of try-catch also catches it (even with just 
catch (Exception ex)):


import std.stdio;
import core.exception;

unittest {
scope(failure) {
writeln("Not gonna happen");
}

try {
try {
static string throwingFunc() {
throw new Exception("An exception");
}
assert(0==1, throwingFunc());
} catch(AssertError ex) {
writeln("Assert");
} catch(Exception ex) {
writeln("Exception A");
}
} catch(Exception ex) {
writeln("Exception B");
}
}

So I'm stumped. It seems the exception handling is simply not 
setup correctly. This could be because of UB I guess, but I'd 
hope the AssertError would be thrown first in such a case.


--
  Simen


Re: Can anyone explain this?

2018-06-05 Thread Nicholas Wilson via Digitalmars-d

On Tuesday, 5 June 2018 at 09:03:03 UTC, Simen Kjærås wrote:

On Tuesday, 5 June 2018 at 08:26:22 UTC, Nicholas Wilson wrote:
writeln("Assert"); // this is not caught because the thrown 
throwable is not an exception


Now that's plain false - If you replace the call to 
throwingFunc() with a string literal, you'll see it's properly 
caught. Also, the catch clause explicitly specifies 
AssertError, which as the name implies, is an Error, not an 
Exception.




Whoops I meant _is_.

However, if we add catch (Throwable ex) to the list of catch 
statements, that *does* catch a regular object.Exception. 
Moving the catch (Exception) statement down the list does 
nothing. Adding another layer of try-catch also catches it 
(even with just catch (Exception ex)):


That does seem odd but is consistent with the implicit "try" 
surrounding Dmain inserted by the runtime.



import std.stdio;
import core.exception;

unittest {
scope(failure) {
writeln("Not gonna happen");
}

try {
try {
static string throwingFunc() {
throw new Exception("An exception");
}
assert(0==1, throwingFunc());
} catch(AssertError ex) {
writeln("Assert");
} catch(Exception ex) {
writeln("Exception A");
}
} catch(Exception ex) {
writeln("Exception B");
}
}

So I'm stumped. It seems the exception handling is simply not 
setup correctly. This could be because of UB I guess, but I'd 
hope the AssertError would be thrown first in such a case.


The assert error will never be thrown because one of the 
parameters to the __assert_fail throws. Its like as if you had 
written.


if (0==1)
{
string tmp = throwingFunc(); // throws
__assert_fail(tmp,__LINE__,...); // dead code.
}

Actually it may be the compiler doing something funky with 
assert(0, msg); being special (assert(0,...) since the spec says 
for assert any compile time expression == 0  has the effect of 
assert(0). i.e. assert(0==1); is the same as assert(0);).


Proof


import std.stdio;
import core.exception;
bool foo() { return false;} // mess with the compiler's reasoning 
about the truthiness of the assert

void main() {
scope(failure) {
writeln("Not gonna happen");
}

try {
static string throwingFunc() {
throw new Exception("An exception");
}
assert(foo(), throwingFunc());
} catch(Exception ex) {
writeln("Exception");
} catch(AssertError ex) {
writeln("Assert");
}
}

prints

Exception



Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Ethan via Digitalmars-d
I've come across this before with Binderoo, but now I've got 
really simple use cases.


Rather than having one unmaintainable mess of a file that handles 
everything (for a really egregious example, see 
std.datetime.systime which has the distinction of both its source 
code and documentation being unreadable), I decided to do 
something similar to C#'s partial classes and use mixin templates 
declared in other modules to complete the implementation.


This is all well and good until you get to dealing with function 
overloads.


Exhibit A: https://run.dlang.io/is/a85Lbq

As soon as you have an overload of a function declared in the 
base object you're mixing in to, any other overload mixed in will 
not resolve correctly. Great.


The core use case I derived this from is client/server message 
handling, and I plan on reusing mixins across client/server types 
since message handling will also require variables added in to 
the object to do so. Simple example: Handling Ping and Pong will 
require the Ping sender to start a timer and resolve it on 
receiving Pong. The partial class model is perfect for this, and 
mixins are the closest we have to this.


I submitted a bug with the above code, and it was "helpfully" 
shut down with a link to the documentation and workaround. 
Congratulations. That's not the use case here, and to be quite 
honest this is one of those examples where a #define macro would 
"just work". And I'm firmly of the view that *ANY* example of 
that should be dealt with at a language level in order to 
completely remove the argument of needing a preprocessor.


Exhibit B: https://run.dlang.io/is/s2BJUO

This one fired as soon as Binderoo tried to do its thing: Doing 
an allMembers pass of the object will list your entirely-mixed-in 
overload as a member, but attempting to get that member will 
resolve the symbol to void.


Great. So functions that otherwise completely resolve as a member 
of a class actually don't resolve as a member of a class? Huh? I 
don't even.


To see where I'm going with this, exhibit C: 
https://run.dlang.io/is/KWN9yA


Rather than mixin things one by one and manually handle errors 
and language shortcomings, I'm using helpers to wholesale add 
functionality to my object.


And, honestly, with this method, I am already seeing the 
workaround. Because I've had to do it a ton of times already with 
other templates. Run a search for 'mixin( "import' in Binderoo to 
see how many times I've had to get around the changes to template 
visibility rules. Rather than do that though, now I'll have to 
iterate over every member of a stored mixin and alias them in to 
the surrounding object.


Sigh.

I know that simply posting this will result in a thread of people 
offering workarounds. I don't need or want them. Why? Because the 
next person that tries to do this will have the same problems. 
And rather than the "correct" way to do this be voodoo knowledge 
found by a Google search if you're lucky, I would far prefer this 
thread become a discussion on how to improve mixins so that a DIP 
can be written and resolved. So that the next person can express 
language as simply as possible and have it all Just Work(TM).


Re: Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Mike Franklin via Digitalmars-d

On Tuesday, 5 June 2018 at 10:11:49 UTC, Ethan wrote:


Exhibit A: https://run.dlang.io/is/a85Lbq

[..snip..]
I submitted a bug with the above code, and it was "helpfully" 
shut down with a link to the documentation and workaround.


This looks like the bug report you are referring to:  
https://issues.dlang.org/show_bug.cgi?id=18944


I understand that the specification defines the current behavior 
and provides a workaround, but what's the justification for that 
behavior?  Is it hygiene?


I've been interested in improving mixins for reasons discussed in 
the interpolated strings PR 
(https://github.com/dlang/dmd/pull/7988) and this discussion 
about library-implemented properties 
(https://forum.dlang.org/post/mqveusvzkmkshrzws...@forum.dlang.org).


Perhaps there's an opportunity here for a language improvement 
that would help all of these use cases.


Mike




Re: Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 10:11:49 UTC, Ethan wrote:
And, honestly, with this method, I am already seeing the 
workaround. Because I've had to do it a ton of times already 
with other templates. Run a search for 'mixin( "import' in 
Binderoo to see how many times I've had to get around the 
changes to template visibility rules. Rather than do that 
though, now I'll have to iterate over every member of a stored 
mixin and alias them in to the surrounding object.


I've had to go nuclear, in fact, to get this working. And resort 
to string mixins.


https://run.dlang.io/is/O5PDaK

So it works. But it doesn't Just Work(TM).


Re: Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Simen Kjærås via Digitalmars-d

On Tuesday, 5 June 2018 at 10:11:49 UTC, Ethan wrote:

Exhibit A: https://run.dlang.io/is/a85Lbq

I submitted a bug with the above code, and it was "helpfully" 
shut down with a link to the documentation and workaround. 
Congratulations. That's not the use case here, and to be quite 
honest this is one of those examples where a #define macro 
would "just work". And I'm firmly of the view that *ANY* 
example of that should be dealt with at a language level in 
order to completely remove the argument of needing a 
preprocessor.


There's a reason for those rules in the language, namely function 
hijacking. This is an issue we take very seriously, and 
workarounds exists.


As you point out, the suggested workaround is aliasing each 
function in the mixin (you also say you don't want workarounds - 
bear with me, I'm building to a point). This can to some extent 
be encapsulated in a string mixin that's used alongside any 
template mixin:


string introduceSymbols(alias F)()
{
enum id = __traits(identifier, F);
return "static foreach (fn; __traits(allMembers, "~id~")) {"~
   "mixin(`alias `~fn~` = "~id~".`~fn~`;`);"~
   "}";
}

mixin foo!() foo_;
mixin(introduceSymbols!foo_);

This introduces complexity in that each mixin must be given a 
unique name at instantiation, another line must be included with 
every mixin, and the name must be repeated in the second line. 
This situation is less than optimal, and the compiler gives no 
help if you've forgotten a introduceSymbols line, or passed it 
the wrong name.


These issues can be ameliorated as in your other post here, by 
wrapping the template mixin statement as well. This leads to a 
host of other problems - how do you specify arguments to the 
mixin template? How do you deal with aliased mixin templates? 
These issues may possibly be fixed, but it's gonna get ugly.



Can we perhaps do better? Could we somehow say at the 
instantiation point 'please introduce all symbols in this mixin 
into the instantiation scope even if there are hijackings.'?  
Something like `mixin scope foo!();`? That seems possible to me. 
If we write a DIP for it, I've a good feeling about getting that 
into the language.


This issue shows up every now and then, so we know it's a real 
issue, and the workarounds are clunky. At the same time, the 
current behavior is there for a reason, and is very unlikely to 
change.


--
  Simen


Re: Can anyone explain this?

2018-06-05 Thread Nicholas Wilson via Digitalmars-d

On Tuesday, 5 June 2018 at 09:58:43 UTC, Nicholas Wilson wrote:

prints

Exception


https://issues.dlang.org/show_bug.cgi?id=18946


Re: stride in slices

2018-06-05 Thread Steven Schveighoffer via Digitalmars-d

On 6/4/18 5:52 PM, DigitalDesigns wrote:

On Monday, 4 June 2018 at 17:40:57 UTC, Dennis wrote:

On Monday, 4 June 2018 at 15:43:20 UTC, Steven Schveighoffer wrote:
Note, it's not going to necessarily be as efficient, but it's likely 
to be close.


-Steve


I've compared the range versions with a for-loop. For integers and 
longs or high stride amounts the time is roughly equal, but for bytes 
with low stride amounts it can be up to twice as slow.

https://run.dlang.io/is/BoTflQ

50 Mb array, type = byte, stride = 3, compiler = LDC -O4 -release
For-loop  18 ms
Fill(0)   33 ms
each! 33 ms

With stride = 13:
For-loop  7.3 ms
Fill(0)   7.5 ms
each! 7.8 ms



This is why I wanted to make sure! I would be using it for a stride of 2 
and it seems it might have doubled the cost for no other reason than 
using ranged. Ranges are great but one can't reason about what is 
happening in then as easy as a direct loop so I wanted to be sure. 
Thanks for running the test!


See later postings from Ethan and others. It's a matter of optimization 
being able to see the "whole thing". This is why for loops are sometimes 
better. It's not inherent with ranges, but if you use the right 
optimization flags, it's done as fast as if you hand-wrote it.


What I've found with D (and especially LDC) is that when you give the 
compiler everything to work with, it can do some seemingly magic things.


-Steve


Re: Simple tutorials for complex subjects

2018-06-05 Thread Kagamin via Digitalmars-d

On Sunday, 3 June 2018 at 16:25:29 UTC, Ethan wrote:
Step seven: In your receive function that takes a byte stream, 
put in a switch statement that looks a little bit like the 
following:


switch( msg.GetID )
{
static foreach( Message; ServerMessages )
{
case ObjectIDOf!Message:
Message deserialised = msg.FromBinary!Message;
this.receive( deserialised );
}
default:
break;
}


Why message detection is in receiver instead of infrastructure? 
And why not gather message types from receiver's interface with 
DbI (like WCF does)?


Re: stride in slices

2018-06-05 Thread Andrei Alexandrescu via Digitalmars-d

On 06/04/2018 07:08 PM, Ethan wrote:

On Monday, 4 June 2018 at 18:11:47 UTC, Steven Schveighoffer wrote:

BTW, do you have cross-module inlining on?


Just to drive this point home.

https://run.dlang.io/is/nrdzb0

Manually implemented stride and fill with everything forced inline. 
Otherwise, the original code is unchanged.


17 ms, 891 μs, and 6 hnsecs
15 ms, 694 μs, and 1 hnsec
15 ms, 570 μs, and 9 hnsecs

My new stride outperformed std.range stride, and the manual for-loop. 
And, because the third test uses the new stride, it also benefited. But 
interestingly runs every so slightly faster...


BTW I've had this thought for a long time to implement stride with a 
compile-time step... never got around to implementing it. It would 
easily generalize the existing code without too much work. Essentially 
the step would be a template parameter; if that is 0, then use a 
run-time stride. Most of the code works unchanged.


Re: Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Adam D. Ruppe via Digitalmars-d

On Tuesday, 5 June 2018 at 10:11:49 UTC, Ethan wrote:
As soon as you have an overload of a function declared in the 
base object you're mixing in to, any other overload mixed in 
will not resolve correctly. Great.


Yes, it is great, since this lets you selectively override 
behavior from a generic mixin template for a specific use. I like 
this.


But we might be able to change the rule so, for functions, it 
follows the overload rules with arguments instead of just going 
by name. That would let you add functions... but that's 
inconsistent with how D does child class inheritance too (you 
need to alias in overloads there as well), for better or for 
worse.


Perhaps adding something like `alias * = Base.*;` as a feature 
would be good. I kinda hate that. But the idea there would be to 
just add all of Base's things to the overload set. OK that 
basically sucks especially when there's multiple bases. but it 
would be fairly consistent.


pure functions cannot be removed, actually: pure vs. total

2018-06-05 Thread FeepingCreature via Digitalmars-d
I'm just posting to clear up the misunderstanding that a call to 
a pure function can be removed. Actually, even calls to strongly 
pure functions cannot always be removed. This is because there is 
one thing that a pure function can do that will change program 
behavior if it is removed, even if it does not change any global 
state whatsoever: it can simply never return.


void foo() pure { while (true) { } }

By the way, this led to an amusing Phobos bug involving a pure 
function (not) returning a struct with an enum member: 
https://github.com/dlang/dmd/pull/8013#pullrequestreview-110250441 and assert(false.repeat.any == true); :)


When a strongly pure function is called multiple times with the 
same parameter, all but the first call can be removed; this is 
because if it was going to not return, it would already have 
inf-looped the first time. pure lets you go from n to 1, but not 
from 1 to 0.


A pure function that returns a value for every possible parameter 
is called a total function. Unfortunately, there is no way to 
enforce totality in the compiler, due to the halting problem.




Re: D on top of Hacker News!

2018-06-05 Thread Dejan Lekic via Digitalmars-d

On Sunday, 3 June 2018 at 17:40:46 UTC, I love Ice Cream wrote:
Is D really a top 20 language? I don't remember seeing it 
anywhere close to the top 20.



https://www.tiobe.com/tiobe-index/ has them in 31


Top comment is kind of depressing.


The right place to look is https://www.tiobe.com/tiobe-index/d/

I agree with other comments regarding TIOBE - they are constantly 
changing how they do statistics so they are not relevant source 
at all. Just look where Kotlin is there and that should pretty 
much tell you everything. I know at least 10 large companies that 
are moving from Java/Scala to Kotlin, yet Kotlin is at the bottom 
50 table... Ridiculous...


Re: Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Stefan Koch via Digitalmars-d

On Tuesday, 5 June 2018 at 11:35:10 UTC, Ethan wrote:

On Tuesday, 5 June 2018 at 10:11:49 UTC, Ethan wrote:
And, honestly, with this method, I am already seeing the 
workaround. Because I've had to do it a ton of times already 
with other templates. Run a search for 'mixin( "import' in 
Binderoo to see how many times I've had to get around the 
changes to template visibility rules. Rather than do that 
though, now I'll have to iterate over every member of a stored 
mixin and alias them in to the surrounding object.


I've had to go nuclear, in fact, to get this working. And 
resort to string mixins.


https://run.dlang.io/is/O5PDaK

So it works. But it doesn't Just Work(TM).


avoid unrolling for-each mate.
you do that by enclosing the Tuple Argument in [Args].


Re: stride in slices

2018-06-05 Thread DigitalDesigns via Digitalmars-d
On Tuesday, 5 June 2018 at 13:05:56 UTC, Steven Schveighoffer 
wrote:

On 6/4/18 5:52 PM, DigitalDesigns wrote:

On Monday, 4 June 2018 at 17:40:57 UTC, Dennis wrote:
On Monday, 4 June 2018 at 15:43:20 UTC, Steven Schveighoffer 
wrote:
Note, it's not going to necessarily be as efficient, but 
it's likely to be close.


-Steve


I've compared the range versions with a for-loop. For 
integers and longs or high stride amounts the time is roughly 
equal, but for bytes with low stride amounts it can be up to 
twice as slow.

https://run.dlang.io/is/BoTflQ

50 Mb array, type = byte, stride = 3, compiler = LDC -O4 
-release

For-loop  18 ms
Fill(0)   33 ms
each! 33 ms

With stride = 13:
For-loop  7.3 ms
Fill(0)   7.5 ms
each! 7.8 ms



This is why I wanted to make sure! I would be using it for a 
stride of 2 and it seems it might have doubled the cost for no 
other reason than using ranged. Ranges are great but one can't 
reason about what is happening in then as easy as a direct 
loop so I wanted to be sure. Thanks for running the test!


See later postings from Ethan and others. It's a matter of 
optimization being able to see the "whole thing". This is why 
for loops are sometimes better. It's not inherent with ranges, 
but if you use the right optimization flags, it's done as fast 
as if you hand-wrote it.


What I've found with D (and especially LDC) is that when you 
give the compiler everything to work with, it can do some 
seemingly magic things.


-Steve


It would be nice if testing could be done. Maybe even profiling 
in unit tests to make sure ranges are within some margin of 
error(10%). One of the main reasons I don't use ranges is I 
simply don't have faith they will be as fast as direct encoding. 
While they might offer a slightly easier syntax I don't know what 
is going on under the hood so I can't reason about it(unless I 
look up the source). With a for loop, it is pretty much a wrapper 
on internal cpu logic so it will be near as fast as possible.


I suppose in the long run ranges do have the potential to out 
perform since they do abstract but there is no guarantee they 
will even come close. Having some "proof" that they are working 
well would ease my mind. As this thread shows, ranges have some 
major issues. Imagine having some code on your machine that is 
very performant but on another machine in a slightly different 
circumstances it runs poorly. Now, say it is the stride issue... 
One normally would not think of that being an issue so one will 
look in other areas and could waste times. At least with direct 
loops you pretty much get what you see. It is very easy for 
ranges to be slow but more difficult for them to be fast.




Re: pure functions cannot be removed, actually: pure vs. total

2018-06-05 Thread Stefan Koch via Digitalmars-d

On Tuesday, 5 June 2018 at 14:48:23 UTC, FeepingCreature wrote:
I'm just posting to clear up the misunderstanding that a call 
to a pure function can be removed. Actually, even calls to 
strongly pure functions cannot always be removed. This is 
because there is one thing that a pure function can do that 
will change program behavior if it is removed, even if it does 
not change any global state whatsoever: it can simply never 
return.


[...]


In that instance you can have false negatives. catgorizing total 
functions an non total.


But no false positives afaics.


Re: Simple tutorials for complex subjects

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 13:33:18 UTC, Kagamin wrote:

Why message detection is in receiver instead of infrastructure?


Because recursion. One of the messages I've written is a wrapper 
message for a multi-packet split message, and calls receive with 
the reconstructed byte buffer. Fairly elegant way to not 
special-case the thing that much.


And why not gather message types from receiver's interface with 
DbI (like WCF does)?


There already is design by introspection. But I don't parse a 
type, I parse an entire module. The switch statement is being 
built through the results of an introspective pass.


This is quite deliberate. I'm writing a large-scale maintainable 
codebase. Having everything in one file is a sure way to reduce 
maintainability and thus productivity of the programmers 
maintaining it. Getting D to favour lots of smaller files means 
getting creative.


I *could* put all the messages in an interface and inherit from 
it... but that's a fairly old-school way of thinking. I don't 
need a giant virtual function table to enforce implementing 
message types when I can use outside-the-box introspective tricks 
and compile down to nothing.


There's also a design advantage to going message-first here. I'm 
forcing the maintainers to think of the data before they get to 
implementation. The existence of a struct already explicitly 
creates one piece of data - the message ID. Anything else you put 
in there is up to you. And being structs, means that you don't 
constantly have to maintain function signatures each time you 
want to add a value to a message for example.


Re: pure functions cannot be removed, actually: pure vs. total

2018-06-05 Thread Steven Schveighoffer via Digitalmars-d

On 6/5/18 10:48 AM, FeepingCreature wrote:
I'm just posting to clear up the misunderstanding that a call to a pure 
function can be removed. Actually, even calls to strongly pure functions 
cannot always be removed. This is because there is one thing that a pure 
function can do that will change program behavior if it is removed, even 
if it does not change any global state whatsoever: it can simply never 
return.


void foo() pure { while (true) { } }

By the way, this led to an amusing Phobos bug involving a pure function 
(not) returning a struct with an enum member: 
https://github.com/dlang/dmd/pull/8013#pullrequestreview-110250441 and 
assert(false.repeat.any == true); :)


When a strongly pure function is called multiple times with the same 
parameter, all but the first call can be removed; this is because if it 
was going to not return, it would already have inf-looped the first 
time. pure lets you go from n to 1, but not from 1 to 0.


A pure function that returns a value for every possible parameter is 
called a total function. Unfortunately, there is no way to enforce 
totality in the compiler, due to the halting problem.




I'll repeat what I said in the PR where you made this similar comment, I 
don't think it is important to ensure a pure function that never returns 
is always called. Can you explain the benefit of such a thing?


We've all heard of optimizers that reduce "code that does nothing" down 
to just a return statement, foiling people who are expecting benchmarks 
to run properly, why is this any different?


I'm asking because it seems like we give up a really easy optimization 
for pure functions for the sake of pure infinite loop programs, which I 
suppose have some value, but not much value. Getting around the infinite 
loop elision would be pretty simple, just return an int.


On the flip side, if the compiler can figure out via introspection that 
some template function is strong pure and returns void, therefore it 
doesn't need to call it, that's a much bigger win than preserving the 
possible infinite loopiness that likely is a bug anyway.


Another observation: under the "infinite loops are important observable 
behavior" world-view, pure functions cannot be lazily evaluated either:


pure int foo() { /*infinite loop */}

void main(string[] args)
{
   auto a = foo;
   writeln("hi");
   if(args[1] == "printa")
  writeln(a);
}

With some optimizers, this can be rewritten:

writeln("hi");
if(args[1] == "printa")
   writeln(foo);

Which if foo is a *normally returning* function and not an infinite loop 
one, then this can save cycles in certain cases.


But under your world-view, the optimization is invalid, because foo 
might have an infinite loop, and then the observable behavior changes 
(instead of printing nothing and infinite looping, "hi" is printed, and 
infinite loops).


-Steve


Re: stride in slices

2018-06-05 Thread Steven Schveighoffer via Digitalmars-d

On 6/5/18 12:50 PM, DigitalDesigns wrote:

I suppose in the long run ranges do have the potential to out perform 
since they do abstract but there is no guarantee they will even come 
close. Having some "proof" that they are working well would ease my 
mind. As this thread shows, ranges have some major issues. 


Just to point it out again, Ethan's numbers:

17 ms, 891 μs, and 6 hnsecs // for loop
15 ms, 694 μs, and 1 hnsec  // fill
15 ms, 570 μs, and 9 hnsecs // each

I think ranges are doing just fine. You just need the cross-module 
inlining turned on.


Imagine 
having some code on your machine that is very performant but on another 
machine in a slightly different circumstances it runs poorly. Now, say 
it is the stride issue... One normally would not think of that being an 
issue so one will look in other areas and could waste times. At least 
with direct loops you pretty much get what you see. It is very easy for 
ranges to be slow but more difficult for them to be fast.


The same can be said even with direct loops. There are no guarantees of 
course that one type of programming style is going to outperform another 
on all platforms and all compilers. My experience is that things that 
seem like they should be slower can sometimes be faster, and vice versa. 
It depends on so many factors, and the best thing to do is test and 
observe in each situation.


-Steve


Re: stride in slices

2018-06-05 Thread Timon Gehr via Digitalmars-d

On 05.06.2018 18:50, DigitalDesigns wrote:
With a for loop, it is pretty much a wrapper on internal cpu logic so it 
will be near as fast as possible.


This is not even close to being true for modern CPUs. There are a lot of 
architectural and micro-architectural details that affect performance 
but are not visible or accessible in your for loop. If you care about 
performance, you will need to test anyway, as even rather sophisticated 
models of CPU performance don't get everything right.


Also, it is often not necessary to be "as fast as possible". It is 
usually more helpful to figure out where the bottleneck is for your code 
and concentrate optimization effort there, which you can do more 
effectively if you can save time and effort for the remaining parts of 
your program by writing simple and obviously correct range-based code, 
which often will be fast as well.


Re: stride in slices

2018-06-05 Thread DigitalDesigns via Digitalmars-d

On Tuesday, 5 June 2018 at 18:46:41 UTC, Timon Gehr wrote:

On 05.06.2018 18:50, DigitalDesigns wrote:
With a for loop, it is pretty much a wrapper on internal cpu 
logic so it will be near as fast as possible.


This is not even close to being true for modern CPUs. There are 
a lot of architectural and micro-architectural details that 
affect performance but are not visible or accessible in your 
for loop. If you care about performance, you will need to test 
anyway, as even rather sophisticated models of CPU performance 
don't get everything right.


Those optimizations are not part of the instruction set so are 
irrelevant. They will occur with ranges too.


For loops HAVE a direct cpu semantic! Do you doubt this?


Cpu's do not have range semantics. Ranges are layers on top of 
compiler semantics... you act like they are equivalent, they are 
not! All range semantics must go through the library code then to 
the compiler then to cpu. For loops of all major systems 
languages go almost directly to cpu instructions.


for(int i = 0; i < N; i++)

translates in to either increment and loop or jump instructions.

There is absolutely no reason why any decent compiler would not 
use what the cpu has to offer. For loops are language semantics, 
Ranges are library semantics. To pretend they are equivalent is 
wrong and no amount of justifying will make them the same. I 
actually do not know even any commercial viable cpu exists 
without loop semantics. I also no of no commercially viable 
compiler that does not wrap those instructions in a for loop(or 
while, or whatever) like syntax that almost maps directly to the 
cpu instructions.


Also, it is often not necessary to be "as fast as possible". It 
is usually more helpful to figure out where the bottleneck is 
for your code and concentrate optimization effort there, which 
you can do more effectively if you can save time and effort for 
the remaining parts of your program by writing simple and 
obviously correct range-based code, which often will be fast as 
well.


It's also often not necessary to be "as slow as possible". I'm 
not asking for about generalities but specifics. It's great to 
make generalizations about how things should be but I would like 
to know how they are. Maybe in theory ranges could be more 
optimal than other semantics but theory never equals practice.






Re: stride in slices

2018-06-05 Thread Adam D. Ruppe via Digitalmars-d

On Tuesday, 5 June 2018 at 19:05:27 UTC, DigitalDesigns wrote:

For loops HAVE a direct cpu semantic! Do you doubt this?


What are they?

And for bonus points, are they actually used by compilers?

Then the final question: is the generated code any different than 
inlined ranges?


Re: stride in slices

2018-06-05 Thread Steven Schveighoffer via Digitalmars-d

On 6/5/18 3:05 PM, DigitalDesigns wrote:

It's also often not necessary to be "as slow as possible". I'm not 
asking for about generalities but specifics. It's great to make 
generalizations about how things should be but I would like to know how 
they are. Maybe in theory ranges could be more optimal than other 
semantics but theory never equals practice.


Again, I want to stress, ranges are not "as slow as possible", and it's 
clear from the numbers posted here that they are faster than for loops 
in practice, at least for this example.


-Steve



Re: stride in slices

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 19:05:27 UTC, DigitalDesigns wrote:

For loops HAVE a direct cpu semantic! Do you doubt this?


...

Right. If you're gonna keep running your mouth off. How about 
looking at some disassembly then.


for(auto i=0; iUsing ldc -O4 -release for x86_64 processors, the initialiser 
translates to:


mov byte ptr [rbp + rcx], 0

The comparison translates to:

cmp r13, rcx
ja .LBB0_2

And the increment and store translates to:

mov byte ptr [rbp + rcx], 0
movsxd rcx, eax
add eax, 3

So. It uses three of the most basic instructions you can think 
of: mov, cmp, j, add.


Now, what might you ask are the instructions that a range 
compiles down to when everything is properly inlined?


The initialisation, since it's a function, pulls from the stack.

mov rax, qword ptr [rsp + 16]
movsxd rcx, dword ptr [rsp + 32]

But the comparison looks virtually identical.

cmp rax, rcx
jb .LBB2_4

But how does it do the add? With some register magic.

movsxd rcx, edx
lea edx, [rcx + r9]

Now, what that looks like it's doing to me is combing the pointer 
load and index increment in to two those two instructions. One 
instruction less than the flat for loop.


In conclusion. The semantics you talk about are literally some of 
the most basic instructions in computing; and that escaping the 
confines of a for loop for a foreach loop can let the compiler 
generate more efficient code than 50-year-old compsci concepts 
can.


Re: D on top of Hacker News!

2018-06-05 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, June 05, 2018 15:09:56 Dejan Lekic via Digitalmars-d wrote:
> On Sunday, 3 June 2018 at 17:40:46 UTC, I love Ice Cream wrote:
> >> Is D really a top 20 language? I don't remember seeing it
> >> anywhere close to the top 20.
> >>
> >> https://www.tiobe.com/tiobe-index/ has them in 31
> >
> > Top comment is kind of depressing.
>
> The right place to look is https://www.tiobe.com/tiobe-index/d/
>
> I agree with other comments regarding TIOBE - they are constantly
> changing how they do statistics so they are not relevant source
> at all. Just look where Kotlin is there and that should pretty
> much tell you everything. I know at least 10 large companies that
> are moving from Java/Scala to Kotlin, yet Kotlin is at the bottom
> 50 table... Ridiculous...

The TIOBE has never been a measurement of how much any given language is
used. At best, it's been a measurement of which languages folks have been
searching for. That can tell you something, but you have to understand what
it's measuring to have any clue what it does tell you. And of course,
because of how difficult it is to measure search results for a particular
language, they keep changing their criteria. The result is that while the
tiobe index may be interesting, it must be taken with a very large grain of
salt - and that's without getting into any discussions of how valid it is or
isn't to use search results from google to do the measuring.

- Jonathan M Davis



Re: Mixin templates are a pain at best, useless at worst for any non-trivial use case

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 12:08:58 UTC, Simen Kjærås wrote:
There's a reason for those rules in the language, namely 
function hijacking. This is an issue we take very seriously, 
and workarounds exists.


So serious that there is no meaningful error message?

These issues can be ameliorated as in your other post here, by 
wrapping the template mixin statement as well. This leads to a 
host of other problems - how do you specify arguments to the 
mixin template? How do you deal with aliased mixin templates? 
These issues may possibly be fixed, but it's gonna get ugly.


I've posted on these newsgroups literally within the last three 
weeks about dealing with multiple different argument types 
(parsing template parameters) and aliases (__traits( identifier, 
Symbol ) does not match Symbol.stringof if it is an alias). As 
such, that's purely within the realms of "solvable by the 
programmer with new idioms" as I see it.


This thing I'm posting about is solvable by giving up and 
generating a string to treat as code. ie the nuclear option when 
everything else in the language is unsuitable.


This issue shows up every now and then, so we know it's a real 
issue, and the workarounds are clunky. At the same time, the 
current behavior is there for a reason, and is very unlikely to 
change.


https://dlang.org/spec/template-mixin.html

1. A TemplateMixin takes an arbitrary set of declarations from 
the body of a TemplateDeclaration and inserts them into the 
current context.


Everything you've talked about here directly conflicts with point 
number 1 of the mixin template spec. Point 3 of the spec makes a 
note of the implementation not actually doing the direct 
copy/paste that it mentions and instead embeds it in to a nested 
scope and imports it after the fact. Yet there appears to be 
quite a number of "except for this" clauses that aren't made 
clear. Clearly something has gone wrong somewhere along the way.


So by that token: How many real world dollars have been wasted on 
function hijacking? Is this something a corporate client has been 
adamant about? Bringing up the #define macro analogy again, these 
are clearly similar problems that can happen in C/C++. So is it 
more of an ideological stand than a real-world one?


Re: pure functions cannot be removed, actually: pure vs. total

2018-06-05 Thread FeepingCreature via Digitalmars-d
On Tuesday, 5 June 2018 at 17:47:15 UTC, Steven Schveighoffer 
wrote:
Another observation: under the "infinite loops are important 
observable behavior" world-view, pure functions cannot be 
lazily evaluated either:


pure int foo() { /*infinite loop */}

void main(string[] args)
{
   auto a = foo;
   writeln("hi");
   if(args[1] == "printa")
  writeln(a);
}

With some optimizers, this can be rewritten:

writeln("hi");
if(args[1] == "printa")
   writeln(foo);

Which if foo is a *normally returning* function and not an 
infinite loop one, then this can save cycles in certain cases.


But under your world-view, the optimization is invalid, because 
foo might have an infinite loop, and then the observable 
behavior changes (instead of printing nothing and infinite 
looping, "hi" is printed, and infinite loops).




That's correct, this optimization is invalid. The only 
optimization that can arise from foo being pure is *subsequent* 
calls to foo being removed.



-Steve


On Tuesday, 5 June 2018 at 17:47:15 UTC, Steven Schveighoffer 
wrote:
I'll repeat what I said in the PR where you made this similar 
comment, I don't think it is important to ensure a pure 
function that never returns is always called. Can you explain 
the benefit of such a thing?


We've all heard of optimizers that reduce "code that does 
nothing" down to just a return statement, foiling people who 
are expecting benchmarks to run properly, why is this any 
different?




Frankly speaking, we should not implement optimizations merely on 
the basis that we cannot immediately think of a case where they 
fail. For instance, a practical function that loops forever would 
be a find() call on an infinite range, such as a range returned 
by .repeat or .generate.


Re: pure functions cannot be removed, actually: pure vs. total

2018-06-05 Thread Steven Schveighoffer via Digitalmars-d

On 6/5/18 5:03 PM, FeepingCreature wrote:

On Tuesday, 5 June 2018 at 17:47:15 UTC, Steven Schveighoffer wrote:
Another observation: under the "infinite loops are important 
observable behavior" world-view, pure functions cannot be lazily 
evaluated either:


pure int foo() { /*infinite loop */}

void main(string[] args)
{
   auto a = foo;
   writeln("hi");
   if(args[1] == "printa")
  writeln(a);
}

With some optimizers, this can be rewritten:

writeln("hi");
if(args[1] == "printa")
   writeln(foo);

Which if foo is a *normally returning* function and not an infinite 
loop one, then this can save cycles in certain cases.


But under your world-view, the optimization is invalid, because foo 
might have an infinite loop, and then the observable behavior changes 
(instead of printing nothing and infinite looping, "hi" is printed, 
and infinite loops).




That's correct, this optimization is invalid. The only optimization that 
can arise from foo being pure is *subsequent* calls to foo being removed.


I think Haskell would disagree with you: 
https://wiki.haskell.org/Lazy_evaluation



On Tuesday, 5 June 2018 at 17:47:15 UTC, Steven Schveighoffer wrote:
I'll repeat what I said in the PR where you made this similar comment, 
I don't think it is important to ensure a pure function that never 
returns is always called. Can you explain the benefit of such a thing?


We've all heard of optimizers that reduce "code that does nothing" 
down to just a return statement, foiling people who are expecting 
benchmarks to run properly, why is this any different?




Frankly speaking, we should not implement optimizations merely on the 
basis that we cannot immediately think of a case where they fail. For 
instance, a practical function that loops forever would be a find() call 
on an infinite range, such as a range returned by .repeat or .generate.


But a call to find doesn't "do nothing". It takes a range and returns a 
range.


We are specifically talking about strong-pure functions that return 
void, or even strong pure functions whose return value is ignored.


And yes, we can actually prove that calls to pure functions do nothing 
based on the rules of pure functions, which is why the optimization is 
easy to prove correct. It's one of the reasons pure optimizations are 
much easier to reason about.


However, if we have a wrinkle of "we have to make sure infinite loops 
execute their thing", then many pure optimizations get thrown out the 
window.


-Steve


Re: stride in slices

2018-06-05 Thread DigitalDesigns via Digitalmars-d

On Tuesday, 5 June 2018 at 20:07:06 UTC, Ethan wrote:

On Tuesday, 5 June 2018 at 19:05:27 UTC, DigitalDesigns wrote:

For loops HAVE a direct cpu semantic! Do you doubt this?


...

Right. If you're gonna keep running your mouth off. How about 
looking at some disassembly then.


for(auto i=0; iUsing ldc -O4 -release for x86_64 processors, the initialiser 
translates to:


mov byte ptr [rbp + rcx], 0

The comparison translates to:

cmp r13, rcx
ja .LBB0_2

And the increment and store translates to:

mov byte ptr [rbp + rcx], 0
movsxd rcx, eax
add eax, 3

So. It uses three of the most basic instructions you can think 
of: mov, cmp, j, add.


Now, what might you ask are the instructions that a range 
compiles down to when everything is properly inlined?


The initialisation, since it's a function, pulls from the stack.

mov rax, qword ptr [rsp + 16]
movsxd rcx, dword ptr [rsp + 32]

But the comparison looks virtually identical.

cmp rax, rcx
jb .LBB2_4

But how does it do the add? With some register magic.

movsxd rcx, edx
lea edx, [rcx + r9]

Now, what that looks like it's doing to me is combing the 
pointer load and index increment in to two those two 
instructions. One instruction less than the flat for loop.


In conclusion. The semantics you talk about are literally some 
of the most basic instructions in computing; and that escaping 
the confines of a for loop for a foreach loop can let the 
compiler generate more efficient code than 50-year-old compsci 
concepts can.


Ok asshat! You still don't get it! I didn't say ranges would not 
compile down to the same thing! Do you have trouble understanding 
the English language?


You don't seem to get the concept where ranges are library 
solutions and someone can some along at any time and modify some 
code and WHAM! They no longer compile down to your efficient 
precious instructions. That is far more unlikely to occur with 
language semantics. Why is that so difficult for you to 
understand you sure do you have an attitude for someone that has 
difficulty with English.





Re: stride in slices

2018-06-05 Thread Steven Schveighoffer via Digitalmars-d

On 6/5/18 5:22 PM, DigitalDesigns wrote:

On Tuesday, 5 June 2018 at 20:07:06 UTC, Ethan wrote:


In conclusion. The semantics you talk about are literally some of the 
most basic instructions in computing; and that escaping the confines 
of a for loop for a foreach loop can let the compiler generate more 
efficient code than 50-year-old compsci concepts can.


Ok asshat! You still don't get it! I didn't say ranges would not compile 
down to the same thing! Do you have trouble understanding the English 
language?


Nope, he doesn't. Look at what you said:

"Maybe in theory ranges could be more optimal than other semantics but 
theory never equals practice. "


And now you have been shown (multiple times) that in practice ranges in 
fact outperform for loops. Including the assembly to prove it (which 
helps with this comment: "Having some "proof" that they are working well 
would ease my mind.")


So tone down the attitude, you got what you *clearly* asked for but seem 
reluctant to acknowledge. Ranges are good, for loops are good too, but 
not as. So maybe you should just use ranges and use the correct 
optimization flags and call it a day? Or else use for loops and accept 
that even though they may not run as quickly, they are "safer" to use 
since some malicious coder could come along and add in sleeps inside the 
std.algorithm functions.


-Steve


Re: D on top of Hacker News!

2018-06-05 Thread I love Ice Cream via Digitalmars-d

On Tuesday, 5 June 2018 at 20:15:07 UTC, Jonathan M Davis wrote:
On Tuesday, June 05, 2018 15:09:56 Dejan Lekic via 
Digitalmars-d wrote:

On Sunday, 3 June 2018 at 17:40:46 UTC, I love Ice Cream wrote:
>> Is D really a top 20 language? I don't remember seeing it 
>> anywhere close to the top 20.

>>
>> https://www.tiobe.com/tiobe-index/ has them in 31
>
> Top comment is kind of depressing.

The right place to look is https://www.tiobe.com/tiobe-index/d/

I agree with other comments regarding TIOBE - they are 
constantly changing how they do statistics so they are not 
relevant source at all. Just look where Kotlin is there and 
that should pretty much tell you everything. I know at least 
10 large companies that are moving from Java/Scala to Kotlin, 
yet Kotlin is at the bottom 50 table... Ridiculous...


The TIOBE has never been a measurement of how much any given 
language is used. At best, it's been a measurement of which 
languages folks have been searching for. That can tell you 
something, but you have to understand what it's measuring to 
have any clue what it does tell you. And of course, because of 
how difficult it is to measure search results for a particular 
language, they keep changing their criteria. The result is that 
while the tiobe index may be interesting, it must be taken with 
a very large grain of salt - and that's without getting into 
any discussions of how valid it is or isn't to use search 
results from google to do the measuring.


- Jonathan M Davis


And all of the other metrics done by other groups that was 
provided that paints a similar picture?


http://githut.info/

http://pypl.github.io/PYPL.html

http://sogrady-media.redmonk.com/sogrady/files/2018/03/lang.rank_.118.png

https://spectrum.ieee.org/computing/software/the-2017-top-programming-languages

https://insights.stackoverflow.com/survey/2016

I'm not really intending to crap on anyone here. It's just the 
dismissal of a collection of data all pointing towards one 
particular conclusion is a bit strange. It seems like the 
interest in D is going down not up. I mean it could have a 
renaissance, but I'd imagine some work would have to be put into 
that to make it happen.


Re: stride in slices

2018-06-05 Thread DigitalDesigns via Digitalmars-d

On Tuesday, 5 June 2018 at 21:52:03 UTC, Ethan wrote:

On Tuesday, 5 June 2018 at 21:22:27 UTC, DigitalDesigns wrote:

Ok asshat!


Take it to reddit. Back your arguments up with actual knowledge 
and intelligence, not unfounded agression.


You are an idiot! You obviously do not understand basic logic. 
Unfounded aggression? Yep, way to see how you didn't start it! 
Must be nice being the bully!


Re: stride in slices

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 21:22:27 UTC, DigitalDesigns wrote:

Ok asshat!


Take it to reddit. Back your arguments up with actual knowledge 
and intelligence, not unfounded agression.


Re: stride in slices

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 21:54:20 UTC, DigitalDesigns wrote:

You are an idiot!


Take it to reddit. Back your arguments up with actual knowledge 
and intelligence, not unfounded agression.


Re: stride in slices

2018-06-05 Thread DigitalDesigns via Digitalmars-d

On Tuesday, 5 June 2018 at 19:18:15 UTC, Adam D. Ruppe wrote:

On Tuesday, 5 June 2018 at 19:05:27 UTC, DigitalDesigns wrote:

For loops HAVE a direct cpu semantic! Do you doubt this?


What are they?

And for bonus points, are they actually used by compilers?

Then the final question: is the generated code any different 
than inlined ranges?


It doesn't matter! The issue that I said was not that ranges were 
slower but that ranges exist on an abstract on top of language 
semantics! that means that they can never be faster than the 
language itself! Anything that a range does can never be faster 
than doing it by hand.


This is not a hard concept to understand. I know everyone wants 
to defend their precious ranges but what happens is irrelevant in 
some particular case. Ranges could be 100x faster in some 
specific case but it doesn't change the fact that they are an 
abstraction on top of the language, not in the language.


I've already pointed out, and made it clear, I will do it one 
last time:


There is no guarantee(doesn't have to be 100% by the rule of god) 
by the compiler that a ranges performance will even come close to 
hand written code or that it won't all of a sudden change when 
someone decides to "optimize" it and actually makes it worse! 
These problems are far less likely to occur in a well established 
language semantic.


I can't believe people are really defending library solutions as 
not having these issues, but I guess that is the nature of most 
humans.




Re: stride in slices

2018-06-05 Thread Ethan via Digitalmars-d

On Tuesday, 5 June 2018 at 22:20:08 UTC, DigitalDesigns wrote:
It doesn't matter! The issue that I said was not that ranges 
were slower but that ranges exist on an abstract on top of 
language semantics! that means that they can never be faster 
than the language itself! Anything that a range does can never 
be faster than doing it by hand.


This is the best part. Ranges *ARE* a language semantic.

https://tour.dlang.org/tour/en/basics/ranges


Re: stride in slices

2018-06-05 Thread DigitalDesigns via Digitalmars-d
On Tuesday, 5 June 2018 at 21:35:03 UTC, Steven Schveighoffer 
wrote:

On 6/5/18 5:22 PM, DigitalDesigns wrote:

On Tuesday, 5 June 2018 at 20:07:06 UTC, Ethan wrote:


In conclusion. The semantics you talk about are literally 
some of the most basic instructions in computing; and that 
escaping the confines of a for loop for a foreach loop can 
let the compiler generate more efficient code than 
50-year-old compsci concepts can.


Ok asshat! You still don't get it! I didn't say ranges would 
not compile down to the same thing! Do you have trouble 
understanding the English language?


Nope, he doesn't. Look at what you said:

"Maybe in theory ranges could be more optimal than other 
semantics but theory never equals practice. "


And now you have been shown (multiple times) that in practice 
ranges in fact outperform for loops. Including the assembly to 
prove it (which helps with this comment: "Having some "proof" 
that they are working well would ease my mind.")


No, you have shown a few fucking cases, why are you guys 
attacking me for being dense?


You can't prove that ranges are more optimal than direct 
semantics! Do it! I'd like to see you try!



So tone down the attitude, you got what you *clearly* asked for 
but seem reluctant to acknowledge. Ranges are good, for loops 
are good too, but not as. So maybe you should just use ranges 
and use the correct optimization flags and call it a day? Or 
else use for loops and accept that even though they may not run 
as quickly, they are "safer" to use since some malicious coder 
could come along and add in sleeps inside the std.algorithm 
functions.


-Steve


What it seems is that a few of you are upset because I didn't bow 
down to your precious range semantics and ask for clarification. 
At first I was jumped on then someone did some tests and found 
out that it wasn't so rosy like everyone thought. Of course, the 
work around is to force optimizations that fix the problem when 
the problem doesn't exist in for loops. Then you come along and 
tell me that specific cases prove the general case... that is 
real dense.


You know, it takes two to have an attitude! I asked for 
information regarding stride. I got the range version, it turned 
out to be slower in some corner case for some bizarre reason. I 
was then told it required optimizations(why? That is fishy why 
the corner cause would be 200% slower for a weird edge case) and 
then I was told that ranges are always faster(which is what you 
just said because you act like one example proves everything). 
Every step of the way I am told "don't worry". You've already 
stepped in the shit once and you expect me to believe everything 
you say?


Why is it so hard to have a test suite that checks the 
performance of range constructs instead of just getting me to 
believe you? Huh? Do you really think I'm suppose to believe 
every thing any asshat says on the net just because they want me 
to? Back up your beliefs, that simple. Provide timings for all 
the range functions in various combinations and give me a worse 
case scenario compared to their equivalent hand-coded versions. 
Once you do that then I will be able to make an informed decision 
rather than doing what you really want, which is except your 
world as authority regardless of the real truth.







Re: stride in slices

2018-06-05 Thread aberba via Digitalmars-d

On Tuesday, 5 June 2018 at 22:28:44 UTC, DigitalDesigns wrote:
On Tuesday, 5 June 2018 at 21:35:03 UTC, Steven Schveighoffer 
wrote:

[...]



[...]
Does ranges not evaluate lazily on some cases. So it'll avoid 
unnecessary work...and be much faster and efficient. If I'm 
correct.


[...]




Re: D on top of Hacker News!

2018-06-05 Thread bachmeier via Digitalmars-d

On Tuesday, 5 June 2018 at 21:53:51 UTC, I love Ice Cream wrote:

On Tuesday, 5 June 2018 at 20:15:07 UTC, Jonathan M Davis wrote:
On Tuesday, June 05, 2018 15:09:56 Dejan Lekic via 
Digitalmars-d wrote:
On Sunday, 3 June 2018 at 17:40:46 UTC, I love Ice Cream 
wrote:
>> Is D really a top 20 language? I don't remember seeing it 
>> anywhere close to the top 20.

>>
>> https://www.tiobe.com/tiobe-index/ has them in 31
>
> Top comment is kind of depressing.

The right place to look is 
https://www.tiobe.com/tiobe-index/d/


I agree with other comments regarding TIOBE - they are 
constantly changing how they do statistics so they are not 
relevant source at all. Just look where Kotlin is there and 
that should pretty much tell you everything. I know at least 
10 large companies that are moving from Java/Scala to Kotlin, 
yet Kotlin is at the bottom 50 table... Ridiculous...


The TIOBE has never been a measurement of how much any given 
language is used. At best, it's been a measurement of which 
languages folks have been searching for. That can tell you 
something, but you have to understand what it's measuring to 
have any clue what it does tell you. And of course, because of 
how difficult it is to measure search results for a particular 
language, they keep changing their criteria. The result is 
that while the tiobe index may be interesting, it must be 
taken with a very large grain of salt - and that's without 
getting into any discussions of how valid it is or isn't to 
use search results from google to do the measuring.


- Jonathan M Davis


And all of the other metrics done by other groups that was 
provided that paints a similar picture?


http://githut.info/

http://pypl.github.io/PYPL.html

http://sogrady-media.redmonk.com/sogrady/files/2018/03/lang.rank_.118.png

https://spectrum.ieee.org/computing/software/the-2017-top-programming-languages

https://insights.stackoverflow.com/survey/2016

I'm not really intending to crap on anyone here. It's just the 
dismissal of a collection of data all pointing towards one 
particular conclusion is a bit strange. It seems like the 
interest in D is going down not up. I mean it could have a 
renaissance, but I'd imagine some work would have to be put 
into that to make it happen.


The first link shows D having more repos. The third doesn't show 
changes in language popularity over time. I can't find any info 
about D usage over time in the other three links. The Stack 
Overflow survey isn't going to be informative anyway because most 
activity for D occurs here, not on SO, so it wouldn't be 
representative.


Re: stride in slices

2018-06-05 Thread Timon Gehr via Digitalmars-d

On 05.06.2018 21:05, DigitalDesigns wrote:

On Tuesday, 5 June 2018 at 18:46:41 UTC, Timon Gehr wrote:

On 05.06.2018 18:50, DigitalDesigns wrote:
With a for loop, it is pretty much a wrapper on internal cpu logic so 
it will be near as fast as possible.


This is not even close to being true for modern CPUs. There are a lot 
of architectural and micro-architectural details that affect 
performance but are not visible or accessible in your for loop. If you 
care about performance, you will need to test anyway, as even rather 
sophisticated models of CPU performance don't get everything right.


Those optimizations are not part of the instruction set so are 
irrelevant. They will occur with ranges too.

...


I was responding to claims that for loops are basically a wrapper on 
internal CPU logic and nearly as fast as possible. Both of those claims 
were wrong.



For loops HAVE a direct cpu semantic! Do you doubt this?
...


You'd have to define what that means. (E.g., Google currently shows no 
hits for "direct CPU semantics".)




Cpu's do not have range semantics. Ranges are layers on top of compiler 
semantics... you act like they are equivalent, they are not!


I don't understand why you bring this up nor what you think it means.

The compiler takes a program and produces some machine code that has the 
right behavior. Performance is usually not formally specified. In terms 
of resulting behavior, code with explicit for loops and range-based code 
may have identical semantics. Which one executes faster depends on 
internal details of the compiler and the target architecture, and it may 
change over time, e.g. between compiler releases.


All range 
semantics must go through the library code then to the compiler then to 
cpu. For loops of all major systems languages go almost directly to cpu 
instructions.


for(int i = 0; i < N; i++)

translates in to either increment and loop or jump instructions.
...


Sure, or whatever else the compiler decides to do. It might even be 
translated into a memcpy call. Even if you want to restrict yourself to 
use only for loops, my point stands. Write maintainable code by default 
and let the compiler do what it does. Then optimize further in those 
cases where the resulting code is actually too slow. Test for 
performance regressions.


There is absolutely no reason why any decent compiler would not use what 
the cpu has to offer. For loops are language semantics, Ranges are 
library semantics.


Not really. Also, irrelevant.

To pretend they are equivalent is wrong and no amount 
of justifying will make them the same.


Again, I don't think this point is part of this discussion.

I actually do not know even any 
commercial viable cpu exists without loop semantics.


What does it mean for a CPU to have "loop semantics"? CPUs typically 
have an instruction pointer register and possibly some built-in 
instructions to manipulate said instruction pointer. x86 has some 
built-in loop instructions, but I think they are just there for legacy 
support and not actually something you want to use in performant code.


I also no of no 
commercially viable compiler that does not wrap those instructions in a 
for loop(or while, or whatever) like syntax that almost maps directly to 
the cpu instructions.

...


The compiler takes your for loop and generates some machine code. I 
don't think there is a "commercially viable" compiler that does not 
sometimes do things that are not direct. And even then, there is no very 
simple mapping from CPU instructions to observed performance, so the 
entire point is a bit moot.


Also, it is often not necessary to be "as fast as possible". It is 
usually more helpful to figure out where the bottleneck is for your 
code and concentrate optimization effort there, which you can do more 
effectively if you can save time and effort for the remaining parts of 
your program by writing simple and obviously correct range-based code, 
which often will be fast as well.


It's also often not necessary to be "as slow as possible".


This seems to be quoting an imaginary person. My point is that to get 
even faster code, you need to spend effort and often get lower 
maintainability. This is not always a good trade-off, in particular if 
the optimization does not improve performance a lot and/or the code in 
question is not executed very often.


I'm not 
asking for about generalities but specifics. It's great to make 
generalizations about how things should be but I would like to know how 
they are.


That's a bit unspecific.

Maybe in theory ranges could be more optimal than other 
semantics but theory never equals practice.




I don't know who this is addressed to. My point was entirely practical.


Phobos, minimal runtime, -betterC compatibility documentation

2018-06-05 Thread Arun Chandrasekaran via Digitalmars-d
I'm more interested in no/minimal runtime[1] than -betterC for my 
use cases.


I think it will be good to have the document mention if the 
function is supported without the druntime and/or with -betterC. 
This documentation can be the module level or function level. Is 
this possible and/or is it worth it?


I understand that using druntime function with -betterC will make 
the compiler throw error. But it will be good to know it up front 
via doc if a function uses druntime or not.


[1] https://dlang.org/changelog/2.079.0.html#minimal_runtime


Re: Phobos, minimal runtime, -betterC compatibility documentation

2018-06-05 Thread Mike Franklin via Digitalmars-d
On Wednesday, 6 June 2018 at 01:34:13 UTC, Arun Chandrasekaran 
wrote:
I'm more interested in no/minimal runtime[1] than -betterC for 
my use cases.


I think it will be good to have the document mention if the 
function is supported without the druntime and/or with 
-betterC. This documentation can be the module level or 
function level. Is this possible and/or is it worth it?


I understand that using druntime function with -betterC will 
make the compiler throw error. But it will be good to know it 
up front via doc if a function uses druntime or not.


[1] https://dlang.org/changelog/2.079.0.html#minimal_runtime


What we actually need is to have the runtime itself to be 
well-documented.  In doing so, one would be able to see which 
features are implemented in the runtime and which features 
aren't, so what is and isn't supported in a "minimal runtime" 
would be self-evident.  In lew of that, however, I'll refer you 
to documentation "object", "core", and "rt" here:  
https://dlang.org/phobos/index.html.  Another good resource is 
https://wiki.dlang.org/Runtime_Hooks;  it's outdated, but still 
relevant.


Please also understand that one of the primary use cases for the 
"minimal runtime" changes in 2.079 is to allow users to port the 
runtime to a new platform incrementally in a pay-as-you-go 
fashion.  For that, you'll need to learn the details of the 
runtime anyway.


Prior to the changes in 2.079, you had to implement a large part 
of the runtime just to get a build, and most of that code would 
have never even been called from your program.  It was ridiculous 
and a major barrier to entry.  With 2.079, you can now implement 
just what you need incrementally, and that will make it much 
easier to learn the runtime.


What I'm trying to say, is the "minimal runtime" approach to 
using D is for those who wish to become runtime hackers, and are 
willing to study and experiment in order to learn how to take 
control of the runtime for themselves.  The reason the phrase 
"minimal runtime" is often used over "no runtime" is because it 
is up to you to decide which features of D to implement or not 
implement.


That being said, understand that -betterC does not link in the 
runtime, so anything not supported by -betterC will also not be 
supported by a bare runtime.  Therefore the documenation at 
https://dlang.org/spec/betterc.html is still relevant to the 
"minimal runtime" approach.There are differences.  For 
example, I think -betterC forwards asserts to the C library, 
while a bare runtime would not.  But, the differences are few.


You're also welcome to ask questions.  I'm the one primarily 
responsible for those "minimal runtime" changes, and I'd be happy 
to help you if I can.


Mike

P.S. You're probably not going to have much success using Phobos 
in a "minimal runtime" scenario.  I'm exploring a way to get 
around that at https://github.com/JinShil/utiliD.


Help with semaphoreci issue?

2018-06-05 Thread Manu via Digitalmars-d
I have 2 DMD PR's that show this issue with semaphoreci:
https://semaphoreci.com/dlang/dmd-2/branches/pull-request-8336/builds/1

I don't understand what's wrong, and whether or not it's my fault...
If it's not, I guess someone needs to know about it?