Re: Splitting up large dirty file

2018-05-21 Thread Jon Degenhardt via Digitalmars-d-learn

On Monday, 21 May 2018 at 15:00:09 UTC, Dennis wrote:
I want to be convinced that Range programming works like a 
charm, but the procedural approaches remain more flexible (and 
faster too) it seems. Thanks for the example.



On Monday, 21 May 2018 at 22:11:42 UTC, Dennis wrote:
In this case I used drop to drop lines, not characters. The 
exception was thrown by the joiner it turns out.

 ...
From the benchmarking I did, I found that ranges are easily an 
order of magnitude slower even with compiler optimizations:


My general experience is that range programming works quite well. 
It's especially useful when used to do lazy processing and as a 
result minimize memory allocations. I've gotten quite good 
performance with these techniques (see my DConf talk slides: 
https://dconf.org/2018/talks/degenhardt.html).


Your benchmarks are not against the file split case, but if you 
benchmarked that you may have also seen it as slow. It that case 
you may be hitting specific areas where there are opportunities 
for performance improvement in the standard library. One is that 
joiner is slow (PR: https://github.com/dlang/phobos/pull/6492). 
Another is that the write[fln] routines are much faster when 
operating on a single large object than many small objects. e.g. 
It's faster to call write[fln] with an array of 100 characters 
than: (a) calling it 100 times with one character; (b) calling it 
once, with 100 characters as individual arguments (template 
form); (c) calling it once with range of 100 characters, each 
processed one at a time.


When joiner is used as in your example, you not only hit the 
joiner performance issue, but the write[fln] issue. This is due 
to something that may not be obvious at first: When joiner is 
used to concatenate arrays or ranges, it flattens out the 
array/range into a single range of elements. So, rather than 
writing a line at a time, you example is effectively passing a 
character at a time to write[fln].


So, in the file split case, using byLine in an imperative fashion 
as in my example will have the effect of passing a full line at a 
time to write[fln], rather than individual characters. Mine will 
be faster, but not because it's imperative. The same thing could 
be achieved procedurally.


Regarding the benchmark programs you showed - This is very 
interesting. It would certainly be worth additional looks into 
this. One thing I wonder is if the performance penalty may be due 
to a lack of inlining due to crossing library boundaries. The 
imperative versions aren't crossing these boundaries. If you're 
willing, you could try adding LDC's LTO options and see what 
happens. There are some instructions in the release notes for LDC 
1.9.0 (https://github.com/ldc-developers/ldc/releases). Make sure 
you use the form that includes druntime and phobos.


--Jon


Re: C style callbacks fix for member callbacks

2018-05-21 Thread IntegratedDimensions via Digitalmars-d-learn

On Monday, 21 May 2018 at 02:23:27 UTC, ag0aep6g wrote:

I tried this. Your code crashes in windows dmd x86 x64.


Hm. Works for me in a virtual machine. But I'm not surprised 
that it's fragile. It might be completely wrong, and it just 
happens to look alright on my machine.


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

Shows the static version produces the same code as the 
non-static. The code was probably compiled on linux.


I can't tell though on my machine what is going on since I cannot 
disassemble properly and what I do see is far more complex.


Re: Splitting up large dirty file

2018-05-21 Thread Dennis via Digitalmars-d-learn

On Monday, 21 May 2018 at 17:42:19 UTC, Jonathan M Davis wrote:
On Monday, May 21, 2018 15:00:09 Dennis via Digitalmars-d-learn 
wrote:
drop is range-based, so if you give it a string, it's going to 
decode because of the whole auto-decoding mess with 
std.range.primitives.front and popFront.


In this case I used drop to drop lines, not characters. The 
exception was thrown by the joiner it turns out.


On Monday, 21 May 2018 at 17:42:19 UTC, Jonathan M Davis wrote:

I find Exceptions in range code hard to interpret.


Well, if you just look at the stack trace, it should tell you. 
I don't see why ranges would be any worse than any other code 
except for maybe the fact that it's typical to chain a lot of 
calls, and you frequently end up with wrapper types in the 
stack trace that you're not necessarily familiar with.


Exactly that: stack trace full of weird mangled names of template 
functions, lambdas etc. And because of lazy evaluation and chains 
of range functions, the line number doesn't easily show who the 
culprit is.


On Monday, 21 May 2018 at 17:42:19 UTC, Jonathan M Davis wrote:
In many cases, ranges will be pretty much the same as writing 
loops, and in others, the abstraction is worth the cost.


From the benchmarking I did, I found that ranges are easily an 
order of magnitude slower even with compiler optimizations:


https://run.dlang.io/gist/5f243ca5ba80d958c0bc16d5b73f2934?compiler=ldc=-O3%20-release

```
LDC -O3 -release
 Range   Procedural
Stringtest: ["267ns", "11ns"]
Numbertest: ["393ns", "153ns"]


DMD -O -inline -release
  Range   Procedural
Stringtest: ["329ns", "8ns"]
Numbertest: ["1237ns", "282ns"]
```

This first range test is an opcode scanner I wrote for an 
assembler. The range code is very nice and it works, but it 
needlessly allocates a new string. So I switched to a procedural 
version, which runs (and compiles) faster. This procedural 
version did have some bugs initially though.


The second test is a simple number calculation. I thought that 
the range code inlines to roughly the same procedural code so it 
could be optimized the same, but there remains a factor 2 gap. I 
don't know where the difficulty is, but I did notice that 
switching the maximum number from int to enum makes the 
procedural version 0 ns (calculated at compile time) while LDC 
can't deduce the outcome in the range version (which still runs 
for >300 ns).


Re: scope guards & debugger breakpoints?

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 1:50 PM, Robert M. Münch wrote:

On 2018-05-21 17:24:12 +, Steven Schveighoffer said:


I'm not 100% sure but I expect:

scope(failure)
    someCode();

putting a breakpoint on someCode should work.


When calling a function an then setting the breakpoint there, like in 
someCode() yes, that should work.


I used code like this:

scope(failure) {
 ... several lines of code
}

And for this it seems (maybe I need to check in more detail) that in 
MSVC, I can set a breakpoint, but the breakpoint is not triggered when 
an exception is thrown.




Seems like the debugger not understanding D source in that case.

What you could try is:

void breakOnThis()
{
   return; // breakpoint here
}
scope(failure)
{
breakOnThis();
...
}

and then see where it goes when you step out of that function.

-Steve


Re: Temporary file creation for unittests

2018-05-21 Thread Atila Neves via Digitalmars-d-learn

On Monday, 21 May 2018 at 15:20:14 UTC, Dr.No wrote:

On Monday, 21 May 2018 at 15:16:11 UTC, Atila Neves wrote:

On Friday, 18 May 2018 at 15:16:52 UTC, Russel Winder wrote:

Hi,

What's the current official position on how to create 
temporary files for use during a unittest. I found


Not official, but...

import unit_threaded;

with(const Sandbox()) {
writeFile("myfile.txt", "contents");
shouldExist("myfile.txt");
shouldEqualContent("myfile.txt", "contents");
fileShouldContain("myfile.txt", "cont");
}

Atila


I've never seen "should" being in used in function names 
before...


There's a whole lot of them here:

https://github.com/atilaneves/unit-threaded/blob/master/source/unit_threaded/should.d


Re: Temporary file creation for unittests

2018-05-21 Thread Atila Neves via Digitalmars-d-learn

On Monday, 21 May 2018 at 17:03:40 UTC, Russel Winder wrote:
On Mon, 2018-05-21 at 15:16 +, Atila Neves via 
Digitalmars-d-learn wrote:

On Friday, 18 May 2018 at 15:16:52 UTC, Russel Winder wrote:
> Hi,
> 
> What's the current official position on how to create 
> temporary files for use during a unittest. I found


Not official, but...

 import unit_threaded;

 with(const Sandbox()) {
 writeFile("myfile.txt", "contents");
 shouldExist("myfile.txt");
 shouldEqualContent("myfile.txt", "contents");
 fileShouldContain("myfile.txt", "cont");
 }

Atila


OK, we like this. A lot.


:)

Given I use Unit-Threaded, why did I not know this. Ah, OK, 
RTFM. :-)


It's got so many features that I don't know how to document 
everything and make it accessible at the same time.



Did I mention how much I like this RAII approach?


Me too - RAII is definitely C++'s gift to the world. I've been 
abusing `with` lately quite a bit. I think it's underused.





Re: auto & class members

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 16:05:00 Steven Schveighoffer via Digitalmars-d-
learn wrote:
> On 5/21/18 3:22 PM, Jonathan M Davis wrote:
> > That's basically what I was suggesting that he do, but I guess that I
> > wasn't clear enough.
>
> Well one thing that seems clear from this example -- we now have
> __traits(isSame) to tell if lambdas are the same, but it looks like the
> compiler doesn't subscribe to that belief...
>
> https://run.dlang.io/is/FW3mVq
>
> We should fix that...

Yeah. That part of lambdas has always been a problem. My guess here is that
the problem stems from the fact that they're declared in separate scopes,
but I don't know. Regardless of the reason for the failure though, that
example really needs to work, or most anything that cares about lambdas
being the same is going to have problems.

- Jonathan M Davis



Re: auto & class members

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 3:22 PM, Jonathan M Davis wrote:


That's basically what I was suggesting that he do, but I guess that I wasn't
clear enough.


Well one thing that seems clear from this example -- we now have 
__traits(isSame) to tell if lambdas are the same, but it looks like the 
compiler doesn't subscribe to that belief...


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

We should fix that...

-Steve


Re: is ==

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 3:20 PM, Jonathan M Davis wrote:

On Monday, May 21, 2018 14:40:24 Steven Schveighoffer via Digitalmars-d-
learn wrote:

For me, the code smell is using arr is null (is it really necessary to
check for a null pointer here?), for which I always have to look at more
context to see if it's *really* right.


Really? I would never expect anyone to use is unless they really cared about
whether array was null. I'd be concerned about whether the code in general
was right, because treating null as special gets tricky, but that particular
line wouldn't concern me.


Don't get me wrong, they probably *do* mean to check if it's null. But 
do they *need* to check?


I'll borrow from your example below:

if(arr != null && arr == arr2)

Replace this with:

if(arr !is null && arr == arr2)

Does this look any better? I don't think so, it means the person didn't 
understand what an array actually is. Even though the second actually 
has some semantic meaning (the first is a no-op), it's likely not what 
the author intended.


In most cases, when they check for null, they just want to check to see 
if the array is unset. The semantic meaning of this is usually that it's 
empty, they don't really care if it's actually null or not. In which 
case, checking for exact nullness is actually more expensive, and prone 
to problems.


This comes from many languages where an array is an object type that 
defaults to null, and we reinforce that misconception by allowing null 
as a valid array literal.



Even people who write == null may want to check for null thinking that
it's how you check an array is empty, not realizing that it *doesn't*
check for a null pointer, *AND* it still does exactly what they need it
to do ;)


You honestly expect someone first coming to D expect to check whether an
array is empty by checking null? That's a bizarre quirk of D that I have
never seen anyhwere else. I would never expect anyone to purposefully use
== null to check for empty unless they were very familiar with D, and even
then, I'd normally expect them to ask what they really mean, which is
whether the array is empty.


Reread what I said again. They *think* they need to check if it's null 
(it being the mythical Array object type that the language no doubt 
lowers to, just like it does in Java or C# or Swift or...), but really, 
they only need to check if it's empty. Which happens to be all they 
really need.


For instance:

int[] arr;

if (cond)
{
   ...
   arr = new int[5];
   ...
}

if (arr == null)

Now, you can certainly replace arr == null with arr is null, and the 
code works fine -- identically, even though it's more expensive. But to 
me, the arr is null is a red flag. Does the person know that they are 
checking for the ACTUAL value null? You still have to read the code to 
figure it out! I would say most times it's a bug waiting to happen. I 
can't imagine you just see "arr is null" and move on believing the 
author knew what they were doing.



It's the same reason that

if(arr)

was temporarily out of the language.


It's similar, but I consider it a different reason. While the intent of
== null may not be crystal clear, 99% of people don't care about the
pointer, they just care whether it's empty. So the default case is
usually good enough, even if you don't know the true details.


I think that that's the key point of disagreement here. I would never
consider the intent of == null to be crystal clear based solely on the code,
because it is so common outside of D to use == null to actually check for
null, and there are better ways in D to check for empty if that's what you
really mean. My immediate expectation on seeing arr == null is that the
programmer does not properly understand arrays in D. If I knew that someone
like you wrote the code, I'd probably decide that you knew what you were
doing and didn't make a mistake, but I'm not going to assume that in
general, and honestly, I would consider it bad coding practice (though we
obviously disagree on that point).


The fundamental reason why == null is generally OK is because generally 
the person doesn't distinguish between nullness and non-null but empty. 
Believe it or not, this is my position as well. Either works fine for 
their code, and in fact, when you analyze the code, checking for 
emptiness is really what they mean.


Consider that new T[0] returns a null array. What happens if it returned 
a non-null array? Only code that uses "is null" would break. Code that 
uses == null would work fine.



I would consider the if(arr) and arr == null cases to be exactly the same.
They both are red flags that the person in question does not understand how
arrays in D work. Yes, someone who knows what they're doing may get it
right, but I'd consider both to be code smells and I wouldn't purposefully
do either in my own code. If I found either in my own code, I would expect
that I'd just found a careless bug.


== null is way more forgiving than if(arr). That is the 

Re: Can I work out error: reinterpreting cast from const(ubyte)* to const(uint)* is not supported in CTFE?

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 18:13:26 Dr.No via Digitalmars-d-learn wrote:
> I'm trying to do some hashing at compile time with xxhash
> algorithm but I get this error:
>
> ..\..\..\AppData\Local\dub\packages\xxhash-master\xxhash\src\xxhash.d(39,3
> 7): Error: reinterpreting cast from const(ubyte)* to const(uint)* is not
> supported in CTFE
>
> this is line 39
>
> (https://github.com/repeatedly/xxhash-d/blob/master/src/xxhash.d#L39):
> > auto srcPtr = cast(const(uint)*)source.ptr;
>
> I'm on Windows 10 64-bit machine.

You can't do any kind of pointer manipulaton or related casts in CTFE. So,
you can't reinterpet one type as another at compile time. You would need a
different hashing algorithm for CTFE - e.g.

if(__ctfe)
{
... do something to calculate a hash
}
else
{
... calculate the hash the current way
}

- Jonathan M Davis



Re: assertNotThrown (and asserts in general)

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 12:44:21 Malte via Digitalmars-d-learn wrote:
> I was interested by asserts and how the compiler uses them to
> optimize the code. So I looked at the compiler explorer to see
> how and found it, it doesn't.
>
> What I tried to do is turn a std.conv.to!ulong(byte) to a simple
> cast with the help of assertions.
> https://godbolt.org/g/4uckWU
>
> If there is an assert right before an if with the same condition,
> I think it should remove the compare and jump in release, but it
> doesn't. I'm assuming the compilers just aren't ready yet, but
> should be someday. At least that is what the documentation
> promises.

Walter wants to use assertions to then have the compiler make assumptions
about the code and optimized based on it, but he hasn't implemented anything
like that, and there are a number of arguments about why it's a very bad
idea - in particular, if it allows the compiler to have undefined behavior
if the assertion would have failed if it were left in. So, what is actually
going to happen with that is unclear. There are folks who want additional
performance benefits by allowing assertions to work as hints to the
compiler, and there are folks who want them to truly just be for debugging
purposes, because they don't want the compiler to then generate code that
makes the function behave even more badly when the assertion would have
failed but had been compiled out.

Personally, my big concern is that it can't introduce undefined behavior, or
it would potentially violate memory safety in @safe code, which would then
mean that using assertions in @safe code could make your code effectively
@system, which would defeat the whole purpose of @safe. If the compiler can
optimize while not breaking those guarantees, then I'm all for it, but some
folks disagree with even that, because they don't want their code to behave
worse when something goes wrong. Of course, the counter-argument is that if
they're that worried about it, they should leave the checks in, but there
definitely isn't agreement on the matter. Walter is in favor of adding
optimizations based on assertions though, so I think that there's a decent
chance that we'll see something like that at some point. But language
feature stuff (like implementing scope for DIP 1000) are generally much
higher priority than adding extra optimizations to the compiler. So, while
optimizations and performance improvements are certainly done, they're not
the main focus right now.

> More curious made me
> "assertNotThrown!ConvOverflowException(input.to!ubyte)" where it
> didn't even remove the assert code in release and produced the
> most inefficient assembly.
> Is that intended behaviour? In my opinion that greatly limits the
> usabilty of it.

assertNotThrown doesn't use any assertions. It explicitly throws an
AssertError (which is what a failed assertion does when it's not compiled
out). assertNotThrown would have to use a version(assert) block to version
the checks to try and mirror what the assert statement does. However,
assertNotThrown is specifically intended for unit tests. IIRC, assertions in
unit tests are left in when compiled with -unittest (otherwise, compiling
with -release and -unittest - like Phobos does for one of its passes as part
of its unittest build - would not work), but I don't think that the
assertions outside of unittest blocks get left in in that case, so using
version(assert) on assertThrown or assertNotThrown might break them. I'm not
sure. Regardless, using them for testing what assertions do is just wrong.
You need to test actual assert statements if that's what you want to be
testing.

- Jonathan M Davis



Re: auto & class members

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 11:13:16 Ali Çehreli via Digitalmars-d-learn wrote:
> On 05/20/2018 10:46 AM, Robert M. Münch wrote:
>  > But I still don't understand why I can't write things explicitly but
>  > have to use an alias for this.
>
> Templatized range types work well when they are used as template
> arguments themselves.
>
> When you need to keep a single type like 'b' (i.e. b is not a template),
> and when you need to set a variable like mySubStream to a dynamic
> object, the solution is to use inputObject():
>
> import std.algorithm;
> import std.range;
>
> class a {
>  int[] myStream = [ 1, 2, 42, 100 ];
> }
>
>
> int myMessage = 42;
>
> class b {
>  InputRange!int mySubStream;
> }
>
> void myFunc() {
>  a myA = new a();
>  b myB = new b();
>
>  myB.mySubStream = inputRangeObject(myA.myStream.filter!(x => x ==
> myMessage));
>
>  assert(myB.mySubStream.equal([myMessage]));
> }
>
> void main() {
>  myFunc();
> }
>
> Now, mySubStream is a range variable that satisfies the input range
> interface and produces int elements. (Adjust accordingly.) You can use a
> more specialized range kind other than InputRange if the actual range
> supports it (e.g. ForwardRange!int, etc.):
>
>
> http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObjec
> t
>
>https://dlang.org/phobos/std_range_interfaces.html#inputRangeObject

Wow. Someone actually uses those? I don't think that I've ever seen anyone
try except when they didn't understand ranges properly and thought that all
ranges derived from the interfaces in that module. I guess that they would
work in this case, but I think that the normal solution is to use typeof
(though as Robert here found, that can get a bit problematic when lambdas
get involved, whereas your solution here is pretty straightforward).

I'd be _very_ leery of using ForwardRange and the like though, since they're
going to have to allocate on every call to save, which gets expensive, and
far too often, range-based code doesn't call save correctly, meaning that
you'll often hit bugs using a forward range that's a class. Phobos is a
_lot_ better about it than it used to be, but I expect that there are still
a few such lingering bugs in there, and I'd expect the average range-based
code to screw it up. Really, the only way to get it right is to actually
test your code with reference type ranges.

If all you're using is a basic input range, then those interfaces just cost
you the one allocation and should be fine, but beyond that, I wouldn't
suggest using them if you can reasonably avoid it. And personally, I'd just
use Steven's solution of using a wrapper function so that you can ensure
that there's really only one lambda type involved, and typeof then works.

- Jonathan M Davis




Re: auto & class members

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 14:55:36 Steven Schveighoffer via Digitalmars-d-
learn wrote:
> On 5/20/18 1:46 PM, Robert M. Münch wrote:
> > On 2018-05-20 17:40:39 +, Robert M. Münch said:
> >> Hi Jonathan, great! This got me a step further. So I can declare my
> >> member now. But I get an implict cast error when I try:
> >>
> >> class a {
> >> ... myStream;
> >> }
> >>
> >> class b {
> >> typeof(a.myStream.filter!(x => x == myMessage)) mySubStream;
> >> }
> >>
> >> void myFunc() {
> >> a myA = new a();
> >> b myB = new b();
> >>
> >> myB.mySubstream = myA.myStream.filter!(x => x == myMessage);
> >> }
> >>
> >> This gives (unnecessary stuff stripped):
> >>
> >> Error: cannot implicitly convert expression filter(...) of type
> >> app.myFunc.filter!(x => x == myMessage) to app.b.filter!(x => x ==
> >> myMessage)
> >
> > Answering myself: Using an alias helps.
> >
> > alias typeof(a.myStream.filter!(x => x == myMessage)) myMessageType;
>
> So the issue here is that the lambda function inside myFunc is DIFFERENT
> than the one inside b. They are both the same function, but with
> essentially different names.
>
> When you use the alias, both are using the same exact lambda.
>
> I see you are casting now as well, which looks horrible to me -- if you
> change something in your lambda now you are in for some trouble.
>
> What may make more sense (both for type sanity and for code reuse) is to
> wrap your call to filter into one place so it can be used wherever you
> need it:
>
> auto wrapStream(S)(S str) { return str.filter!(x => x == myMessage); }
>
> class b
> {
> typeof(wrapStream(a.init.myStream)()) mySubStream;
> }
>
> void myFunc() {
> a myA = new a;
> b myB = new b;
> myB.mySubstream = myA.myStream.wrapStream;
> }

That's basically what I was suggesting that he do, but I guess that I wasn't
clear enough.

- Jonathan M Davis




Re: is ==

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 14:40:24 Steven Schveighoffer via Digitalmars-d-
learn wrote:
> On 5/21/18 2:05 PM, Jonathan M Davis wrote:
> > The core problem here is that no one reading a piece of code has any way
> > of knowing whether the programmer knew what they were doing or not when
> > using == null with an array, and the vast majority of newbies are not
> > going to have understood the semantics properly. If I know that someone
> > like you or Andrei wrote the code, then the odds are good that what the
> > code does is exactly what you intended. But for the average D
> > programmer? I don't think that it makes any sense to assume that,
> > especially since anyone coming from another language is going to assume
> > that == null is checking for null, when it's not.
>
> For me, the code smell is using arr is null (is it really necessary to
> check for a null pointer here?), for which I always have to look at more
> context to see if it's *really* right.

Really? I would never expect anyone to use is unless they really cared about
whether array was null. I'd be concerned about whether the code in general
was right, because treating null as special gets tricky, but that particular
line wouldn't concern me.

> Even people who write == null may want to check for null thinking that
> it's how you check an array is empty, not realizing that it *doesn't*
> check for a null pointer, *AND* it still does exactly what they need it
> to do ;)

You honestly expect someone first coming to D expect to check whether an
array is empty by checking null? That's a bizarre quirk of D that I have
never seen anyhwere else. I would never expect anyone to purposefully use
== null to check for empty unless they were very familiar with D, and even
then, I'd normally expect them to ask what they really mean, which is
whether the array is empty.

> > It's the same reason that
> >
> > if(arr)
> >
> > was temporarily out of the language.
>
> It's similar, but I consider it a different reason. While the intent of
> == null may not be crystal clear, 99% of people don't care about the
> pointer, they just care whether it's empty. So the default case is
> usually good enough, even if you don't know the true details.

I think that that's the key point of disagreement here. I would never
consider the intent of == null to be crystal clear based solely on the code,
because it is so common outside of D to use == null to actually check for
null, and there are better ways in D to check for empty if that's what you
really mean. My immediate expectation on seeing arr == null is that the
programmer does not properly understand arrays in D. If I knew that someone
like you wrote the code, I'd probably decide that you knew what you were
doing and didn't make a mistake, but I'm not going to assume that in
general, and honestly, I would consider it bad coding practice (though we
obviously disagree on that point).

I would consider the if(arr) and arr == null cases to be exactly the same.
They both are red flags that the person in question does not understand how
arrays in D work. Yes, someone who knows what they're doing may get it
right, but I'd consider both to be code smells and I wouldn't purposefully
do either in my own code. If I found either in my own code, I would expect
that I'd just found a careless bug.

> > At this point, I'm honestly inclined to think that we never should have
> > allowed null for arrays. We should have taken the abstraction a bit
> > further and disallowed using null to represent dynamic arrays. It would
> > then presumably still work to do arr.ptr is null, but arr is null
> > wouldn't work, because null wouldn't be an array, and arr == null
> > definitely wouldn't work. Then we could just use [] for empty arrays
> > everywhere, and there would be no confusion, leaving null for actual
> > pointers. And it would almost certinly kill off all of the cases where
> > null was treated as special for dynamic arrays except maybe for when
> > dealing with C code, but in that case, they'd have to use ptr directly.
> > However, at this point, I expect that that's all water under the
> > bridge, and we're stuck with it.
>
> If we never had null be the default value for an array, and used []
> instead, I would be actually OK with that. I also feel one of the
> confusing things for people coming to the language is that arrays are
> NOT exactly reference types, even though null can be used as a value for
> assignment or comparison.
>
> But it still wouldn't change what most people write or mean, they just
> would write == [] instead of == null. I don't see how this would solve
> any of your concerns.

It would solve the concern, because no one is going to write arr == [] to
check for null. They'de write it just like they'd write arr == "". They're
clearly checking for empty, not null. The whole problem here is that pretty
much everywhere other than D arrays, null and empty are two separate things,
and pretty much anyone coming from 

Re: auto & class members

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/20/18 1:46 PM, Robert M. Münch wrote:

On 2018-05-20 17:40:39 +, Robert M. Münch said:

Hi Jonathan, great! This got me a step further. So I can declare my 
member now. But I get an implict cast error when I try:


class a {
... myStream;
}

class b {
typeof(a.myStream.filter!(x => x == myMessage)) mySubStream;
}

void myFunc() {
a myA = new a();
b myB = new b();

myB.mySubstream = myA.myStream.filter!(x => x == myMessage);
}

This gives (unnecessary stuff stripped):

Error: cannot implicitly convert expression filter(...) of type 
app.myFunc.filter!(x => x == myMessage) to app.b.filter!(x => x == 
myMessage)


Answering myself: Using an alias helps.

alias typeof(a.myStream.filter!(x => x == myMessage)) myMessageType;


So the issue here is that the lambda function inside myFunc is DIFFERENT 
than the one inside b. They are both the same function, but with 
essentially different names.


When you use the alias, both are using the same exact lambda.

I see you are casting now as well, which looks horrible to me -- if you 
change something in your lambda now you are in for some trouble.


What may make more sense (both for type sanity and for code reuse) is to 
wrap your call to filter into one place so it can be used wherever you 
need it:


auto wrapStream(S)(S str) { return str.filter!(x => x == myMessage); }

class b
{
   typeof(wrapStream(a.init.myStream)()) mySubStream;
}

void myFunc() {
   a myA = new a;
   b myB = new b;
   myB.mySubstream = myA.myStream.wrapStream;
}

-Steve


Re: UFCS syntax I never saw before.

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 14:00:55 ANtlord via Digitalmars-d-learn wrote:
> On Monday, 21 May 2018 at 11:38:12 UTC, SrMordred wrote:
> > After all this time I saw this:
> >
> > writeln = iota = 5;
> >
> > what??
> >
> > I never saw that before!
> >
> > This is interesting, there is something useful that i can do
> > with this kind of call?
>
> What the hell is this? I don't figure out why are there so many
> syntax features? It doesn't make the language more easier. Is it
> any reason to support 2 additional cases of function calling? We
> have no literal for a tuple but we call a function via 3 cases.
> I'm frustrated.

This particular example is a result of how property functions were
originally introduced into the language, and UCFS just compounded the
problem. It's also why () is optional on function calls.

foo = bar;

is treating foo like a setter property, and

auto result = foo;

is treating foo like a getter property. Heck, in

foo = bar;

both foo and bar could be function calls. As long as it's used
intelligently, this is great, because then you can treat functions as
properties. But it gets really bad when someone does something dumb like

writeln = "hello";

Because this can get really dumb, @property was introduced into the language
with the idea that it would be used to mark functions which were supposed to
be used as properties. Then dumb stuff like

writeln = "hello";

could become illegal, whereas stuff functions that were actually intended to
be used as properties could continue to be used as properties. So, the clean
uses would be left, and the bad uses would be illegal. Unfortunately,
because moving to @property meant breaking code (even code that was using
properties legitimately, since it was introduced before @property was a
thing), that meant that we had to introduce @property as doing nothing and
then switch to enforcing it later. Somewhere along the line, the -property
flag was introduced to start enforcing it, but it only partially enforced
it, and of course code continued to be written without using it. So,
actually moving to enforcing everything with @property was slow.

And then UFCS happened, and that pretty much killed the whole thing. The
problem was twofold:

1. A number of folks just got in the habit of calling functions without
parens and liked it. They would generally agree that

writeln = "foo";

was dumb, but they liked being able to just not use parens when doing stuff
like

myObj = foo;

or

myFunc(foo);

So, telling them that they couldn't do that anymore didn't go over well.

2. Once, UFCS came into the game, instead of having code like

auto result = map!(a => a / 2)(range);

you got

auto result = range.map!(a => / 2)();

and you all of a sudden had a bunch of templated functions with empty
parens when called, and since you already had a one set of parens for the
template argument, folks thought that that was ugly. So, they started
writing

auto result = range.map!(a => / 2);

So, requiring that they then use parens for that as they would have to if
parens were required when calling all non-@property functions as had been
the plan was _not_ going to go over well. It basically became completely
unacceptable to require @property for property functions, and so plans to
properly implement @property were dropped.

The result is that @property does almost nothing (it affects what typeof
does, and it affects __traits - and thus std.traits.functionAttributes - and
you can't overload an @property function and a normal function, but that's
pretty much it). Lots of us use it all the time to indicate what we intend
to be used as a property function, but it's just documentation.

Now, even if you think that calling functions with no parens is great, that
still leaves us with two problems:

1. writeln = "foo"; is still legal. Maybe we could make it so that @property
is required with free functions used as setters that aren't used with UFCS,
but figuring out a set of rules that doesn't require putting @property on
all setter functions while still disallowing the really dumb stuff isn't
easy, and it's questionable that requiring @property on setters at this
point is going to go over well. It's very annoying that stuff like

writeln = "foo";

is legal, and it's dumb, but it hasn't mattered much in practice. So,
causing a bunch of code breakage in order to disallow it is unlikely to go
over well. It would also then make getters and setters inconsistent in that
setters would require @property and getters wouldn't. How much that matters
is debatable, but it does make such a change less palatable.

2. The other issue that @property was supposed to fix was property functions
that return callables - e.g. foo could return a delegate, but the compiler
has to assume that the parens on foo() are calling foo, not the delegate
that it returns. So, even though you want to treat foo as a property that is
a delegate, you're forced to treat it as a function and use double parens -
e.g. foo()(). 

Re: is ==

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 2:05 PM, Jonathan M Davis wrote:

The core problem here is that no one reading a piece of code has any way of
knowing whether the programmer knew what they were doing or not when using
== null with an array, and the vast majority of newbies are not going to
have understood the semantics properly. If I know that someone like you or
Andrei wrote the code, then the odds are good that what the code does is
exactly what you intended. But for the average D programmer? I don't think
that it makes any sense to assume that, especially since anyone coming from
another language is going to assume that == null is checking for null, when
it's not.


For me, the code smell is using arr is null (is it really necessary to 
check for a null pointer here?), for which I always have to look at more 
context to see if it's *really* right.


Even people who write == null may want to check for null thinking that 
it's how you check an array is empty, not realizing that it *doesn't* 
check for a null pointer, *AND* it still does exactly what they need it 
to do ;)




It's the same reason that

if(arr)

was temporarily out of the language.


It's similar, but I consider it a different reason. While the intent of 
== null may not be crystal clear, 99% of people don't care about the 
pointer, they just care whether it's empty. So the default case is 
usually good enough, even if you don't know the true details.


Whereas, if(arr) is checking that the pointer is null as well as the 
length is 0. Most people aren't expecting that, and those who are are 
like Andrei and Vladimir -- they know the quirks of the language here. 
For the longest time I thought it was just checking the pointer!


I think aside from the clout of the ones who wanted it, the biggest 
reason that change was reverted was that it became really difficult to 
use an array inside a conditional. One-liners had to be extracted out, 
temporary variables defined.



At this point, I'm honestly inclined to think that we never should have
allowed null for arrays. We should have taken the abstraction a bit further
and disallowed using null to represent dynamic arrays. It would then
presumably still work to do arr.ptr is null, but arr is null wouldn't work,
because null wouldn't be an array, and arr == null definitely wouldn't work.
Then we could just use [] for empty arrays everywhere, and there would be no
confusion, leaving null for actual pointers. And it would almost certinly
kill off all of the cases where null was treated as special for dynamic
arrays except maybe for when dealing with C code, but in that case, they'd
have to use ptr directly. However, at this point, I expect that that's all
water under the bridge, and we're stuck with it.


If we never had null be the default value for an array, and used [] 
instead, I would be actually OK with that. I also feel one of the 
confusing things for people coming to the language is that arrays are 
NOT exactly reference types, even though null can be used as a value for 
assignment or comparison.


But it still wouldn't change what most people write or mean, they just 
would write == [] instead of == null. I don't see how this would solve 
any of your concerns.


-Steve


Re: Real Int24

2018-05-21 Thread IntegratedDimensions via Digitalmars-d-learn

On Monday, 21 May 2018 at 15:41:21 UTC, Simen Kjærås wrote:
On Saturday, 19 May 2018 at 18:44:42 UTC, IntegratedDimensions 
wrote:
On Saturday, 19 May 2018 at 18:19:35 UTC, IntegratedDimensions 
wrote:
Is there any way to create an int24 type that behaves just 
like any other built in type without having to reimplement 
everything?


In fact, what I'd like to do is create an arbitrary type:

struct atype(T)
{

}

where atype(T) is just a "view" in to N_T bits interpreted as 
T, an enum.


If T is bit, then the N = 1 and the interpretation is 1 bit.
If T is byte, then the N = 8 and the interpretation is 7 bits 
followed by 1 signed bit.
If T is int24, then the N = 24 and the interpretation is 23 
bits followed by 1 signed bit.


The idea is the storage of atype is exactly N bits. If this is 
not possible due to boundary issues then N can always be a 
multiple of 8(which is for my use cause is the smallest).


D does not support types that take up less than one byte of 
space. It's possible to make types that represent less than one 
byte - bool may be considered such an example - but they still 
take up at least 1 byte.


If you create a custom range type, you could pack more than one 
element in each byte, see std.bitmanip.BitArray[0] for an 
example.



The main thing is that I would like to be able to use atype as 
if it were a built in type.


If N = 24, 3 bytes, I want to be able to create arrays of 
atype!int24[] which work just as if they were arrays of bytes 
without any exception or special cases.


atype!byte would be equivalent to byte and reduce to the 
compiler internals. I'm not looking to create a "view" of an 
array. I want a standalone type that can behave as all the 
desired types needed, which is most of the numerical types of 
D and some of the ones it neglected like 24-bit ints, 48-bit 
ints, etc. Ideally, any type could be used and the "most 
optimal" code is generated while being able to use the types 
using the standard model.


We already have std.numeric.CustomFloat[1]. As the name 
implies, it only works for floats.


I hacked together something somewhat equivalent for ints:

https://gist.github.com/Biotronic/f6668d8ac95b70302015fee93ae9c8c1

Usage:

// Two's-complement, native-endian, 24-bit int type:
CustomInt!24 a;

// Unsigned, native-endian, 15-bit:
CustomInt!(15, Representation.Unsigned) b;

// Offset (-2..5) 3-bit int:
CustomInt!(3, Representation.OffsetBinary, 2) c;

// You get the idea:
CustomInt!(64, Representation.SignedMagnitude, 0, 
Endianness.BigEndian) d;


Not sure this is what you're looking for, but it's at the very 
least inspired by your post. :)


If what you want is a type that can represent something a 
packed array of 13-bit ints, the above is not what you're 
looking for - you're going to need a custom range type.


--
  Simen

[0]: https://dlang.org/phobos/std_bitmanip#BitArray
[1]: https://dlang.org/phobos/std_numeric.html#.CustomFloat


Cool. I'll try it as a drop in replacement and if it works then 
it works! ;) Thanks.


Just to be clear and to make sure this works the way it seems:

All types multiple of a byte are reduced to either internal 
representation(byte, ubyte, short, ushort, int, uint, long, 
ulong) directly(becomes an alias) or the most efficient structure 
for the representation: unsigned 24-bit = 3 bytes and is 
effectively ubyte[3], usigned 128-bit is ubyte[16], etc?



Non multiples are extended up one byte, so 7-bits is representing 
using an byte, etc.


This seems to be the case from the code.


Now, what I didn't see was anything to work with non byte aligned 
arrays of CustomInt. Would it be possible to add? I know you say 
that we should use bitmanip but code could be extended to support 
it relatively easily by treating an array of bits as an array of 
CustomInts and the indexer can compute the appropriate offset 
using the bit size.


Maybe that will require CustomIntsArray?

The idea is, say one has 7-bit ASCII represented in a ubyte[] 
then they can map that to a CustomInt!7[] which will be use 
CustomInt!7(but 7 bits, not 8) as representation. But, of course 
CustomInt!7[3] would be 8 bits. But basically it retrieves the 
correct value and stores it by doing the standard masking.


BTW, it looks like you could extend your type to deal with floats 
and doubles which would make this type very robust in dealing 
with arbitrary primitive types.


The idea is that any matching language types are aliased to and 
those that don't are handled appropriately.







Can I work out error: reinterpreting cast from const(ubyte)* to const(uint)* is not supported in CTFE?

2018-05-21 Thread Dr.No via Digitalmars-d-learn
I'm trying to do some hashing at compile time with xxhash 
algorithm but I get this error:


..\..\..\AppData\Local\dub\packages\xxhash-master\xxhash\src\xxhash.d(39,37): 
Error: reinterpreting cast from const(ubyte)* to const(uint)* is not supported 
in CTFE

this is line 39 
(https://github.com/repeatedly/xxhash-d/blob/master/src/xxhash.d#L39):



auto srcPtr = cast(const(uint)*)source.ptr;


I'm on Windows 10 64-bit machine.


Re: auto & class members

2018-05-21 Thread Ali Çehreli via Digitalmars-d-learn

On 05/20/2018 10:46 AM, Robert M. Münch wrote:

> But I still don't understand why I can't write things explicitly but
> have to use an alias for this.

Templatized range types work well when they are used as template 
arguments themselves.


When you need to keep a single type like 'b' (i.e. b is not a template), 
and when you need to set a variable like mySubStream to a dynamic 
object, the solution is to use inputObject():


import std.algorithm;
import std.range;

class a {
int[] myStream = [ 1, 2, 42, 100 ];
}


int myMessage = 42;

class b {
InputRange!int mySubStream;
}

void myFunc() {
a myA = new a();
b myB = new b();

myB.mySubStream = inputRangeObject(myA.myStream.filter!(x => x == 
myMessage));


assert(myB.mySubStream.equal([myMessage]));
}

void main() {
myFunc();
}

Now, mySubStream is a range variable that satisfies the input range 
interface and produces int elements. (Adjust accordingly.) You can use a 
more specialized range kind other than InputRange if the actual range 
supports it (e.g. ForwardRange!int, etc.):



http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObject

  https://dlang.org/phobos/std_range_interfaces.html#inputRangeObject

Ali



Re: is ==

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 10:01:15 Steven Schveighoffer via Digitalmars-d-
learn wrote:
> On 5/18/18 9:48 PM, Jonathan M Davis wrote:
> > Of
> > course, the most notable case where using == with null is a terrible
> > idea is dynamic arrays, and that's the case where the compiler
> > _doesn't_ complain.
> I use arr == null all the time. I'm perfectly fine with that, and
> understand what it means.
>
> > Using == with null and arrays is always unclear about the programmer's
> > intent and almost certainly wasn't what the programmer intended.
>
> I beg to differ.
>
> > If the
> > programmer cares about null, they should use is. If they care about
> > lengnth, then that's what they should check. Checking null with == is
> > just a huge code smell.
>
> IMO, doing anything based on the pointer of an array being null is a
> huge code smell. In which case, == null is perfectly acceptable. I'm
> comparing my array to an empty array. What is confusing about that?
>
> I actually hate using the pointer in any aspect -- an array is
> semantically equivalent to its elements, it's not important where it's
> allocated. The only place D forces me to care about the pointer is when
> I'm dealing with ranges.

The core problem here is that no one reading a piece of code has any way of
knowing whether the programmer knew what they were doing or not when using
== null with an array, and the vast majority of newbies are not going to
have understood the semantics properly. If I know that someone like you or
Andrei wrote the code, then the odds are good that what the code does is
exactly what you intended. But for the average D programmer? I don't think
that it makes any sense to assume that, especially since anyone coming from
another language is going to assume that == null is checking for null, when
it's not.

It's the same reason that

if(arr)

was temporarily out of the language. The odds are very high that the
programmer using it is using it wrong. Andrei and Vladimir were using it
correctly in their code, so they didn't like the fact that it had then
become illegal, but while knew what they were doing and were using it
correctly, plenty of other folks have been inserting bugs whenever they do
that, and if I see if(arr) or assert(arr) in code, I'm going to consider it
to be code smell just as much as I consider arr == null to be code smell.

And yes, trying to treat the ptr as being null as special with a dynamic
array is risky, and most code shouldn't be doing it, but you're almost
forced to in some cases when interacting with C code, and clearly there are
folks that do (e.g. Andrei and Vladimir). But even if we could unequivocably
say that no one should be doing it, you still have no way of knowing whether
someone is attempting it or not when they do arr == null, and since caring
whether an array is null or not is a very typical thing to do in other
languages where there is a very clear distinction between a null array and
an empty one, plenty of folks come to D expecting to be able to do the same.
And they're going to write arr == null or arr != null, and any time I see
code like that, I'm going to have sit down and figure out whether they
really meant arr is null, or whether they meant arr.length == 0, whereas if
they had just written arr is null or arr.length == 0 (or arr.empty), their
intent would have been perfectly clear. As such, I would strongly advise D
programmers to use arr.empty or arr.length == 0 instead of arr == null, even
if they know what they're doing, just like I would advise them to not treat
null as special for arrays unless they really need to.

At this point, I'm honestly inclined to think that we never should have
allowed null for arrays. We should have taken the abstraction a bit further
and disallowed using null to represent dynamic arrays. It would then
presumably still work to do arr.ptr is null, but arr is null wouldn't work,
because null wouldn't be an array, and arr == null definitely wouldn't work.
Then we could just use [] for empty arrays everywhere, and there would be no
confusion, leaving null for actual pointers. And it would almost certinly
kill off all of the cases where null was treated as special for dynamic
arrays except maybe for when dealing with C code, but in that case, they'd
have to use ptr directly. However, at this point, I expect that that's all
water under the bridge, and we're stuck with it.

- Jonathan M Davis



Re: scope guards & debugger breakpoints?

2018-05-21 Thread Robert M. Münch via Digitalmars-d-learn

On 2018-05-21 17:24:12 +, Steven Schveighoffer said:


I'm not 100% sure but I expect:

scope(failure)
someCode();

putting a breakpoint on someCode should work.


When calling a function an then setting the breakpoint there, like in 
someCode() yes, that should work.


I used code like this:

scope(failure) {
... several lines of code
}

And for this it seems (maybe I need to check in more detail) that in 
MSVC, I can set a breakpoint, but the breakpoint is not triggered when 
an exception is thrown.


--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



VisualD / fatal error C1905: Front-End and Back-End are not compatible (have to use the same processor)

2018-05-21 Thread Robert M. Münch via Digitalmars-d-learn
A project I can compile via the command line and dub, gives an error in 
VisualD. I created the VisualD configuration through dub:


fatal error C1905: Front-End und Back-End sind nicht kompatibel 
(müssen den gleichenProzessor verwenden).


This translates to: "Front-End and Back-End are not compatible (have to 
use the same processor)"


Well, I don't have a clue what this should mena, nor how this could 
happen. It sounds a bit like if the compiler & linker are not useing 
the same architecture (I want to use x64) but I didn't find any options 
to check/change this.


Any ideas?

--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: Splitting up large dirty file

2018-05-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 21, 2018 15:00:09 Dennis via Digitalmars-d-learn wrote:
> On Thursday, 17 May 2018 at 21:10:35 UTC, Dennis wrote:
> > It's unfortunate that Phobos tells you 'there's problems with
> > the encoding' without providing any means to fix it or even
> > diagnose it.
>
> I have to take that back since I found out about std.encoding
> which has functions like `sanitize`, but also `transcode`. (My
> file turned out to actually be encoded with ANSI / Windows-1252,
> not UTF-8)
> Documentation is scarce however, and it requires strings instead
> of forward ranges.
>
> @Jon Degenhardt
>
> > Instead of:
> >  auto outputFile = new File("output.txt");
> >
> > try:
> > auto outputFile = File("output.txt", "w");
>
> Wow I really butchered that code. So it is the `drop(4)` that
> triggers the UTFException?

drop is range-based, so if you give it a string, it's going to decode
because of the whole auto-decoding mess with std.range.primitives.front and
popFront. If you can't have auto-decoding, you either have to be dealing
with functions that you know avoid it, or you need to do use something like
std.string.representation or std.utf.byCodeUnit to get around the
auto-decoding. If you're dealing with invalid Unicode, you basically have to
either convert it all up front or do something like treat it like binary
data, or Phobos is going to try to decode it as Unicode and give you a
UTFExceptions.

> I find Exceptions in range code hard to interpret.

Well, if you just look at the stack trace, it should tell you. I don't see
why ranges would be any worse than any other code except for maybe the fact
that it's typical to chain a lot of calls, and you frequently end up with
wrapper types in the stack trace that you're not necessarily familiar with.
The big problem here really is that all you're really being told is that
your string has invalid Unicode in it somewhere and the chain of function
calls that resulted in std.utf.decode being called on your invalid Unicode.
But even if you weren't dealing with ranges, if you passed invalid Unicode
to something completely string-based which did decoding, you'd run into
pretty much the same problem. The data is being used outside of its original
context where you could easily figure out what it relates to, so it's going
to be a problem by its very nature. The only real solution there is to be
controlling the decoding yourself, and even then, it's easy to be in a
position where it's hard to figure out where in the data the bad data is
unless you've done something like keep track of exactly what index your at,
which really doesn't work well once you're dealing with slicing data.

> @Kagamin
>
> > Do it old school?
>
> I want to be convinved that Range programming works like a charm,
> but the procedural approaches remain more flexible (and faster
> too) it seems. Thanks for the example.

The whole auto-decoding mess makes things worse than they should be, but if
you find procedural examples more flexible, then I would guess that that
would be simply a matter of getting more experience with ranges. Ranges are
far more composable in terms of how they're used, which tends to inherently
make them more flexible. However, it does result in code that's a mixture of
functional and procedural programming, which can be quite a shift for some
folks. So, there's no question that it takes some getting used to, but D
does allow for the more classic approaches, and ranges are not always the
best approach.

As for performance, that depends on the code and the compiler. It wouldn't
surprise me if dmd didn't optimize out the range stuff as much as it really
should, but it's my understanding that ldc typically manages to generate
code where the range abstraction didn't cost you anything. If there's an
issue, I think that it's frequently an algorithmic one or the fact that some
range-processing has a tendency to process the same data multiple times,
because that's the easiest, most abstract way to go about it and works in
general but isn't always the best solution.

For instance, because of how the range API works, when using splitter, if
you iterate through the entire range, you pretty much have to iterate
through it twice, because it does look-ahead to find the delimiter and then
returns you a slice up to that point, after which, you process that chunk of
the data to do whatever it is you want to do with each split piece. At a
conceptual level, what you're doing with your code with splitter is then
really clean and easy to write, and often, it should be plenty efficient,
but it does require going over the data twice, whereas if you looped over
the data yourself, looking for each delimiter, you'd only need to iterate
over it once. So, in cases like that, I'd fully expect the abstraction to
cost you, though whether it costs enough to matter depends on what you're
doing.

As is the case when dealing with most abstractions, I think that it's mostly
a matter of using it where it makes sense 

Re: scope guards & debugger breakpoints?

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 1:00 PM, Robert M. Münch wrote:
If I use scope(failure) with code that should be run if an exception is 
thrown, how can I set a breakpoint for this code in the debugger?




I'm not 100% sure but I expect:

scope(failure)
   someCode();

putting a breakpoint on someCode should work.

-Steve


scope guards & debugger breakpoints?

2018-05-21 Thread Robert M. Münch via Digitalmars-d-learn
If I use scope(failure) with code that should be run if an exception is 
thrown, how can I set a breakpoint for this code in the debugger?


--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: Temporary file creation for unittests

2018-05-21 Thread Russel Winder via Digitalmars-d-learn
On Mon, 2018-05-21 at 15:16 +, Atila Neves via Digitalmars-d-learn wrote:
> On Friday, 18 May 2018 at 15:16:52 UTC, Russel Winder wrote:
> > Hi,
> > 
> > What's the current official position on how to create temporary 
> > files for use during a unittest. I found
> 
> Not official, but...
> 
>  import unit_threaded;
> 
>  with(const Sandbox()) {
>  writeFile("myfile.txt", "contents");
>  shouldExist("myfile.txt");
>  shouldEqualContent("myfile.txt", "contents");
>  fileShouldContain("myfile.txt", "cont");
>  }
> 
> Atila

OK, we like this. A lot.

Given I use Unit-Threaded, why did I not know this. Ah, OK, RTFM. :-)

Did I mention how much I like this RAII approach?

-- 
Russel.
==
Dr Russel Winder  t: +44 20 7585 2200
41 Buckmaster Roadm: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


signature.asc
Description: This is a digitally signed message part


Re: UFCS syntax I never saw before.

2018-05-21 Thread SrMordred via Digitalmars-d-learn

"%s %s".writefln = ("foo".tuple = "bar").expand;

lol



How do I see the flags passed from dub to the compiler?

2018-05-21 Thread Dr.No via Digitalmars-d-learn

where's this stored?


Re: How do I see the flags passed from dub to the compiler?

2018-05-21 Thread rikki cattermole via Digitalmars-d-learn

On 22/05/2018 4:21 AM, Dr.No wrote:

where's this stored?


-v should do the trick


Re: Real Int24

2018-05-21 Thread Simen Kjærås via Digitalmars-d-learn
On Saturday, 19 May 2018 at 18:44:42 UTC, IntegratedDimensions 
wrote:
On Saturday, 19 May 2018 at 18:19:35 UTC, IntegratedDimensions 
wrote:
Is there any way to create an int24 type that behaves just 
like any other built in type without having to reimplement 
everything?


In fact, what I'd like to do is create an arbitrary type:

struct atype(T)
{

}

where atype(T) is just a "view" in to N_T bits interpreted as 
T, an enum.


If T is bit, then the N = 1 and the interpretation is 1 bit.
If T is byte, then the N = 8 and the interpretation is 7 bits 
followed by 1 signed bit.
If T is int24, then the N = 24 and the interpretation is 23 
bits followed by 1 signed bit.


The idea is the storage of atype is exactly N bits. If this is 
not possible due to boundary issues then N can always be a 
multiple of 8(which is for my use cause is the smallest).


D does not support types that take up less than one byte of 
space. It's possible to make types that represent less than one 
byte - bool may be considered such an example - but they still 
take up at least 1 byte.


If you create a custom range type, you could pack more than one 
element in each byte, see std.bitmanip.BitArray[0] for an example.



The main thing is that I would like to be able to use atype as 
if it were a built in type.


If N = 24, 3 bytes, I want to be able to create arrays of 
atype!int24[] which work just as if they were arrays of bytes 
without any exception or special cases.


atype!byte would be equivalent to byte and reduce to the 
compiler internals. I'm not looking to create a "view" of an 
array. I want a standalone type that can behave as all the 
desired types needed, which is most of the numerical types of D 
and some of the ones it neglected like 24-bit ints, 48-bit 
ints, etc. Ideally, any type could be used and the "most 
optimal" code is generated while being able to use the types 
using the standard model.


We already have std.numeric.CustomFloat[1]. As the name implies, 
it only works for floats.


I hacked together something somewhat equivalent for ints:

https://gist.github.com/Biotronic/f6668d8ac95b70302015fee93ae9c8c1

Usage:

// Two's-complement, native-endian, 24-bit int type:
CustomInt!24 a;

// Unsigned, native-endian, 15-bit:
CustomInt!(15, Representation.Unsigned) b;

// Offset (-2..5) 3-bit int:
CustomInt!(3, Representation.OffsetBinary, 2) c;

// You get the idea:
CustomInt!(64, Representation.SignedMagnitude, 0, 
Endianness.BigEndian) d;


Not sure this is what you're looking for, but it's at the very 
least inspired by your post. :)


If what you want is a type that can represent something a packed 
array of 13-bit ints, the above is not what you're looking for - 
you're going to need a custom range type.


--
  Simen

[0]: https://dlang.org/phobos/std_bitmanip#BitArray
[1]: https://dlang.org/phobos/std_numeric.html#.CustomFloat


Re: Temporary file creation for unittests

2018-05-21 Thread Dr.No via Digitalmars-d-learn

On Monday, 21 May 2018 at 15:16:11 UTC, Atila Neves wrote:

On Friday, 18 May 2018 at 15:16:52 UTC, Russel Winder wrote:

Hi,

What's the current official position on how to create 
temporary files for use during a unittest. I found


Not official, but...

import unit_threaded;

with(const Sandbox()) {
writeFile("myfile.txt", "contents");
shouldExist("myfile.txt");
shouldEqualContent("myfile.txt", "contents");
fileShouldContain("myfile.txt", "cont");
}

Atila


I've never seen "should" being in used in function names before...


Re: Mysql query result access by field name

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 10:59 AM, kdevel wrote:

On Monday, 21 May 2018 at 14:17:23 UTC, Steven Schveighoffer wrote:

    Data f;
    allrows[0].toStruct (f);

I haven't checked this.


This only works if your struct has exactly the same layout as the fields.

So if, for instance, your rows are selected "title", "name", 
"surname", but your data type orders them name, surname, title, you 
won't be happy with the result.


Haven't seen this. Then there is no more field-safety than in the OP's 
"assembler" code.


In the other post you wrote

| 1. Use ResultRange instead of the Row interface. This provides
| a couple of ways to use column names, .asAA to get all the data
| in a nice AA format (they are still variants),

The AA format can than be used to fill the struct automatically 
(detecting missing and excess fields) like in this code:


    T toStructX(T) (string[string] a)
    {
   T t;
   bool[string] bookkeep;
   foreach (i, m; t.tupleof) {
  string key = T.tupleof[i].stringof;
  if (key !in a) {
     stderr.writefln ("missing key <%s>", key);
     continue;
  }
  t.tupleof[i] = a[key].to!(typeof (m));
  bookkeep[key] = true;
   }
   foreach (x, y; a)
  if (x !in bookkeep)
     stderr.writefln ("excess key-value pair <%s>:<%s>", x, y);
   return t;
    }


Yes, this is very similar to what I do in my serialization library, 
except I don't use the AA, I keep a map of indexes based on the index of 
the field in the tuple to avoid allocation associated with an AA.


Note that your incoming AA is going to be a Variant[string].

-Steve


Re: Temporary file creation for unittests

2018-05-21 Thread Atila Neves via Digitalmars-d-learn

On Friday, 18 May 2018 at 15:16:52 UTC, Russel Winder wrote:

Hi,

What's the current official position on how to create temporary 
files for use during a unittest. I found


Not official, but...

import unit_threaded;

with(const Sandbox()) {
writeFile("myfile.txt", "contents");
shouldExist("myfile.txt");
shouldEqualContent("myfile.txt", "contents");
fileShouldContain("myfile.txt", "cont");
}

Atila


Re: Splitting up large dirty file

2018-05-21 Thread Dennis via Digitalmars-d-learn

On Thursday, 17 May 2018 at 21:10:35 UTC, Dennis wrote:
It's unfortunate that Phobos tells you 'there's problems with 
the encoding' without providing any means to fix it or even 
diagnose it.


I have to take that back since I found out about std.encoding 
which has functions like `sanitize`, but also `transcode`. (My 
file turned out to actually be encoded with ANSI / Windows-1252, 
not UTF-8)
Documentation is scarce however, and it requires strings instead 
of forward ranges.


@Jon Degenhardt

Instead of:

 auto outputFile = new File("output.txt");

try:

auto outputFile = File("output.txt", "w");


Wow I really butchered that code. So it is the `drop(4)` that 
triggers the UTFException? I find Exceptions in range code hard 
to interpret.


@Kagamin

Do it old school?


I want to be convinved that Range programming works like a charm, 
but the procedural approaches remain more flexible (and faster 
too) it seems. Thanks for the example.





Re: Mysql query result access by field name

2018-05-21 Thread kdevel via Digitalmars-d-learn
On Monday, 21 May 2018 at 14:17:23 UTC, Steven Schveighoffer 
wrote:

    Data f;
    allrows[0].toStruct (f);

I haven't checked this.


This only works if your struct has exactly the same layout as 
the fields.


So if, for instance, your rows are selected "title", "name", 
"surname", but your data type orders them name, surname, title, 
you won't be happy with the result.


Haven't seen this. Then there is no more field-safety than in the 
OP's "assembler" code.


In the other post you wrote

| 1. Use ResultRange instead of the Row interface. This provides
| a couple of ways to use column names, .asAA to get all the data
| in a nice AA format (they are still variants),

The AA format can than be used to fill the struct automatically 
(detecting missing and excess fields) like in this code:


   T toStructX(T) (string[string] a)
   {
  T t;
  bool[string] bookkeep;
  foreach (i, m; t.tupleof) {
 string key = T.tupleof[i].stringof;
 if (key !in a) {
stderr.writefln ("missing key <%s>", key);
continue;
 }
 t.tupleof[i] = a[key].to!(typeof (m));
 bookkeep[key] = true;
  }
  foreach (x, y; a)
 if (x !in bookkeep)
stderr.writefln ("excess key-value pair <%s>:<%s>", 
x, y);

  return t;
   }


Re: UFCS syntax I never saw before.

2018-05-21 Thread Dennis via Digitalmars-d-learn

On Monday, 21 May 2018 at 11:38:12 UTC, SrMordred wrote:

what??


Here's another weird example:
```
void funWithUfcsAndPropertySyntax() {
import std.typecons : tuple;
"%s %s".writefln = ("foo".tuple = "bar").expand;
}
```

source: 
https://github.com/Hackerpilot/Idiotmatic-D/blob/master/idiotmatic.d#L78


Re: UFCS syntax I never saw before.

2018-05-21 Thread Chris M. via Digitalmars-d-learn

On Monday, 21 May 2018 at 11:38:12 UTC, SrMordred wrote:

After all this time I saw this:

writeln = iota = 5;

what??

I never saw that before!

This is interesting, there is something useful that i can do 
with this kind of call?


That's pretty cool, but at the same time this should be wiped off 
the face of the Earth.


Re: Mysql query result access by field name

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 9:39 AM, kdevel wrote:

On Sunday, 20 May 2018 at 16:08:03 UTC, ipkwena wrote:
How does one access the columns fields in a Mysql query results by the 
column name.


[...]


Data f;
f.name = to!string(allrows[0][0]);
f.surname = to!string(allrows[0][1]);
f.title  = to!string(allrows[0][2]);

I am using the mysql-native package or DB connectivity.


According to the source code 
https://github.com/mysql-d/mysql-native/blob/master/source/mysql/result.d it 
should be possible to write the rowdata into the struct:


    Data f;
    allrows[0].toStruct (f);

I haven't checked this.


This only works if your struct has exactly the same layout as the fields.

So if, for instance, your rows are selected "title", "name", "surname", 
but your data type orders them name, surname, title, you won't be happy 
with the result.


-Steve


Re: UFCS syntax I never saw before.

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/21/18 8:15 AM, SrMordred wrote:

Right, so this should´n be working I think.


struct SomeStruct
{
    void foo(int);
}

SomeStruct s;
s.foo = 10;


I thought that only with @property this will work.



That was the plan, but it got derailed.

Whoever wrote that original line of code, they need a stern talking-to.

-Steve


Re: Mysql query result access by field name

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/20/18 12:08 PM, ipkwena wrote:

I have started learning D and I am enjoying it so far.

How does one access the columns fields in a Mysql query results by the 
column name. Currently I have to use the method as shown in a couple of 
example by indexing array values (f being a struct variable):


Data f;
f.name = to!string(allrows[0][0]);
f.surname = to!string(allrows[0][1]);
f.title  = to!string(allrows[0][2]);

I am using the mysql-native package or DB connectivity.


This is one of the weak spots of mysql-native -- the Row object has no 
knowledge of the column names, so you have to "know" the order of the 
columns you got from the server.


So what you can do is:

1. Use ResultRange instead of the Row interface. This provides a couple 
of ways to use column names, .asAA to get all the data in a nice AA 
format (they are still variants), .colNames to get the list of column 
names ordered by the row fields, or .colNameIndicies which gives you an 
AA of names to indices. Note that the AA generating versions will 
allocate a lot of throw-away data.


2. Write a complicated serialization library like I did :) In this case, 
I'm turning my ResultRange from a range of Rows to a range of the data 
type I want, all serialized by column name instead of index. 
Unfortunately, this is not open source so I can't share it.


At some point, I want to fix this part of mysql-native. I'm a bit 
annoyed that we have to do Variants instead of writing directly to the 
data type we are going to use anyway.


-Steve


Re: is ==

2018-05-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/18/18 9:48 PM, Jonathan M Davis wrote:

On Saturday, May 19, 2018 01:27:59 Neia Neutuladh via Digitalmars-d-learn
wrote:

On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions

wrote:

Why does D complain when using == to compare with null? Is
there really any technical reason? if one just defines == null
to is null then there should be no problem. It seems like a
pedantic move by who ever implemented it and I'm hoping there
is actually a good technical reason for it.


tldr: this error is outdated.

In the days of yore, "obj == null" would call
"obj.opEquals(null)". Attempting to call a virtual method on a
null object is a quick path to a segmentation fault. So "obj ==
null" would either yield false or crash your program.


I remember this, and I remember arguing for the current behavior many 
times (after having many many crashes) :)


https://forum.dlang.org/post/fqlgah$15v2$1...@digitalmars.com

Read that thread if you want to see the rationale.

However, I'd argue it's still good to keep the error as there is 
literally no point to not using == null on class references vs. is null. 
You now would get the same result, but it's faster/cleaner.



Actually, that runtime function has existed since before TDPL came out in
2010. It even shows the implementation of the free function opEquals (which
at the time was in object_.d rather than object.d). I'm not even sure that
the error message was added before the free function version of opEquals
was. Maybe when that error message was first introduced, it avoided a
segfault, but if so, it has been a _long_ time since that was the case.


Some things in TDPL were forward-thinking. I remember Andrei fleshing 
out some of how the languages SHOULD behave in the forums or mailing 
lists for the purposes of writing TDPL even though it didn't yet behave 
that way. In fact, I'm almost positive the new object comparison 
function came as a result of TDPL (but I'm not 100% sure). Some of TDPL 
still has never been implemented.


Long story short, don't date the existence of features in TDPL based on 
the publication :)


In this case, for fun (what is wrong with me), I looked up the exact 
date it got added, and it was Feb 2010: 
https://github.com/dlang/druntime/commit/2dac6aa262309e75ad9b524cb4d1c3c1f0ecc2ae. 
TDPL came out in June 2010, so this feature does predate TDPL by a bit.


In fact, through this exercise, I just noticed that the reason it 
returns auto instead of bool is to make sure it gets into the now 
defunct "generated" object.di file 
(https://github.com/dlang/druntime/pull/2190).



It *is* faster to call "foo is null" than "foo == null", but I
don't think that's particularly worth a compiler error. The
compiler could just convert it to "is null" automatically in that
case.


It's not worth a compiler error if we didn't already have it, but I 
don't know that it's worth taking out. It's really what you should be 
doing, it's just that the penalty for not doing it isn't as severe as it 
used to be.



One casualty of the current state of affairs is that no object
may compare equal to null.


And let's keep it that way!


Of
course, the most notable case where using == with null is a terrible idea is
dynamic arrays, and that's the case where the compiler _doesn't_ complain.


I use arr == null all the time. I'm perfectly fine with that, and 
understand what it means.



Using == with null and arrays is always unclear about the programmer's
intent and almost certainly wasn't what the programmer intended.


I beg to differ.


If the
programmer cares about null, they should use is. If they care about lengnth,
then that's what they should check. Checking null with == is just a huge
code smell.


IMO, doing anything based on the pointer of an array being null is a 
huge code smell. In which case, == null is perfectly acceptable. I'm 
comparing my array to an empty array. What is confusing about that?


I actually hate using the pointer in any aspect -- an array is 
semantically equivalent to its elements, it's not important where it's 
allocated. The only place D forces me to care about the pointer is when 
I'm dealing with ranges.



So, perhaps the compiler is being pedantic, but it's still telling you the
right thing. It's just insisting about it in the case where it matters less
while not complaining aobut it in the case where it really matters, which is
dumb. So IMHO, if anything, adding an error message for the array case would
make more sense than getting rid of the error with pointers and references.


I hope this never happens.

-Steve


Re: UFCS syntax I never saw before.

2018-05-21 Thread ANtlord via Digitalmars-d-learn

On Monday, 21 May 2018 at 11:38:12 UTC, SrMordred wrote:

After all this time I saw this:

writeln = iota = 5;

what??

I never saw that before!

This is interesting, there is something useful that i can do 
with this kind of call?


What the hell is this? I don't figure out why are there so many 
syntax features? It doesn't make the language more easier. Is it 
any reason to support 2 additional cases of function calling? We 
have no literal for a tuple but we call a function via 3 cases. 
I'm frustrated.


D has a lot cool features, I like D, but that is one of those 
which make me doubt the language future. I don't play a big role 
in the project but I talk to all my python co-workers: "You 
know... so there so cool language, it's called D. It can do this 
and that... It supports convenient static typing so you 
definitely know what happens in a piece of code.". But something 
like this make doubt about what happens in a piece of code. There 
is static typing so I know that type a variable has, but I look 
at a method calling and I ask: "Is it data field? No. Is it 
property? No. Is it method? No. It's UFCS! Okay." And now I see 
that UFCS can works the same way as a property!


Re: Mysql query result access by field name

2018-05-21 Thread kdevel via Digitalmars-d-learn

On Sunday, 20 May 2018 at 16:08:03 UTC, ipkwena wrote:
How does one access the columns fields in a Mysql query results 
by the column name.


[...]


Data f;
f.name = to!string(allrows[0][0]);
f.surname = to!string(allrows[0][1]);
f.title  = to!string(allrows[0][2]);

I am using the mysql-native package or DB connectivity.


According to the source code 
https://github.com/mysql-d/mysql-native/blob/master/source/mysql/result.d it should be possible to write the rowdata into the struct:


   Data f;
   allrows[0].toStruct (f);

I haven't checked this.


assertNotThrown (and asserts in general)

2018-05-21 Thread Malte via Digitalmars-d-learn
I was interested by asserts and how the compiler uses them to 
optimize the code. So I looked at the compiler explorer to see 
how and found it, it doesn't.


What I tried to do is turn a std.conv.to!ulong(byte) to a simple 
cast with the help of assertions.

https://godbolt.org/g/4uckWU

If there is an assert right before an if with the same condition, 
I think it should remove the compare and jump in release, but it 
doesn't. I'm assuming the compilers just aren't ready yet, but 
should be someday. At least that is what the documentation 
promises.


More curious made me 
"assertNotThrown!ConvOverflowException(input.to!ubyte)" where it 
didn't even remove the assert code in release and produced the 
most inefficient assembly.
Is that intended behaviour? In my opinion that greatly limits the 
usabilty of it.


Re: UFCS syntax I never saw before.

2018-05-21 Thread SrMordred via Digitalmars-d-learn

Right, so this should´n be working I think.


struct SomeStruct
{
void foo(int);
}

SomeStruct s;
s.foo = 10;


I thought that only with @property this will work.



Re: Copying an std.stdio.File into another one

2018-05-21 Thread rikki cattermole via Digitalmars-d-learn

On 21/05/2018 11:50 PM, 0xEAB wrote:

What's the correct way to copy a `File` into another one in D?

If `LockingTextReader` wasn't undocumented, I'd have gone for that 
approach:



import std.algorithm.mutation : copy;
import std.stdio : File, LockingTextReader;

void main()
{
    auto a = File("a.txt", "r");
    auto b = File("b.txt", "w");

    a.LockingTextReader.copy(b.lockingTextWriter);
}



Side-note:
Although the example code suggest otherwise, I'm not talking about 
copying actual files on disk. In such a case I'd just use 
`std.file.copy` ;)

So, just imagine `a` were `stdout` of process pipe.


Kind regards,
Elias


I would probably start by reading it byChunk and writing it out as a 
rawWrite or something along those lines. That way its using a nice 
buffer (to limit memory usage).


Copying an std.stdio.File into another one

2018-05-21 Thread 0xEAB via Digitalmars-d-learn

What's the correct way to copy a `File` into another one in D?

If `LockingTextReader` wasn't undocumented, I'd have gone for 
that approach:



import std.algorithm.mutation : copy;
import std.stdio : File, LockingTextReader;

void main()
{
auto a = File("a.txt", "r");
auto b = File("b.txt", "w");

a.LockingTextReader.copy(b.lockingTextWriter);
}



Side-note:
Although the example code suggest otherwise, I'm not talking 
about copying actual files on disk. In such a case I'd just use 
`std.file.copy` ;)

So, just imagine `a` were `stdout` of process pipe.


Kind regards,
Elias



Re: UFCS syntax I never saw before.

2018-05-21 Thread Rubn via Digitalmars-d-learn

On Monday, 21 May 2018 at 11:38:12 UTC, SrMordred wrote:

After all this time I saw this:

writeln = iota = 5;

what??

I never saw that before!

This is interesting, there is something useful that i can do 
with this kind of call?


I probably wouldn't use that. That wasn't what it was intended 
for and it's not really UFCS. It's was meant for properties that 
are defined as functions.


struct SomeStruct
{
void foo(int);
}

SomeStruct s;
s.foo = 10;

It's kind of horrible syntax for what it is doing, where it isn't 
obvious what is happening. Writeln and iota aren't setting 
anything, they are just function calls that happen to be able to 
take one parameter.


UFCS syntax I never saw before.

2018-05-21 Thread SrMordred via Digitalmars-d-learn

After all this time I saw this:

writeln = iota = 5;

what??

I never saw that before!

This is interesting, there is something useful that i can do with 
this kind of call?