Re: std.file.read returns void[] why?

2014-04-17 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 17 April 2014 at 12:59:20 UTC, Steven Schveighoffer 
wrote:

It was never possible. You must explicitly cast to void[].

void[] makes actually little sense as the result of whole-file 
read that allocates. byte[] is at least usable and more 
accurate. In fact, it's a little dangerous to use void[], since 
you could assign pointer-containing values to the void[] and it 
should be marked as NOSCAN (no pointers inside file data).


However, when using the more conventional read(void[]) makes a 
LOT of sense, since any T[] implicitly casts to void[].


-Steve


void[] will only make sense once you've accepted that 
void.sizeof == 1.


Well, I guess void[] is C++'s char* for indiscriminate 
buffers. Speaking of which, does void* trigger strict aliasing 
in D? This subject seems like a hot potato no-one wants to touch.


Re: std.file.read returns void[] why?

2014-04-18 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 17 April 2014 at 21:27:44 UTC, Steven Schveighoffer 
wrote:
On Thu, 17 Apr 2014 17:04:25 -0400, monarch_dodra 
monarchdo...@gmail.com wrote:
void[] will only make sense once you've accepted that 
void.sizeof == 1.


It is already accepted that when we talk about length in a 
void[], it's the number of bytes. But the data has no formal 
type.


Well, I always thought that void[] slice meant there are 
slice.length items, starting at slice.ptr. I don't know the size 
of the individual items.


For example, in C, a lot of functions take void* first, size_t 
num, size_t width.


In fact, most of druntime functions take void[] buffers that 
work that way. There's an associated typeid, so that you can now 
how large each individual items are.


But any array implicitly casts to void[]. This is why it makes 
a good parameter for read or write (when reading or writing the 
binary data).


I guess. I just find it kind of strange that a type that has no 
type would have an actual sizeof. Then again, I thought void had 
no sizeof in C, but I just checked, and I was wrong.


Well, I guess void[] is C++'s char* for indiscriminate 
buffers. Speaking of which, does void* trigger strict 
aliasing in D? This subject seems like a hot potato no-one 
wants to touch.


No, it's equivalent to void *, not char *.

in D, ubyte[] would be the equivalent of C's char *.

-Steve


Correct.


Re: std.file.read returns void[] why?

2014-04-18 Thread monarch_dodra via Digitalmars-d-learn
On Friday, 18 April 2014 at 13:08:04 UTC, Steven Schveighoffer 
wrote:
I admit, I didn't think C's void had a size ;) I'm pretty sure 
it doesn't in D, but then again...


-Steve


Yeah... static assert(void.sizeof == 1); passes :/

So in any case, long story short:
void[]: This is an un-typed buffer, pointing to a memory 
location that starts at .ptr, and is .length bytes in length.


Also, as far as the GC is concerned, void is a type that should 
be scanned (whether or not the data originally allocated was 
marked as such is another issue).


Re: Reducing an array

2014-04-18 Thread monarch_dodra via Digitalmars-d-learn
On Friday, 18 April 2014 at 20:27:20 UTC, Steven Schveighoffer 
wrote:
Note also that what it returns is not an array, but a lazily 
iterated range over the array. If you want another array, this 
is the code I would use:


arr.sort();
arr = arr.uniq.array();

-Steve


Out of curiosity, if the requirement was to *also* preserve 
ordering (eg: remove all non-first elements), how would you go at 
it?


[2, 1, 1, 3, 2, 3] = [2, 1, 3];

Maybe std.algorithm's `makeIndex` would help here?

Bonus points for doing it inplace.


Re: Reducing an array

2014-04-19 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 18 April 2014 at 22:11:17 UTC, bearophile wrote:

monarch_dodra:

Out of curiosity, if the requirement was to *also* preserve 
ordering (eg: remove all non-first elements), how would you go 
at it?


[2, 1, 1, 3, 2, 3] = [2, 1, 3];

Maybe std.algorithm's `makeIndex` would help here?

Bonus points for doing it inplace.


This preserves ordering and it's in-place. Not tested much:

void main() {
import std.stdio, std.traits;

auto data = [2, 1, 1, 3, 2, 3];

bool[ForeachType!(typeof(data))] seen;
size_t pos = 0;
foreach (immutable i; 0 .. data.length)
if (data[i] !in seen) {
if (pos != i)
data[pos] = data[i];
seen[data[i]] = true;
pos++;
}
data.length = pos;

data.writeln;
}


Bye,
bearophile


I thought of an approach somewhere along these lines. I was 
wondering if there was a UFCS approach too. Or an in-place 
approach.


Well, the inplace is easy of you accept N² performance :)


Re: Reducing an array

2014-04-19 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 18 April 2014 at 22:11:17 UTC, bearophile wrote:

This preserves ordering and it's in-place. Not tested much:

void main() {
import std.stdio, std.traits;

auto data = [2, 1, 1, 3, 2, 3];

bool[ForeachType!(typeof(data))] seen;
size_t pos = 0;
foreach (immutable i; 0 .. data.length)
if (data[i] !in seen) {
if (pos != i)
data[pos] = data[i];
seen[data[i]] = true;
pos++;
}
data.length = pos;

data.writeln;
}


Bye,
bearophile


If you replace that = with a swap, then you can also preserve 
the duplicate elements at the end (although in no specific 
ordering):


import std.stdio : writefln;
import std.algorithm : canFind, swap;

//
void main()
{
auto arr = [1,1,5,2,3,2,2,4,5,5,1];
size_t pos = 0;
foreach(ref e; arr)
if (!arr[0 .. pos].canFind(e))
swap(arr[pos++], e);
writefln(uniques: %s, arr[0 .. pos]);
writefln(dupes:   %s, arr[pos .. $]);
}
//

I was trying a 100% inplace solution, but I found nothing 
better than N². It's  basically still what you submitted though.


Re: Template method and type resolution of return type

2014-04-20 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 20 April 2014 at 07:52:08 UTC, matovitch wrote:


struct S
{
   ubyte get()  { return 0 ; }
   float get()  { return 0.; }
}

void main()
{
   S s;
   float x = s.get();  // does'nt know which overload, does'nt 
compile.

}


What I do find interesting though, is that you are allowed to 
write the overload, whereas C++ would outright block you for 
ambiguity at the source.


This means that with proper meta magic eg 
`__traits(getOverloadSet, S, get)`, you could, *manually* 
resolve the ambiguity yourself.


Re: number formatting

2014-04-20 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 20 April 2014 at 12:53:11 UTC, steven kladitis wrote:

Note sure if you can edit messages once sent.

 $13,456.67
 245,678,541


On Sunday, 20 April 2014 at 12:50:52 UTC, steven kladitis wrote:

How do you format numbers to have things like.
Leading $ or , or CR with or without leading zeros.
 for example $56.00
 $056.00
 $1,3456.67
 345.89CR


Simply add what you want in the format string. For example:

double d = 56.55;
writefln($03.5s, d);
writefln(.4sCR, d);

will print
$056.55
56.55CR

I don't know of any built-in way to do number grouping.

Also, when dealing with monetary amounts, you shouldn't be using 
doubles (I'm not saying you are), but some other structure 
specifically designed to track cents. Ideally, such a structure 
would have built-in toString formating.


Re: string - string literal

2014-04-20 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 20 April 2014 at 17:55:25 UTC, Ellery Newcomer wrote:
is there a function in phobos anywhere that takes a string and 
escapes it into a string literal suitable for string mixins? 
something like


assert (f(abc\ndef) == \abc\\ndef\);


It's a bit hackish, but it avoids deploying code and reinventing 
anything. You can use format string-range formating to print 
the string escaped. Catch that, and then do it again:


string s = abc\ndef;
writefln([%s]\n, s); //raw

s = format(%(%s%), [s]);
writefln([%s]\n, s); //escaped

s = format(%(%s%), [s]);
writefln([%s]\n, s); //escapes are escaped

As you can see from the output, after two iterations:

[abc
def]

[abc\ndef]

[\abc\\ndef\]

I seem to recall that printing strings escaped has been 
requested before, but, AFAIK, this is the best we are currently 
providing.


Unless you call std.format's formatElement directly. However, 
this is an internal and undocumented function, and the fact it 
isn't private is probably an oversight.


Re: Function to print a diamond shape

2014-04-21 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 21 April 2014 at 00:11:14 UTC, Jay Norwood wrote:
So this printDiamonde2b example had the fastest time of the 
solutions, and had similar times on all three builds. The ldc2 
compiler build is performing best in most examples on ubuntu.


void printDiamonde2b(in uint N)
{
uint N2 = N/2;
char pSpace[] = uninitializedArray!(char[])(N2);
pSpace[] = ' ';

char pStars[] = uninitializedArray!(char[])(N+1);
pStars[] = '*';

pStars[$-1] = '\n';

auto w = appender!(char[])();
w.reserve(N*3);

foreach (n ; 0 .. N2 + 1){
w.put(pSpace[0 .. N2 - n]);
w.put(pStars[$-2*n-2 .. $]);
}

foreach_reverse (n ; 0 .. N2){
w.put(pSpace[0 .. N2 - n]);
w.put(pStars[$-2*n-2 .. $]);
}

write(w.data);
}


With this slightly tweaked solution, I can get times of roughly 
50% to 100% faster, on my dmd-linux box:


//
void printDiamonde2monarch(in uint N)
{
uint N2 = N/2;

char[] pBuf = uninitializedArray!(char[])(N + N2);
pBuf[ 0 .. N2] = ' ';
pBuf[N2 ..  $] = '*';

auto slice = uninitializedArray!(char[])(3*N2*N2 + 4*N);

size_t i;
foreach (n ; 0 .. N2 + 1){
auto w = 1 + N2 + n;
slice[i .. i + w] = pBuf[n .. w + n];
slice[(i+=w)++]='\n';
}

foreach_reverse (n ; 0 .. N2){
auto w = 1 + N2 + n;
slice[i .. i + w] = pBuf[n .. w + n];
slice[(i+=w)++]='\n';
}

write(slice[0 .. i]);
}
//

The two key points here, first, is to avoid using appender. 
Second, instead of having two buffer:  and **\n, and 
two do two slice copies, to only have 1 buffer *, and 
to do 1 slice copy, and a single '\n' write. At this point, I'm 
not sure how we could be going any faster, short of using 
alloca...


How does this hold up on your environment?


Re: Named template constraints

2014-04-22 Thread monarch_dodra via Digitalmars-d-learn
On Tuesday, 22 April 2014 at 15:06:34 UTC, Steven Schveighoffer 
wrote:

Note, is the r2 = R.init needed? Not sure.


Yes: It R2 has no default init, or is an immutable, then that 
line will fail to compile.


Re: Function to print a diamond shape

2014-04-22 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 22 April 2014 at 05:05:30 UTC, Jay Norwood wrote:

On Monday, 21 April 2014 at 08:26:49 UTC, monarch_dodra wrote:
The two key points here, first, is to avoid using appender. 
Second, instead of having two buffer:  and **\n, 
and two do two slice copies, to only have 1 buffer 
*, and to do 1 slice copy, and a single '\n' write. At 
this point, I'm not sure how we could be going any faster, 
short of using alloca...


How does this hold up on your environment?


Yes your solution is the fastest yet.  Also, its times are 
similar for all three compilers.   The range of execution times 
varied for different solutions from over 108 seconds down to 64 
msec.


I see that RefAppender's data() returns the managed array.  Can 
write() handle that?  It seems that would be more efficient 
than duplicating the  character buffer ...


I'm not sure what you mean? data returns the managed array, but 
no duplication ever actually happens. It's allocated on the GC. 
the only thing that is copied is the slice itself.


or perhaps writing directly to an OutBuffer, and then sending 
that to write() would avoid the duplication?


appender *is* the outbuffer :)


Re: Function to print a diamond shape

2014-04-22 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 22 April 2014 at 11:41:41 UTC, Jay Norwood wrote:
Wow,  joiner is much slower than join.  Such a small choice can 
make this big of a difference.  Not at all expected, since the 
lazy calls, I thought, were considered to be more efficient.  
This is with ldc2 -O2.


Yeah, that's because join actually works on RoR, R, rather than 
R, E. This means if you feed it a string[], string, then it 
will actually iterate over individual *characters*. Not only 
that, but since you are using char[], it will decode them too.


join is faster for 2 reasons:
1) It detects you want to joins arrays, so it doesn't have to 
iterate over them: It just glues them slice at once

2) No UTF decoding.

I kind of wish we had a faster joiner, but I think it would have 
made the call ambiguous.


Re: Named template constraints

2014-04-22 Thread monarch_dodra via Digitalmars-d-learn
On Tuesday, 22 April 2014 at 15:30:36 UTC, Steven Schveighoffer 
wrote:
On Tue, 22 Apr 2014 11:15:14 -0400, monarch_dodra 
monarchdo...@gmail.com wrote:


On Tuesday, 22 April 2014 at 15:06:34 UTC, Steven 
Schveighoffer wrote:

Note, is the r2 = R.init needed? Not sure.


Yes: It R2 has no default init, or is an immutable, then that 
line will fail to compile.


I don't believe it's possible to have no 'init'.

I think the reason it says '= R.init' is for ranges that have 
@disable this().


Yes, that's what I meant by no default init. Guess I got my 
terms wrong. Sorry.



Also, an immutable can be initialized that way:

immutable int[] = int[].init;


Isn't that exactly R.init ?


Of course, it wouldn't pass the rest of isInputRange.

-Steve


In this particular case, probably not (except for, maybe 
repeat?) In any case, it's become the generic way of 
initializing a generic type.


Re: The lifetime of reduce's internal seed

2014-04-22 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 22 April 2014 at 17:31:22 UTC, Ali Çehreli wrote:
I opened the following bug before reading reduce's 
documentation carefully:


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

import std.stdio;
import std.algorithm;

void main()
{
int[] arr = [ 0 ];

int[1] seed;
int[] result = reduce!((sum, _) = sum[])(seed, arr);

writefln(%s, result);
}

The output is garbage like [373728176].

Note that the original seed is a value type, which is later 
sliced by the lambda.


Now I think that it can be considered a user error. Do you 
agree whit that? If so, this is something else we should be 
careful about similar to the internal buffer of byLine.


Ali


I see one user bug, and one language bug, but no library issues.

The user bug is the lambda, that returns a reference to a local 
(sum[]). That said, I do believe the compiler should be able to 
catch think.


The int[] reduce..., however, I think is a outright language 
issue. Implicilty calling opSlice on a static array is one thing, 
but doing it on an rvalue is an outright aberration. The code 
should be rejected no questions asked.


Re: The lifetime of reduce's internal seed

2014-04-22 Thread monarch_dodra via Digitalmars-d-learn
On Tuesday, 22 April 2014 at 18:34:47 UTC, Steven Schveighoffer 
wrote:
On Tue, 22 Apr 2014 14:17:57 -0400, Ali Çehreli 
acehr...@yahoo.com wrote:


I don't think there is slicing an rvalue though. (?) reduce() 
is taking a copy of the seed and then returning a slice to it 
because the user slices it in their lambda. It effectively 
does the following, which unfortunately compiles:


int[] foo()
{
int[1] sum;
return sum[];// -- no warning
}


It's not slicing an rvalue, but the above is trivially no 
different than:


In this case no, but;
//
int[1] foo();
int[] a = foo();
//
*is* slicing an rvalue, and it *does* compile. I don't think 
there needs to be escape analysis to catch this.


Re: The lifetime of reduce's internal seed

2014-04-23 Thread monarch_dodra via Digitalmars-d-learn
On Tuesday, 22 April 2014 at 18:49:41 UTC, Steven Schveighoffer 
wrote:
On Tue, 22 Apr 2014 14:47:19 -0400, monarch_dodra 
monarchdo...@gmail.com wrote:



In this case no, but;
//
int[1] foo();
int[] a = foo();
//
*is* slicing an rvalue, and it *does* compile. I don't think 
there needs to be escape analysis to catch this.


Oh yeah, that's bad.

-Steve


It's filed:
https://issues.dlang.org/show_bug.cgi?id=12625

I hope it gets fixed. I really see no justification for it.


Re: Partial ordering of constructors with type parameters

2014-04-23 Thread monarch_dodra via Digitalmars-d-learn
On Wednesday, 23 April 2014 at 16:44:37 UTC, Charles McAnany 
wrote:

Friends,

I have a class that needs two constructors:

class Foo{
this(int x){}
this(T)(T x) if(!is(T == int)){}
}
void main(){}

But this does not compile because the two constructors conflict:

buggy.d(3): Error: template buggy.Foo.__ctor(T)(T x) if (!is(T 
== int)) conflicts with constructor buggy.Foo.this at buggy.d(2)


Of course, I can just have one constructor that doesn't have 
the constraint and then use a static if to redirect to a 
private method, but that seems clunky to me. (not to mention it 
would complicate the documentation.)


Any ideas?

Cheers,
Charles McAnany.


Update your compiler. What version are you on? This was resolved 
in the 2.064 release. You don't even need the if(!is(T == 
int)), since non-template takes precendence.


//
class Foo{
this(int x){}
this(T)(T x) {}
}
void main()
{
auto a = new Foo(5);
}
//

If you can't update your compiler, an alternative is to make your 
non-template version an actual template:


class Foo{
this(T : int)(T x){}
this(T)(T x) {}
}


Re: Partial ordering of constructors with type parameters

2014-04-24 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 23 April 2014 at 22:07:32 UTC, John Colvin wrote:
On Wednesday, 23 April 2014 at 18:04:05 UTC, monarch_dodra 
wrote:
If you can't update your compiler, an alternative is to make 
your non-template version an actual template:


class Foo{
   this(T : int)(T x){}
   this(T)(T x) {}
}


I haven't tested, but wouldn't this be more precisely 
equivalent?:


class Foo{
this()(int x){}
this(T)(T x) {}
}


*That* creates a conflict though :/


Re: Partial ordering of constructors with type parameters

2014-04-24 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 24 April 2014 at 10:12:15 UTC, Andrej Mitrovic via 
Digitalmars-d-learn wrote:

On 4/24/14, monarch_dodra via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

*That* creates a conflict though :/


Are you sure? I can't reproduce.


Weird. I can't either. I probably accidentally tested it on 
2.063? Who cares; yes, it's more practical.


Re: The lifetime of reduce's internal seed

2014-04-26 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 26 April 2014 at 06:24:26 UTC, Ali Çehreli wrote:

On 04/22/2014 11:45 AM, monarch_dodra wrote:

 Reduce returns the seed. It's actually doing something more
like this:

 int[1] foo()
 {
  int[1] sum
  sum = sum[]; //The lambda operates, and the
   //result is assigned back to the seed.
  return sum; //Returns the seed.
 }

My original lambda that returned a slice was correct then. The 
seed would eventually be copied out. Had the compiler not allow 
slicing the rvalue then I would be in good shape.


Well... your lambda *was* returning a slice to its local copy of 
sum. So I thin kit is still wrong. (ref sum, _) = sum[] would 
have been correct though.



 BTW, I'm re-implemented reduce recently (not yet pulled), but
I was
 *very* thorough about documenting what it does:
 https://github.com/D-Programming-Language/phobos/pull/2060

 Could you take a look at it (the documentation I mean), and
tell me if
 everything is what you would have expected?

I think it looks great! :)

Two comments/questions which I did not make on github:

1) Some of the documentation comments that are inside a scope 
are not formatted as such. For example, this comment does not 
start with /++ :



https://github.com/monarchdodra/phobos/blob/reduceReimpl/std/algorithm.d#L753

I wonder whether they are still included in the produced 
documentation.


Nope, that was a mistake on my part. Good catch.

2) I think even single-line code blocks should have curly 
brackets but Phobos code does not follow that guideline. :)


Ali


It depends I say. I usually do that, but for certain functions, 
such as reduce, it would *literally* double the amount of lines 
required to write it. I that point, the function becomes long 
enough for it to be a readability problem.


Re: Can I circumvent nothrow?

2014-04-27 Thread monarch_dodra via Digitalmars-d-learn
On Sunday, 27 April 2014 at 08:04:54 UTC, Andrej Mitrovic via 
Digitalmars-d-learn wrote:

On 4/27/14, Damian Day via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

So I have this procedure.


Have a look at std.exception.assumeWontThrow:
http://dlang.org/phobos/std_exception.html#.assumeWontThrow


Keep in mind that assume won't throw will assert *should* an 
exception actually be thrown.


If the function actually can and will throw, but you simply don't 
care, you'd need a squelchException (which we don't have), or 
more simply, just:

//
try {
myCode();
} catch (Exception){}
//


Re: Trailing commas in constructor arguments?

2014-05-04 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 4 May 2014 at 10:04:26 UTC, Gary Willoughby wrote:
In the following snippet is the line marked WOAH legal? The 
compiler doesn't complain about the trailing comma in the 
constructor arguments.


import std.stdio;

class Foo
{
public this(string foo)
{
}
}

void main(string[] args)
{
auto foo = new Foo(bar, ); // -- WOAH
}


Yes. As a rule of thumb, a single trailing comma is *always* 
legal. It allows for easier and uniform syntax for calls with 
lots of arguments:


new Foo(
  bar1,
  bar2,
  bar3,
  bar4,
);

This works for mostly anything: both calls and function 
declaration:


this(
string arg1,
string arg2,
string arg3,
string arg4,
)
{
   ...
}

It also works for arrays:
auto arr1= [
1,
2,
3,
4,
];

Or enums:
enum Letters
{
A,
B,
C,
D,
}

The advantage in all the above means no special case if you want 
to add, swap or comment a certain argument: They are all equal 
in terms of separator comma.


Finally, it makes mixins/generated code easier, since you don't 
have to worry about the last argument special case (though if 
you use range formating: %(%s,%), it shouldn't matter).




So long story short, yes, it is legal. And convenient. I've 
personally adopted it, and use it any time I list arguments 
vertically.


Re: Is this a bug?

2014-05-04 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 4 May 2014 at 09:42:17 UTC, Alex wrote:

Hello,

I am trying to use the std.log module that is here:

https://github.com/linkrope/log.d

And I encountered a segmentation fault using dmd 2.065 on a 
Linux 64 platform. The reduced test case is this:


//
import std.stdio;
import std.log;

private class CHello {

~this() {
		info(info - destructor); //info, warning, error segfault; 
however, writefln works

}
}

void main(string[] args) { CHello chello = new CHello(); }
//

Is this a bug?


Maybe, maybe not. As rule of thumb, you can't allocate during a 
GC cleaning cycles, and class destructors are usually called 
during a GC cleaning cycle.


This means it is usually unsafe to call *anything* that could 
potentially allocate in a destructor.


I don't know the details of the log module. AFAIK, the code 
itself doesn't *seem* to allocate anything to just log, but it 
does seem to use a singleton logger object.


Could you try to log a single info in your main, and see if it 
resolves the issue?


We'd need to contact the author directly too about this issue.


Re: Is this a bug?

2014-05-04 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 4 May 2014 at 10:28:30 UTC, Mike Parker wrote:
The current implementation of the GC will run destructors on 
any objects still resident on the heap during termination. 
There is no way to guarantee the order in which those 
destructors will be run.


Most likely, what you're seeing is that the LogFilter instance 
referenced by the info template is being destroyed before the 
destructor on CHello is run. Therefore, you're referencing an 
invalid memory location.


The short of it is that you should never touch anything on that 
lives on the GC heap from inside a destructor -- there's no 
guarantee that it will still be alive when your destructor is 
run.


Really??? I knew there was no guarantee in which order the 
destructor were run, but at the very least, I thought you had a 
guarantee of dependency ordering?


...

Then again, the GC can collect cycles, so...

Well dang. That's a bummer.


Is my T.init elaborate (eg: Not 0)

2014-05-05 Thread monarch_dodra via Digitalmars-d-learn
I'm looking for a way, to *statically* know if my type's .init 
value is nothing but zeros.


I need this to initialize a dynamic array: If the T.init is 
nothing but 0, then I can just memset the whole array in a single 
call. Otherwise, I have to memcpy T.init individually N times.


Currently, I can (runtime) use typeid(T).init.ptr: Types that 
don't have an an elaborate .init will return null.


I'm trying to find the same result, without a runtime check. 
Anybody know how? I'd write a function that tests the bits of a 
T.init copy, but reinterpreting is not allowed during CTFE...


Re: Is my T.init elaborate (eg: Not 0)

2014-05-06 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 5 May 2014 at 21:54:33 UTC, Tobias Pankrath wrote:

On Monday, 5 May 2014 at 21:51:14 UTC, Tobias Pankrath wrote
I'm trying to find the same result, without a runtime check. 
Anybody know how? I'd write a function that tests the bits of 
a T.init copy, but reinterpreting is not allowed during 
CTFE...


Foreach member x of Type X of T, check if T.init.x equals 
X.init?


Ah, sorry, didn't read carefully. This is not what you want.


Actually, I think you're on to something. I can recursively 
iterate on all basic types in my T, and check they are all 0 or 
NULL. Should work.


Thanks!


Re: throws Exception in method

2014-05-08 Thread monarch_dodra via Digitalmars-d-learn

On Thursday, 8 May 2014 at 13:06:05 UTC, amehat wrote:

Okay.
Thank you for these explanations, I understand a little better 
the exceptions D.


Keep in mind that D also has the concept of Error. Both 
Exception and Error derive from Throwable.


nothrow only means the function will not throw an *Exception*.

Error can be thrown any time, from anywhere. They bypass the 
nothrow, bypass destructor cleanup, and fly past catch 
(Exception).


An Error is basically: A critical Error has occurred. Salvage 
what you can before dying.


Re: why can't I call const methods on shared objects?

2014-05-11 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 9 May 2014 at 21:58:41 UTC, Steven Schveighoffer wrote:
On Fri, 09 May 2014 17:45:37 -0400, Vlad Levenfeld 
vlevenf...@gmail.com wrote:


Is there any way to declare a method as safe regardless of 
shared/mutability/etc (or some other way to avoid 
cast(Type)object.property every time I want to check a 
property which won't affect any state)?


Not really for shared. For everything else, there's const for 
value properties, and inout for reference properties.


Shared is quite different, because the method has to be 
cognizant of race conditions. It has to be implemented 
differently.


Casting away shared is somewhat dangerous, but OK if you 
logically know there is no race condition.


-Steve


You could just declare the function as immutable.

But then, it'll only work on immutable types.

But then again, that would be the only way to actually statically 
and safely guarantee there are no race conditions.


Re: Why std.algorithm.sort can't be applied to char[]?

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn
On Monday, 12 May 2014 at 18:44:22 UTC, Jonathan M Davis via 
Digitalmars-d-learn wrote:
Sure, you can cast char[] to ubyte[] and sort that if you know 
that the array
only holds pure ASCII. In fact, you can use 
std.string.representation to do it

- e.g.

auto ascii = str.representation;

and if str were mutable, then you could sort it. But that will 
only work if
the string only contains ASCII characters. Regardless, he 
wanted to know why
he couldn't sort char[], and I explained why - all strings are 
treated as
ranges of dchar, making it so that if their element type is 
char or wchar, so

they're not random access and thus can't be sorted.


Arguably, a smart enough implementation should know how to sort a 
char[], while still preserving codepoint integrity.


As a matter of fact, the built in sort property does it.

void main()
{
char[] s = éöeèûà.dup;
s.sort;
writeln(s);
}
//prints:
eàèéöû


Re: Array!T and find are slow

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 14 May 2014 at 14:54:57 UTC, David Nadlinger wrote:

On Wednesday, 14 May 2014 at 14:24:28 UTC, Damian Day wrote:
I've written some search functions, which are many times 
faster, is it

worth making a pull request?


Generally, we strive to make the algorithms in Phobos as fast 
as possible even in the general case. I didn't look at the 
issue at hand in any detail, but if the -O -release -inline 
performance when operating on Arrays is considerably worse than 
when directly operating on the data, we have a problem, as it 
likely to also impact other ranges.


In short, I don't think the best solution is to add this 
special case to Array!T, but rather to figure out what exactly 
is wrong with Array!T and/or find() and fix the problem at its 
source. Could you post a short benchmark snippet explicitly 
showing the problem?


Best,
David


One of the issue is the cost of repeatedly indexing Array, when 
internally it is nothing more than an array. Adding a special 
case in Array.Range allows bypassing the repeated indexing 
costs, but at the very least, should be implemented in terms of 
find itself, eg:


Range searchForward(E)(E needle)
if (isImplicitlyConvertible!(E, T))
{
assert(_outer._data.refCountedStore.isInitialized);

auto haystack = _outer._data._payload[_a .. _b];
haystack = haystack.find(needle);
return Range(this._outer, _b - haystack.length, _b);
}


Re: Array!T and find are slow

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 14 May 2014 at 15:42:13 UTC, Damian Day wrote:
On Wednesday, 14 May 2014 at 14:54:57 UTC, David Nadlinger 
wrote:


Could you post a short benchmark snippet explicitly showing 
the problem?


Benchmark found here:
http://dpaste.dzfl.pl/0058fc8341830


FYI, that implementation is wrong: Array.Range keeps `_a` and 
`_b`, which represents the internal bounds of the payload 
proper (and not low and length). You want something along the 
lines of:


Range searchForward(E)(E needle)
if (isImplicitlyConvertible!(E, T))
{
   assert(_data.refCountedStore.isInitialized);

auto haystack = _data._payload[_a .. _b];
immutable len = _b - _a;

   for (size_t index = 0; index  len; ++index)
   {
  if (haystack[index] is needle)
return Range(this, _b - len, _b);
   }

   return Range(this, _b, _b);
}

But even then, as I suggested above, while I think having 
searchForward could improve the situation, implementing it in 
terms of find would be better: This way, you'd still benefit 
from some of the highly optimized cases in find.


Re: Array!T and find are slow

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 14 May 2014 at 14:24:28 UTC, Damian Day wrote:

I've found bench-marking my program that std.algorithm.find is
very slow on Array!T, due to the fact it iterates on a range
instead of a plain array.

I've written some search functions, which are many times 
faster, is it

worth making a pull request?

http://dpaste.dzfl.pl/63b54aa27f35#


BTW, this is a more general issue: Given a generic algorithm 
std.foo, how can I write my own (better optimized) 
object.foo, and make sure *that* is called instead?


I initially filed the issue for retro, while indeed mentioning 
that find was also open to the improvement:

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

This spawned the thread:
http://forum.dlang.org/thread/op.xeuot6g2eav7ka@stevens-macbook-pro-2.local

Unfortunately, nothing came of it.


Re: Array!T and find are slow

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 14 May 2014 at 20:29:52 UTC, David Nadlinger wrote:

On Wednesday, 14 May 2014 at 17:36:35 UTC, monarch_dodra wrote:
Adding a special case in Array.Range allows bypassing the 
repeated indexing costs, but at the very least, should be 
implemented in terms of find itself, eg:


Shouldn't the extra indirection just vanish into thin air once 
opIndex or what have you is inlined? I don't see a conceptual 
reason for overhead in this case.


Maybe. That said, currently, find doesn't use indexing for RA 
ranges. It simply uses a front/popFront for loop, so *that's* 
extra work.


I just tried a RA/hasLength/hasSlicing case in find. It improves 
the situation by a factor of 2 on my machine (with dmd), but it 
is still somewhat slower than extracting the array directly.


I'm usually reluctant to add extra code when the generic case 
works, but I feel we should make an exception for find.


I don't know if the optimizer can optimize away the indirection 
entirely, when the code for front also does indexing, with bounds 
checking...


Array comes with deterministic memory management, as well as 
non-invalidating range when relocation occurs. Extra overhead is 
to be expected.


Of course, the compiler probably wouldn't be able to infer any 
of the memchr/… optimizations find does for the array case, but 
Damian's alternative version doesn't do any of that either.


David


The memchr optimization would only trigger for ubyte/byte and 
char (although a bug prevents Array from working with char 
https://issues.dlang.org/show_bug.cgi?id=8824)


But more importantly, there are more flavors of find, such as 
with predicate, or range/range find. Having an implementation 
provide a thin wrapper might be acceptable. Reimplementation 
isn't.


Re: Array!T and find are slow

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 14 May 2014 at 21:20:06 UTC, Kapps wrote:

That pull shows that the previous behaviour was to use enforce?
Isn't this very expensive, particularly considering that enforce
uses lazy non-scope arguments?


Yes.


Re: Array!T and find are slow

2014-05-14 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 15 May 2014 at 04:37:16 UTC, Jonathan M Davis via 
Digitalmars-d-learn wrote:

enforce(cond, failure);

really should just translate to something close to

if(!cond) throw new Exception(failure);

but it doesn't do anything close to that. And as long as it 
doesn't, enforce
is of questionable value in any code that cares about 
efficiency.


- Jonathan M Davis


As a workaround, I'm sure we could specialize enforce without 
lazy for built-in types?


BTW: Why *is* enforce lazy again? I don't really see it. I makes 
more sense for things like collectException I guess, but I 
don't see it for enforce.


Re: Array!T and find are slow

2014-05-15 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 15 May 2014 at 06:52:44 UTC, Jonathan M Davis via 
Digitalmars-d-learn wrote:

On Thu, 15 May 2014 05:53:45 +
monarch_dodra via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:


As a workaround, I'm sure we could specialize enforce without
lazy for built-in types?


No. I don't think that that would work. The problem is that 
you'd have to be

able to overload between stuff like error message and
format(error message: %s, foo), because you don't want the 
first one to be

lazy, whereas you do want the second one to be lazy.


Oh... right. It's the *second* parameter that's lazy.

Arguably, the compiler should be able too see if the argument 
passed is a value or an expression though, and optimize 
accordingly.


Re: Why std.algorithm.sort can't be applied to char[]?

2014-05-15 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 14 May 2014 at 09:01:23 UTC, John Colvin wrote:

Why would anyone ever want to sort code-points?


Why not? To remove duplicate characters?

They might want to sort graphemes, but that's difficult to do 
in-place (needs O(n) memory, I think...). If out-of-place is 
good enough


someStr.byGrapheme.array.sort();


The current status quo in D is that a dchar basically
represents a character.


Re: Why std.algorithm.sort can't be applied to char[]?

2014-05-15 Thread monarch_dodra via Digitalmars-d-learn

On Thursday, 15 May 2014 at 13:26:45 UTC, Steven Schveighoffer
wrote:
On Wed, 14 May 2014 05:13:42 -0400, Jonathan M Davis via 
Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote:



On Wed, 14 May 2014 08:27:45 +
monarch_dodra via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

As a matter of fact, the built in sort property does it.

void main()
{
char[] s = éöeèûà.dup;
s.sort;
writeln(s);
}
//prints:
eàèéöû


I'm surprised. I thought that one of Bearophile's favorite 
complaints was that
it didn't sort unicode properly (and hence one of the reasons 
that it should

be removed). Regardless, I do think that it should be removed.


I can't believe this worked. I want to say that it's a freak 
accident for that set of characters. Looking in druntime, I 
don't see where the special case is.


-Steve


Must be a hell of a freak accident ;)

 auto s = é東öe京ûタèワà.dup;
 writeln(s.sort);

= eàèéöûタワ京東

It's in rt/adi.d

extern (C) char[] _adSortChar(char[] a)

It's basically: string=dstring=sort=dstring=string.



BTW, the built in reverse also works with char[], and so does 
std.algorithm.reverse (and it does it pretty cleverly too, might 
I say).


As far as I'm concerned, if we *can* do it in n.log(n), and 
somebody provides the implementation, then there is no reason to 
not offer dchar sorting for char[]/wchar.


Re: [Rosettacode] Growable slices

2014-05-15 Thread monarch_dodra via Digitalmars-d-learn

On Thursday, 15 May 2014 at 09:00:13 UTC, bearophile wrote:
This task asks for an basic implementation of the the 
Lempel-Ziv-Welch (LZW) compression/decompression algorithm. I 
am keeping two D versions, the first one is minimal, and the 
second is a little more optimized:

http://rosettacode.org/wiki/LZW_compression#More_Refined_Version

There are of course ways to implement a really efficient ZLW 
compressor in D, and such implementation could be added as 
third D entry if it manages to be not too much long, but for 
the first two versions keeping the code very short is more 
important.


Despite the compressor in the second D entry is still not 
efficient at all, I have tried to make it not terrible 
regarding its efficiency, so I have defined a new kind of slice 
that can be extended, unlike the D slices, to avoid the string 
appends visible in the first D entry:



struct Slice {
size_t start, end;
@property opSlice() const pure nothrow @safe @nogc {
return original[start .. end];
}
alias opSlice this;
}

Slice w;
Tcomp[] result;
foreach (immutable i; 0 .. original.length) {
auto wc = Slice(w.start, w.end + 1); // Extend slice.
if (wc in dict) {
w = wc;
} else {
result ~= dict[w];
assert(dict.length  Tcomp.max); // Overflow guard.
dict[wc] = cast(Tcomp)dict.length;
w = Slice(i, i + 1);
}
}


Is this showing a limit (problem) of D slices, or is this 
design better written in other ways?


Bye,
bearophile


I don't think it shows a limit of slices in and out of itself, 
but rather the whole range concept, that conveniently 
encapsulates a start/end iteration scheme.


The problem though is that, unlike iterators, these can only 
shrink, and never grow. Furthermore, it is usally hard to split 
a range into two parts, given a center iterator (especially for 
bidirectional-only ranges: EG: linked list).


I think ranges/slices still provide more functionality and are 
worth it, but they do sacrifice *some* power: Growth and 
splitting.


To be honest, what you are doing is essentially working with 
iterator pairs, disguised as indexes inside a Slice struct. Not 
that there's anything wrong with that, but that's my impression 
when looking at the code.


Related:
http://forum.dlang.org/thread/bhssgxfcscfbionhq...@forum.dlang.org#post-umxlhsfqmfjwydemfdeb:40forum.dlang.org
http://forum.dlang.org/thread/gpsiwnslxtsyfolym...@forum.dlang.org#post-mailman.2149.1353648522.5162.digitalmars-d:40puremagic.com


Re: Why std.algorithm.sort can't be applied to char[]?

2014-05-15 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 15 May 2014 at 17:46:52 UTC, Steven Schveighoffer 
wrote:
As far as I'm concerned, if we *can* do it in n.log(n), and 
somebody provides the implementation, then there is no reason 
to not offer dchar sorting for char[]/wchar.


I think there is nothing wrong with requiring the steps to be 
explicit. We should not hide such bloat behind sort.


-Steve


Of course, but I meant if we could find an algoirthm O(1) (or 
O(log(N)) space overhead.


If the only algorithm we are capable of providing just 
temporarily dstrings, then no.


Re: [Rosettacode] Growable slices

2014-05-16 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 16 May 2014 at 15:20:04 UTC, bearophile wrote:

Artur Skawina:


Ugh. So how does it perform wrt the D version that I wrote for
you last time? [1]


I have done a benchmark with the various version (the first 3 
are the ones on the Rosettacode site, and the #4 is yours):


lzw1: 0.39
lzw2: 0.17
lzw3: 0.21
lzw4: 0.17

I think your comment was about an older version of the first 
entry, that is non meant to be fast, just short and simple.


I think the second version is enough. Do you agree?

The third version should be more efficient but for such small 
files it's slower than the second.


Bye,
bearophile


Arguably, your code allocates a lot.

To speed it up, arguably, you could store a global immutable 
string containing characters 0 to char.max + 1.


This way, when you build your dictionary (each time you enter 
compress), you at least don't have to allocate the string, but 
rather, slice your global immutable. Ditto for the lines w = 
[ch];, which allocates, you could instead do w = gAllChars[ch 
.. ch + 1]. (or dict[b] = [b] etc...)


Well, just a quick idea...

I'll give it a shot (next week).


Re: [Rosettacode] Growable slices

2014-05-16 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 16 May 2014 at 15:49:10 UTC, bearophile wrote:

monarch_dodra:


Arguably, your code allocates a lot.


What version (1-2-3) do you mean?


Any of the versions where you can see [c] or [b] where c/b is 
a char/byte


Re: Is it possible to assumeSafeAppend malloced memory?

2014-05-19 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 19 May 2014 at 06:08:18 UTC, Ali Çehreli wrote:
We know that most of the time memory is allocated more than the 
requested amount. Is there a way to take advantage of that 
extra trailing space? (And potentially the pages that come 
after that.)


import core.memory;

void main()
{
const count = 1;

// I think there is extra capacity beyond the 'count' 
elements

int* ptr = cast(int*)GC.malloc(count * int.sizeof);
int[] arr = ptr[0 .. count];

assert(arr.capacity == 0);
arr.assumeSafeAppend;
assert(arr.capacity == 0);// still 0. :(
}

This issue puts std.array.array to a disadvantage compared to 
proper slices because array() involves the following call 
chain, the last of which does call GC.malloc:


  trustedAllocateArray
  uninitializedArray
  arrayAllocImpl

As a result, iota(10).array.assumeSafeAppend ends up having 0 
capacity. :(


Ali


Recently, a new function in druntime was added: _d_newarrayU.

This void allocates a new array *with* appendable information. We 
can hope it will be given a more formal and public interface, and 
it would then be useable by array and/or Appender, to produce 
slices that have appendable data.


Re: Is it possible to assumeSafeAppend malloced memory?

2014-05-19 Thread monarch_dodra via Digitalmars-d-learn
On Monday, 19 May 2014 at 13:55:00 UTC, Steven Schveighoffer 
wrote:

On Monday, 19 May 2014 at 06:08:18 UTC, Ali Çehreli wrote:


This issue puts std.array.array to a disadvantage compared to 
proper slices because array() involves the following call 
chain, the last of which does call GC.malloc:


 trustedAllocateArray
 uninitializedArray
 arrayAllocImpl


This is a bug. arrayAllocImpl should alloc using the proper 
functions and flags.


Well, Yes and no. The issue is that there is no interface 
available to achieve this, that wouldn't completely destroy what 
`array` is going for anyways. So it's more of a design issue than 
a bug proper.


https://issues.dlang.org/show_bug.cgi?id=12444
https://github.com/D-Programming-Language/phobos/pull/2044

The only way I'd know (currently) to make it work, is with 
reserve+assumeSafeAppend. But the issue with that approach is 
that it's not pure (because of the whole purity with global GC 
side effects deal).


Re: Is it possible to assumeSafeAppend malloced memory?

2014-05-19 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 19 May 2014 at 18:51:31 UTC, Dicebot wrote:
If it still resorts to GC in this case, utility of such 
addition sounds questionable.


It's not really an addition as much as it is a necessary 
building block to make higher order GC functions work: For 
example, dup was recently made a druntime library implemented 
function, and as such, required that function to allocate, before 
building data onto it.


Huh, will it also make possible to call `realloc` if capacity 
is exceeded?


AFAIK, using the GC.realloc (or GC.extent) function on it 
directly would not work. This may or may not be an issue with how 
GC.realloc is designed. The reason for this is because this 
functions are actually extremelly low level, and simply request 
GC memory, without knowing or caring about the APPENDABLE data. 
So while the calls could succeed, the result would not be useable.


Currently, you could just use reserve or simply allocate again, 
to achieve almost the desired result. reserve+assumeSafeAppend 
would basically be a void-extend (as opposed to size, which 
would be an initialized extend).


At the end of the day though, it can all be done, but it's really 
about what you want to expose in object.d.


Re: Question about @nogc

2014-05-20 Thread monarch_dodra via Digitalmars-d-learn
On Tuesday, 20 May 2014 at 12:25:11 UTC, Dominikus Dittes Scherkl 
wrote:
Did I understand correct that a function can only be @nogc if 
also all functions that it calls are @nogc too (and of course 
it doesn't use the GC itself)?


If so, should this be possible:

string foo()
{
   // use GC to allocate some string
}

bar @nogc
{
   mixin(foo());
}

Because, bar() didn't really call foo() but instead foo() is 
evaluated during compile time and it's result is now part of 
the code, right?


Right.

It's the same mechanics you'd get from pure/nothrow and 
@safe+@trusted


Re: byCodePoint for a range of chars

2014-05-20 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 20 May 2014 at 17:59:09 UTC, John Colvin wrote:
Given a range with element type char, what's the best way of 
iterating over it by code-point, without filling an array first?


Related to this: What's the status of std.utf and std.encoding? 
The comments in std.encoding say that some functions supersede 
their std.utf counterparts.


FWI, Walter just wrote byDchar, that does what you want:
https://github.com/D-Programming-Language/phobos/pull/2043

It's about to be merged.


Re: byCodePoint for a range of chars

2014-05-20 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 20 May 2014 at 18:06:09 UTC, Justin Whear wrote:
Foreach on narrow strings automatically decodes, so it's as 
simple as:


// assume UTF-8 encoded
char[] myData = ...
foreach (dchar codePoint; myData)
   ...


I think the point of his question is if you have an actual 
non-array range of chars, in which case foreach does NOT decode. 
It simply iterates.


Re: Question about @nogc

2014-05-20 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 20 May 2014 at 21:04:37 UTC, anonymous wrote:
On Tuesday, 20 May 2014 at 20:15:09 UTC, Dominikus Dittes 
Scherkl

wrote:
/// create a fixed size array with the given name and with 
*max* entries


max + 1 entries

/// of immutable values of the same type as the return value 
of the

/// given function.
/// it contains the values of that function in the range 
[0..max].
string makeLookupTable(alias fn, uint max=255)(string name) 
pure @safe if(is(typeof(fn(max

{
  string table = immutable  ~ to!string(typeof(fn(max))) ~ 
[ ~ to!string(max+1) ~ ]  ~ name ~= [ ;

  foreach(i; 0..max) table ~= to!string(fn(i) ~ , ;
  return table ~ to!string(fn(max) ~ ];
}


Couldn't resist purging that of the string fiddling:

 ...

 enum ReturnType!fn[length] lookupTable = [elements];


Depending on what the usecase is, you might want to change that 
to static immutable instead:


static immutable ReturnType!fn[length] lookupTable = [elements];

Remember that when using an enum, the compiler will create a 
*new* variable on every use. While the compiler can sometimes 
avoid actually allocating, it may also insert some object code 
bloat to do so.


Re: How to get struct's members ?

2014-05-23 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 23 May 2014 at 01:17:18 UTC, bioinfornatics wrote:

Dear,

I would like to get struct's members and zip them with an action

as

struct A
{
  int a;
  int b;
}

std.range.zip( __traits( allmembers, A ), [(x) = x == 0, (y) =
y  3] );

like this i could apply an action to each field.

I tried this:
http://dpaste.dzfl.pl/747799ffa64e

but:
  tuple get by allmembers is not an input rage then i can't to 
use

zip
  allmembers return both fiels and method while i would like 
only

fields

thanks


tupleof will do what you need (mostly). However, I don't think 
there will be any way to (generically) run-time zip on the 
members, due to probably type mismatch, and memory layout. In any 
case, nothing trivial, AFAIK.


Re: How to get struct's members ?

2014-05-23 Thread monarch_dodra via Digitalmars-d-learn
On Friday, 23 May 2014 at 08:20:05 UTC, Philippe Sigaud via 
Digitalmars-d-learn wrote:
On Fri, May 23, 2014 at 8:44 AM, monarch_dodra via 
Digitalmars-d-learn

digitalmars-d-learn@puremagic.com wrote:

On Friday, 23 May 2014 at 01:17:18 UTC, bioinfornatics wrote:



I would like to get struct's members and zip them with an 
action


tupleof will do what you need (mostly). However, I don't think 
there will be
any way to (generically) run-time zip on the members, due to 
probably type
mismatch, and memory layout. In any case, nothing trivial, 
AFAIK.


You can define a map-like (or zip-like) template to act on 
tuples as
if they were ranges, but the resulting type will still be a 
tuple: in
general, the members and the delegates associated with them 
will all

have a different type.

Bioinfornatics, if you know your struct members are all of the 
same
type, you can 'cast' the tuple as an array by wrapping it in 
square

brackets like this:

[ myStruct.tupleof ]

and then use the usual range algorithms.


One issue with this is that it will allocate a copy of all the 
elements. This may be fine if the elements are meant for a 
read-only operation. But it won't solve the issue if there are 
any mutating operations.


Just saying.



Re: How to handle try-catch blocks, nothrow and logfiles

2014-05-24 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 24 May 2014 at 17:09:24 UTC, Tim wrote:
Imagine I've an application where I want log all thrown 
exceptions.


Arguably, that's not something you'd want to do. In a normal 
application, exceptions get thrown around, and it is completely 
normal. In particular, the *thrower* has no way to know its 
context, and whether or not the situation it has encountered is 
catastrophic exception or completely normal. Only the 
catcher can know.


   2) When I want create an application where all methods are 
defined as nothrow - how can I realize that? Writing to a 
log-file is already throwable. Yes, I can catch the exception 
and write the same to the command line but that's also 
unsafe... are there any nothrow-function to write a file or 
something to the command line? It's a bit sad when I want log 
an exception and I'm unable to write the log entry because 
something happened. So how can make sure that I log all 
exceptions? Is that even possible?


Well, you seem to be mixing the notion of nothrow and safe, 
which are orthogonal concepts. Most logging frameworks gag 
their exceptions, which makes them nothrow.


This doesn't mean that exceptional things can't happen: It only 
means the exceptions will not escape from the call.


Re: What are the best std algo for testing a range implementation ?

2014-05-27 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 27 May 2014 at 10:50:54 UTC, BicMedium wrote:
Let's say I have a set of containers, using a 
D-unfriendly-semantic. They rather use a kind of ADA vocabulary 
(according to https://en.wikipedia.org/wiki/Deque). I want to 
make them range-aware.


If the input/output ranges are easy to implement(so it's just 
reading/writing an element, keeping an index for the writer and 
another for the reader, and reseting it, isn't it ? So if 
(isInputRange!MyCont  isOutputRange!MyCont) then it's a 
Deque, right ?).
The bidirectionnal ranges or the forward ranges become more 
difficult to interpret with the idioms I 
use(Insert,Add,Remove)...Is this a kind of 3rd plane (time: 
return to previous state, make a backup: copy/roll-back - 
undo/redo ?)


Just keep in mind that a container is not a range. A container is 
an object that can hold items, and you can add and remove items 
from said object. The Range is a way to iterate your container.


For example, a range definitely does NOT make insertion, removals 
or duplactes of your items. You can save a range, but that's 
NOT the same thing as making a duplicate of your container that 
you can roll back.


I'd suggest you take a look at std.container.array to see what 
I'm talking about.


Could you recommend me the algos from std.algo to test 
efficiently my implementations ? (example, if you want to be 
sure that the input ranges work then you'd use this...if you 
want to be sure that output ranges work then you'd use that 
...Some kind of reference unit tests ?). At the present time, 
each time I try one I get rejected by the template 
constraints...


If the algos are turning you down, then you must have missed 
something. Check that:

alias Range = YourRangeTypeHere;
static assert(isInputRange!Range);
static assert(isForwardRange!Range);
static assert(isBidirectionalRange!Range);
static assert(hasLength!Range);
static assert(isRandomAccessRange!Range);
static assert(hasSlicing!Range);

At the *very least*, the first 3 should pass for a deque. The 3 
others depend on what primitives you want to offer.


Re: What are the best std algo for testing a range implementation ?

2014-05-27 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 27 May 2014 at 12:18:15 UTC, BicMedium wrote:

I mean that those tests are just like testing an interface...).


If your interface isn't complete, than it is irrelevant what your 
implementations are, since the algorithms can't use your ranges 
anyways.


BTW the 2nd and the 3rd assertions are exactly what fails when 
I try to test an algo (isInputRange!Range or 
isOutputRange!Range pass but has the test doesn't know about 
the implementation I can't know If it's really working...


Probably you are missing `save`, or you implemented it as a 
non-property function (though arguably, it shouldn't be a 
property, but that's another issue).


Re: What are the best std algo for testing a range implementation ?

2014-05-27 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 27 May 2014 at 16:49:42 UTC, BicMedium wrote:
But there could be a templated-unittest for those kind of 
things...Ranges are relatively straightforward in to use, but 
when you want to implement one, it's another thing...So it's 
just about indexes ? And a kind of State machine for indexes 
(push/pop) ?


We can't wright a generic unittest to make sure that a range 
works. Indeed, depending on *what* your range iterates, the 
test would be different.


You just have to test that yourself.

I hardly get how to make my easy containers range-aware. but I 
want to, because of std.algo.


The easiest way is to give your container the Range opSlice() 
function, where Range is the range you defined to iterate on your 
container. See std.container.array.


Re: Cost of .dup vs. instantiation

2014-05-28 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 28 May 2014 at 14:36:25 UTC, Chris wrote:
I use Appender to fill an array. The Appender is a class 
variable and is not instantiated with each function call to 
save instantiation. However, the return value or the function 
must be dup'ed, like so:


Appender!(MyType[]) append;
public auto doSomething() {
  scope (exit) { // clear append }
  // ... do something
  append ~= item;
  return (append.data).dup
}

My question is whether I save anything with Appender as a class 
variable here. I have to .dup the return value (+ clear the 
Appender). If I had a new Appender with each function call, it 
might be just as good.


public auto doSomething() {
  Appender!(MyType[]) append;
  // 
  return append.data.
}

Right or wrong?


You might save a little because you avoid the cost of growing 
your appender repeatedly: Once the appender has come to 
maturity, it will very likely stop growing.


At that point, you only pay for *1* allocation per call to 
doSomething. Further advantages include:

 - dup has APPENDABLE info (whereas appender.data does not).
 - less wasted memory: dup uses no more memory than it has to, 
whereas Appender may over-allocate, depending on how you fill it.


The downside to your approach is that you keep a handle on a 
buffer that can grow, but never shrink. If a at a certain point, 
you have to process some particularly large input, then you'll 
consume excessive amounts of memory.


Re: std.algorithm range violation

2014-05-28 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 28 May 2014 at 11:40:05 UTC, Wanderer wrote:

Sorry about typo, I meant

providor_symbol_map.sort!((x,y)={x.value.lengthy.value.length})

above.


providor_symbol_map is an Associative Array, so you can't sort 
that. *Usually*, you want to do what the OP did, which is to get 
the keys, and sort them, but leave the AA unchanged. EG:


Val[Key] myAA;
Key[] mySortedKeys = myAA.keys.sort!((x, y)= compare(myAA[x], 
myAA[y]))()


//Print values in incremented order:
foreach(key; mySortedKeys)
writefln(%s: %s, key, myAA[key]);


Re: std.algorithm range violation

2014-05-28 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 28 May 2014 at 17:39:15 UTC, monarch_dodra wrote:

On Wednesday, 28 May 2014 at 11:40:05 UTC, Wanderer wrote:

Sorry about typo, I meant

providor_symbol_map.sort!((x,y)={x.value.lengthy.value.length})

above.


providor_symbol_map is an Associative Array, so you can't sort 
that. *Usually*, you want to do what the OP did, which is to 
get the keys, and sort them, but leave the AA unchanged. EG:


Val[Key] myAA;
Key[] mySortedKeys = myAA.keys.sort!((x, y)= compare(myAA[x], 
myAA[y]))()


//Print values in incremented order:
foreach(key; mySortedKeys)
writefln(%s: %s, key, myAA[key]);


I case this was not clear compare is an function you should 
replace with your own. It should simply define strict ordering of 
x and y.  is one such function.


Re: @safe @nogc memory allocation

2014-05-28 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 28 May 2014 at 19:43:53 UTC, Nordlöw wrote:

I would like my radix sort function radixSortImpl() at

https://github.com/nordlow/justd/blob/master/intsort.d

to not use the GC. However, when I tag with @nogc I get the 
error:


intsort.d(195,47): Error: @nogc function 
'isort.radixSortImpl!(byte[], a, false).radixSortImpl' cannot 
call non-@nogc function 'std.array.uninitializedArray!(byte[], 
immutable(ulong)).uninitializedArray'


Is there an alternative to

std.array: uninitializedArray
Elem[] y = uninitializedArray!(Elem[])(n);

that neither use the GC and nor preinitialize the data?


malloc? There's no wrapper around it though, like there is for 
uninitializedArray.


Keep in mind though that currently, you have to choose either of 
pure (GC) or nogc (malloc) if you need dynamic allocation :/



Could the recent DMD pull optimization to scope here

https://github.com/D-Programming-Language/dmd/commit/abc7033bf9cf7f7224a47e45096efc48a21b5ab8

be used?

/Per


I don't think scope can be used to create a dynamic array on the 
stack. I think it requires the object's type be statically known. 
I could be wrong though.


If you know n has a max size, you could you create a fixed size 
array, or attempt a alloca array?


Re: @safe @nogc memory allocation

2014-05-28 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 28 May 2014 at 20:00:17 UTC, safety0ff wrote:
I think malloc isn't @safe and alloca doesn't work if your 
function can throw.


Yeah, uninitializedArray is also *only* trusted if the type in 
question has no indirections.


I've heard of several bugs with alloca, but I don't know the 
exact list.


Re: Cost of .dup vs. instantiation

2014-05-29 Thread monarch_dodra via Digitalmars-d-learn

On Thursday, 29 May 2014 at 08:49:10 UTC, Chris wrote:

monarch_dodra:
Hm. This last point might be an issue. If I process a large 
input (text in this case) then I might run into trouble with 
append as a class variable. I also had a weird bug, because I 
didn't clear the memory for overwrite.


You can always implement an upper bound approach, where if your 
input data becomes larger than a certain size, you return the 
data directly, and reset your appender. EG:


Appender!(MyType[]) append;
public auto doSomething() {
  scope (failure) { append.clear; }
  // ... do something
  append ~= item;
  MyType[] ret;
  if (append.data.length  10_000)
  {
ret = append.data).dup;
append.clear; //clears buffer, keeps memory.
  }
  else
  {
ret = append.data;
append = appender!(MyType[])(); //jettison old appender data.
  }
  return ret;
}


Re: enums

2014-05-30 Thread monarch_dodra via Digitalmars-d-learn
On Friday, 30 May 2014 at 15:30:15 UTC, Russel Winder via 
Digitalmars-d-learn wrote:

I think I have no idea what D enums are about.

Bearophile's example of some code in an email on another thread 
uses:


enum double p0 = 0.0045;

Now I would have written:

immutable double p0 = 0.0045;

or at the very worst:

const double p0 = 0.0045;

For me, enum means create an enumerated type. Thus enum 
double to

define a single value is just a contradiction.

Enlightenment required…


The keyword enum stems from the enum hack in C++, where you use:
enum {foo = 100}; //Or similar

As a way to declare a manifest constant known at compile time.

D simply hijacked the enum keyword to mean manifest constant 
that is known at compile time.


Compared to an immutable instance:
* The immutable instance creates an actual reference-able object 
in your binary. The enum will not exist outside of the 
compilation (think of it as a higher order macro)
* immutable represents a value, which *may* be initialized at 
runtime. In any case, more often than not (I have observed), the 
compiler will refuse to use the immutable's value as compile-time 
known, and it won't be useable as a template parameter, or static 
if constraint.


Re: Different random shuffles generated when compiled with gdc than with dmd

2014-05-30 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 30 May 2014 at 13:39:18 UTC, Andrew Brown wrote:

Hi there,

The following code:

void main(){
   import std.array : array;
   import std.stdio : writeln;
   import std.random : rndGen, randomShuffle;
   import std.range : iota;

   rndGen.seed(12);
   int[] temp = iota(10).array;
   randomShuffle(temp);
   writeln(temp);
}

writes [1, 8, 4, 2, 0, 7, 5, 6, 9, 3] if it's compiled with dmd,
but [1, 7, 4, 6, 2, 9, 5, 0, 3, 8] with gdc.

...

Andrew


Are you sure you are compiling with the same version of dmd and 
gdc? Fixes were made to the rand.d library in the latest release, 
which could explain the difference you are observing.


Re: Different random shuffles generated when compiled with gdc than with dmd

2014-05-30 Thread monarch_dodra via Digitalmars-d-learn
On Friday, 30 May 2014 at 18:41:55 UTC, Joseph Rushton Wakeling 
via Digitalmars-d-learn wrote:

On 30/05/14 18:13, monarch_dodra via Digitalmars-d-learn wrote:
Are you sure you are compiling with the same version of dmd 
and gdc? Fixes were
made to the rand.d library in the latest release, which could 
explain the

difference you are observing.


Which fixes are you thinking of here ... ?  I don't recall 
anything that ought to alter the behaviour of the standard 
random number generator.


Didn't you make changes to how and when the global PRNG is popped 
and accessed in randomShuffle? I figured it *could* be an 
explanation.


Re: enums

2014-05-31 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 31 May 2014 at 21:21:59 UTC, Paul D Anderson wrote:
'enum' as a manifest constant keyword has been an unpopular 
decision from its introduction. Everybody agrees that it 
should be changed. Everybody but Walter


I find enum makes sense.


Re: How to sort a 2D array by column

2014-06-07 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 7 June 2014 at 20:47:31 UTC, katuday wrote:

On Saturday, 7 June 2014 at 19:18:34 UTC, Chris Cain wrote:

On Saturday, 7 June 2014 at 19:14:01 UTC, Chris Cain wrote:
This is my attemot to create a compare object. But I don't 
know how to use it together with .sort member function



Don't use the .sort property. Use std.algorithm.sort, which 
has a less predicate (that should return a bool).


http://dlang.org/phobos/std_algorithm.html#sort


Also note that the examples use a string to define the 
predicate, but it accepts functions as well. Such as:


   bool myCompareFunc(AType lhs, AType rhs)
   {
   return lhs.blah  rhs.blah;
   }

   //...
   AType[] arr;
   //...
   arr.sort!myCompareFunc();


I need an example if you don't mind. My sort function requires 
columns numbers supplied at run-time


This is how I defined my sort function
bool compareRow(int[] columns, ref const Row lhs, ref const Row 
rhs)

{
  bool ret = false;
  for (auto i = 0; i  columns.length; ++i)
  {
const auto currentColumn = columns[i];
  if (lhs[currentColumn]  rhs[currentColumn] )
ret = true;
  if (rhs[currentColumn]  lhs[currentColumn] )
ret = false;
   }
   return ret;
}


That function don't make no sense (to me): It'll just return the 
result of the last iteration.


It *looks* like you are trying to do a lexicographical 
comparison? You should just replace those ret = XXX with 
straight up return XXX. The last return ret should be return 
false (I think)



Calling sort like this does not compile

sort!(compareRow)(sort_key,the_table);


You need to create a delegate that binds your sort key to have 
predicate that accepts exactly 2 arguments. A lambda will fill 
that role.


sort!((lhs, rhs)=compareRow(sort_key, a, b))(the_table);
or (not tested) use std.functional's curry:
sort!(curry!(compareRow, sort_key))(the_table);


Re: Conversion string-int

2014-06-07 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 7 June 2014 at 20:53:03 UTC, Paul wrote:

I can not understand, why this code works:

char s[2] = ['0', 'A'];
string ss = to!string(s);
writeln(parse!uint(ss, 16));

but this can deduces template:

char s[2] = ['0', 'A'];
writeln(parse!uint(to!string(s), 16));

What's the reason? And what is the right way to parse 
char[2]-int with radix?


parse takes an lvalue to a range. char[2] is a static array, and 
is not a range. You need to store an actual char[] (or string) 
in a variable to call parse. So ss will work, to!string(s) 
will not.


Re: array as parameter

2014-06-07 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 7 June 2014 at 20:56:14 UTC, Paul wrote:
Dynamic array is really reference. Right? But why modification 
of parameter in this case does not work:


void some_func(string[] s) {
 s ~= xxx; s ~= yyy;
}

but this works:

void some_fun(ref string[] s) {
 s ~= xxx; s ~= yyy;
}

In the 1st case s is reference too, is not it?


It's a value type that holds a reference to data. If you modify 
the *actual* slice, rather than the referenced items, then you 
need to pass by ref.


Re: Permutation Sort Algorithm Very Slow

2014-06-08 Thread monarch_dodra via Digitalmars-d-learn

On Saturday, 7 June 2014 at 22:01:25 UTC, Ali GOREN wrote:

Thank you. I can not resolve it in quicker time, right?


Depends what exactly you want to achieve. This will achieve the 
same result in a fraction of the time.


void main() {
auto data = [2, 7, 4, 3, 5, 1, 0, 9, 8, 6, -1];
sort(data);
data.writeln;
}

But it's not permutation sort. Honestly, I've never *heard* of 
permutation sort. In any case, it's one of the worst sorts I've 
ever heard of.


If you want to use a bad algorithm, you could also go for 
bogosort:


void main() {
auto data = [2, 7, 4, 3, 5, 1, 0, 9, 8, 6, -1];
while (!isSorted(data))
randomShuffle(data);
data.writeln;
}


Re: Interesting bug with std.random.uniform and dchar

2014-06-08 Thread monarch_dodra via Digitalmars-d-learn
On Sunday, 8 June 2014 at 08:54:30 UTC, Joseph Rushton Wakeling 
via Digitalmars-d-learn wrote:
I think it should suffice to forbid uniform!T from accepting 
dchar parameters and to tweak the integral-type uniform()'s 
internal check to avoid calling that specialization with dchar.


Thoughts ... ?

Thanks  best wishes,

-- Joe


Why would we ban uniform!T from accepting dchar? I see no reason 
for that.


Let's just fix the bug by tweaking the internal check.


Re: Interesting bug with std.random.uniform and dchar

2014-06-08 Thread monarch_dodra via Digitalmars-d-learn
On Sunday, 8 June 2014 at 13:55:48 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
On Sun, Jun 08, 2014 at 11:17:41AM +0200, Joseph Rushton 
Wakeling via Digitalmars-d-learn wrote:

On 08/06/14 11:02, monarch_dodra via Digitalmars-d-learn wrote:
Why would we ban uniform!T from accepting dchar? I see no 
reason for that.


Let's just fix the bug by tweaking the internal check.

Yea, I came to the same conclusion while working on it. :-)

The solution I have is (i) in uniform![] check that 
!is(ResultType

== dchar) before checking the condition for calling
uniform!ResultType, and (ii) inside uniform!T, place

static if (is(T == dchar))
{
return uniform![](T.min, T.max, rng);
}


Doesn't wchar need to have a similar specialization too? Aren't 
some

values of wchar invalid as well?


T


Arguably, the issue is the difference between invalid and 
downright illegal values. The thing about dchar is that while 
it *can* have values higher than dchar max, it's (AFAIK) illegal 
to have them, and the compiler (if it can) will flag you for it:


dchar c1 = 0x_D800; //Invalid, but fine.
dchar c2 = 0x_; //Illegal, nope.


Re: scope exit in mixin template

2014-06-08 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 8 June 2014 at 18:28:25 UTC, Byron wrote:


Can we not use scope(..) in a mixin template?

struct bar {}
bar* c_make() { return new bar(); }
void c_free(bar* b) { b = null; }

mixin template Foo() {
  auto b = c_make;
  scope(exit) if(b) c_free(b);
}

void main() {
  mixin Foo;
}

I get Error: Declaration expected, not '('

-Byron


Mixin templates can only insert declarations, not arbitrary code. 
When it sees scope, it's expecting it to be the attribute, not 
the declaration.


Re: scope exit in mixin template

2014-06-08 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 8 June 2014 at 18:48:03 UTC, monarch_dodra wrote:
Mixin templates can only insert declarations, not arbitrary 
code. When it sees scope, it's expecting it to be the 
attribute, not the declaration.


To add to that, if you want to mixin arbitrary code, then you can 
use a string mixin:


template declare_bar(string var_name) {
  enum declare_bar =
auto  ~ var_name ~  = c_make(); ~
scope(exit) if( ~ var_name ~ ) c_free( ~ var_name ~ );
}

void main() {
mixin(declar_var!b)
}

For example.

That said, given your example, simply using an RAII wrapper 
*could* be superior (depends on your actual usecase).


Re: scope exit in mixin template

2014-06-08 Thread monarch_dodra via Digitalmars-d-learn

On Sunday, 8 June 2014 at 18:28:25 UTC, Byron wrote:

void c_free(bar* b) { b = null; }


Heads up: This code does nothing. You are passing the pointer by 
value, so b = null; will have no effect at the end of the call. 
Use pass by ref:


void c_free(ref bar* b) { b = null; }


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 10:23:16 UTC, Chris wrote:


Ok, thanks. I'll keep that in mind for the next version.


Seems to me to also work with 2.065 and 2.064.


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 11:04:12 UTC, Chris wrote:

From the library reference:

assert(equal(splitter(hello  world, ' '), [ hello, , 
world ]));


and

If a range with one separator is given, the result is a range 
with two empty elements.


My problem was that if I have input like

auto word = bla-;

it will return parts.data.length == 2, so I would have to check 
parts.data[1] != . This is too awkward. I just want the parts 
of the word, i.e.


length == 2 // grab [0] grab [1]
length == 1 // grab [0] (no second part, as in bla-)
length  2 // do something else


You can just pipe in an extra filter!(a=!a.empty), and it'll 
do what you want:

put(parts, w.splitter('-').filter!(a=!a.empty)());

The rational for this behavior, is that it preserves the total 
amount of information from your input. EG:


assert(equal(myString.spliter(sep).join(sep), myString));

If the empty tokens were all stripped out, that wouldn't work, 
you'd have lost information about how many separators there 
actually were, and where they were.


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 11:40:24 UTC, Chris wrote:

On Monday, 9 June 2014 at 11:16:18 UTC, monarch_dodra wrote:

On Monday, 9 June 2014 at 11:04:12 UTC, Chris wrote:

From the library reference:

assert(equal(splitter(hello  world, ' '), [ hello, , 
world ]));


and

If a range with one separator is given, the result is a 
range with two empty elements.


My problem was that if I have input like

auto word = bla-;

it will return parts.data.length == 2, so I would have to 
check parts.data[1] != . This is too awkward. I just want 
the parts of the word, i.e.


length == 2 // grab [0] grab [1]
length == 1 // grab [0] (no second part, as in bla-)
length  2 // do something else


You can just pipe in an extra filter!(a=!a.empty), and 
it'll do what you want:

put(parts, w.splitter('-').filter!(a=!a.empty)());

The rational for this behavior, is that it preserves the 
total amount of information from your input. EG:


assert(equal(myString.spliter(sep).join(sep), myString));

If the empty tokens were all stripped out, that wouldn't work, 
you'd have lost information about how many separators there 
actually were, and where they were.


I see, I've already popped in a filter. I only wonder how much 
of a performance loss that is. Probably negligible.


Arguably, none, since someone has to do the check anyways. If 
it's not done outside of splitter, it has to be done inside...


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn
On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer 
wrote:
Just looked at std.string for a strip function that allows 
custom character strippage, but apparently not there. The above 
is quite awkward.


-Steve


It's in algorithm, because it's more generic than just strings.


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 15:19:05 UTC, Chris wrote:
On Monday, 9 June 2014 at 14:47:45 UTC, Steven Schveighoffer 
wrote:
On Mon, 09 Jun 2014 10:39:39 -0400, Chris wend...@tcd.ie 
wrote:



Atm, I have

auto parts = appender!(string[]);
w.splitter('-').filter!(a = !a.empty).copy(parts);

Which looks more elegant and gives me what I want. IMO, the 
module that handles the splitting of hyphenated words should 
be able to deal with cases like blah- without the input 
being prepared in a certain way.


It's not mishandled. It's handled exactly as I would have 
expected. If blah- and blah result in the same thing, then 
how do you know the difference?


Stripping any possible leading or trailing hyphens is much 
more efficient than checking every single word to see if it's 
empty.


However, if you have an instance of --, your solution will 
remove the extra empty string, whereas mine does not. Not sure 
if that's important.


-Steve


It is important. blah-- should come out as blah. The logic 
is along the following lines:


if (canFind(w, -)) {
  auto parts = appender!(string[]);
  w.splitter('-').filter!(a = !a.empty).copy(parts);
  if (parts.data.length == 1) {
// false alarm. Trailing hyphen
  }
}

The more common case is that it's not a trailing hyphen. 
std.string.strip() only works for whitespaces. Would be nice to 
have something like that for random characters. strip(s, '-') 
or strip(s, ['-', '+', '@'])


http://dlang.org/phobos/std_algorithm.html#strip

w = w.strip('-');
if (canFind(w, -)) {
   ...


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn
On Monday, 9 June 2014 at 15:54:29 UTC, Steven Schveighoffer 
wrote:
On Mon, 09 Jun 2014 11:49:29 -0400, monarch_dodra 
monarchdo...@gmail.com wrote:


On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer 
wrote:
Just looked at std.string for a strip function that allows 
custom character strippage, but apparently not there. The 
above is quite awkward.


-Steve


It's in algorithm, because it's more generic than just strings.


Ugh.. This makes things difficult. If I want to work with 
strings, I import std.string.


I understand that the algorithm is applicable to all types, but 
this makes for some awkward coding. What if you wanted to use 
both? Surely we can come up with a better solution than this.


-Steve


There's 2 different issues: The first, is that split(string) 
was pre-existing in std.string, and *then* split was introduced 
in algorithm. Where ideally (?) everything would have been placed 
in the same module, we true to avoid moving things around now.


The second thing is that split without any predicate/item can 
only make sense for strings, but not for generic ranges.


For what it's worth, I find it makes sense.


Re: hijacking override from template mixin

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 15:54:21 UTC, Ivan Kazmenko wrote:
I'd expect a multiple overrides of same function error, much 
like if I just paste the mixin code by hand.  Is that a bug or 
working by design?  In the latter case, please explain the 
reasoning.


AFAIK, the rationale is that *should* a colision happen, the 
local symbol shadows the mixed-in symbol. Doing this avoid 
breaking your code just because someone added an extra member in 
their mixin, which happened to conflict with one of yours.


The idea is that you can workaround the issue by naming your 
mixin templates. Then, when you want to access members of the 
mixin template, you *know* it'll always work, regardless of what 
else may have been declared in your class.


That said, for something like virrtual functions, things get a 
bit trickier, since your *aren't* supposed to call them 
explicitly... I don't know if bug, or just surprising behavior.


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn
On Monday, 9 June 2014 at 17:57:24 UTC, Steven Schveighoffer 
wrote:
I think we are confusing things here, I was talking about strip 
:)


strip and split are actually both pretty much in the same boat 
actually in regards to that, so just 's/split/strip/g', and the 
same answer will apply.


split (and splitter) actually have it a bit more complicated, 
because historically, if you imported both string and algorithm, 
then split(myString) will create an ambiguous call. The issue 
is that you can't do selective imports when you already have a 
local object with the same name, so algorithm had:



auto split(String)(String myString) {
   return std.string.split(myString);
}

rather than

public import std.string : split;


I tried to fix the issue by removing split(String) from 
algorithm, but that created some breakage.


So Andrei just came down and put *everything* in algorithm, and 
added an public import std.algorithm : split in std.string.


This works, but it does mean that:
1. string unconditionally pulls algorithm.
2. You can do things like:
   std.string.split([1, 2, 3], 2);

IMO, the strip solution is better :/

If we could split up std.algorithm into individual modules, 
that would probably help.


-Steve


Yes.


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 19:47:29 UTC, Chris wrote:
Uh, I see, I misread the signature of std.string.strip(). So 
that's one option now, to strip all trailing hyphens with 
std.string.strip(). Well, I'll give it a shot tomorrow.


No, you read the documentation of std.*STRING*.strip correctly.

I'm suggesting you use the one from std.*ALGORITHM*.

The signatures are mutually exclusive, so you don't need to 
qualify them.


Re: splitter for strings

2014-06-09 Thread monarch_dodra via Digitalmars-d-learn

On Monday, 9 June 2014 at 19:54:08 UTC, Chris wrote:
I think it makes sense to put any generic range based 
algorithms (split and so forth) into std.algorithm. It's always 
my first port of call, when I have a range. However, that you 
can do


std.string.split([1, 2, 3], 2);

is not exactly a desirable situation.


Right, but split(hello world) *is* string specific. It makes 
sense for strings only. It doens't make sense to write split([1, 
2, 3]), which is why I'm unsatisfied with the current situation.


Re: D aliases vs. C typedefs

2014-06-10 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 10 June 2014 at 20:33:03 UTC, Ali Çehreli wrote:
I think they are actually legal: This is D's support of C-style 
array declaration acting the same in alias declaration:


Ali


C-style array declaration has got to be one of C's *worst* 
abominations. There's no real *technical* rationale for it either.


I am ***INCREDIBLY*** glad D's stance is simply depth first left 
to right. It *supports* C style, but unless you are copy pasting 
some C code, you'd have to be mad in your head to actually ever 
use it.


Honestly, try to declare:
*A two element array of pointers to int
*A pointer to a two element array of ints

Tip: the solutions are in this set:
int *arr1[2];
int (*arr2)[2];
int *(arr3[2]);

Also, the syntax is *so* horrible, the syntax is actually 
deprecated in D. And that's saying a lot, when you know how much 
Walter hates breaking code...


Re: Splitting Ranges using Lambda Predicates

2014-06-10 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 10 June 2014 at 21:11:17 UTC, Nordlöw wrote:

1. someName = SomeName


My example is dumb and incorrect.

I actually want this to do the following

2. _someGreatVariableName = Some Great Varible Name


The current splitter works on the notion of splitter tokens, 
eg, it splits when it find an element or range that corresponds 
to the passed value/pred.


What exactly are you requesting though?
- Split on the edge lowercase to uppercase?
- Split on uppercase but keep the uppercase element?

Either way, your example should look like this:

SomeGreatVariableName = [Some, Great, Variable, Name]

Since you are splitting up your range into subranges.

And also either way, AFAIK, yeah, we don't have any splitter that 
does that. We are also missing the version that takes both a 
range an predicate, which would allow things like:


This Cool thing is COOL!!!.split((a, b)=a == 
b.toLower())(cool)

  =
[This ,  thing is , !!!]

Looks like you'll have to roll your own :/


Re: Splitting Ranges using Lambda Predicates

2014-06-10 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 10 June 2014 at 21:26:50 UTC, monarch_dodr

What exactly are you requesting though?
- Split on the edge lowercase to uppercase?
- Split on uppercase but keep the uppercase element?


Thinking about this more: Do you *actually* have two different 
predicates, or are they mutually exclusive? EG: predicate 
isUpper, and split on a false-true?


Either way, it shouldn't be too hard to implement. Base it off 
splitter!pred, which is actually quite trivial. AFAIK, your 
requirements could even make it simpler, since you don't need to 
skip the splitter element (which, for strings, can actually be 
tricky business...).


You'd just have to use 2 calls to find though, for both your 
predicates or for not predicate then predicate.


Re: Splitting Ranges using Lambda Predicates

2014-06-11 Thread monarch_dodra via Digitalmars-d-learn

On Tuesday, 10 June 2014 at 22:31:37 UTC, Nordlöw wrote:
Either way, it shouldn't be too hard to implement. Base it off 
splitter!pred, which is actually quite trivial. AFAIK, your


What do you mean by basing it off splitter!pred - should I 
start with some existing splitter algorithm in Phobos or start 
from scratch?


Thx.


I meant mostly copy pasting it, and modifying it to your needs. 
For example, I adapted it into this. For simplicity, I stripped 
infinite and forward only range support. The only functions I 
actually modified were findTerminator, to actually find 
according to what I want, and popFront.


//
auto slicer(alias isTerminator, Range)(Range input)
if (((isRandomAccessRange!Range  hasSlicing!Range) || 
isSomeString!Range)

 is(typeof(unaryFun!isTerminator(input.front
{
return SlicerResult!(unaryFun!isTerminator, Range)(input);
}

private struct SlicerResult(alias isTerminator, Range)
{
alias notTerminator = not!isTerminator;

private Range _input;
private size_t _end = 0;

private void findTerminator()
{
auto r = 
_input.save.find!(not!isTerminator).find!isTerminator();

_end = _input.length - r.length;
}

this(Range input)
{
_input = input;

if (!_input.empty)
findTerminator();
else
_end = size_t.max;
}

static if (isInfinite!Range)
enum bool empty = false;  // Propagate infiniteness.
else
@property bool empty()
{
return _end == size_t.max;
}

@property auto front()
{
return _input[0 .. _end];
}

void popFront()
{
_input = _input[_end .. _input.length];
if (_input.empty)
{
_end = size_t.max;
return;
}
findTerminator();
}

@property typeof(this) save()
{
auto ret = this;
ret._input = _input.save;
return ret;
}
}
//

This will split on before the first element where pred is true, 
provided there are previous elements where pred is false:


//
void main()
{
SomeGreatVariableName  .slicer!isUpper.writeln();
someGGGreatVariableName.slicer!isUpper.writeln();
.slicer!isUpper.writeln();
a.slicer!isUpper.writeln();
A.slicer!isUpper.writeln();
}
//
[Some, Great, Variable, Name]
[some, GGGreat, Variable, Name]
[]
[a]
[A]
//

This may or may not be what you wanted, depending on how you want 
to split GGGreat. If you wanted it to simply split *ON* the 
left of every capital letter, then you can modify the the find 
terminator into:



private void findTerminator()
{
auto r = _input.save.dropOne.find!isTerminator;
_end = _input.length - r.length;
}

And you'd get:
[some, G, G, Great, Variable, Name]


***
***
***


In any case, yeah, it shouldn't be too hard to shape it into what 
you want. A more involved solution to this problem could be to 
simply pass a searchFun predicate, in which case you'd be able 
to split not just according to any unitary predicate, but 
according to an entire range search strategy:


//
auto slicer(alias searchFun, Range)(Range input)
if (((isRandomAccessRange!Range  hasSlicing!Range) || 
isSomeString!Range)

 is(typeof(searchFun(input
{
return SlicerResult!(searchFun, Range)(input);
}

private struct SlicerResult(alias searchFun, Range)
{
private Range _input;
private size_t _end = 0;

private void findTerminator()
{
auto r = searchFun(_input.save);
_end = _input.length - r.length;
}

...
//

And then:


SomereatVariableName.slicer!((s)=s.find!isLower.find!isUpper).writeln();
someGGGreatVariableName 
.slicer!((s)=s.dropOne.find!isUpper).writeln();


[Some, reat, Variable, Name]
[some, G, G, Great, Variable, Name]

Just ideas.


Re: Basic dynamic array question. Use of new versus no new.

2014-06-11 Thread monarch_dodra via Digitalmars-d-learn

On Wednesday, 11 June 2014 at 05:46:07 UTC, Ali Çehreli wrote:

On 06/10/2014 08:06 PM, Matt wrote:

 On Wednesday, 11 June 2014 at 02:30:01 UTC, WhatMeWorry wrote:

 int[] array; // initially empty
 array.length = 5; // now has 5 elements

 while in Mr. Alexandrescu's book, it says

 To create a dynamic array, use a new expression (§ 2.3.6.1
on page 51)
 as follows:

 int[] array = new int[20]; // Create an array of 20 integers

 I would have read the second as creating a static array of 20
ints in
 heap memory, then assigning a dynamic array to point to it.

Correct but it is not different from the first one, other than 
doing it in one step.


Wait, what? That's not correct. new int[20] is simply one of 
two syntaxes to allocate an array of 20 ints, the other being 
new int[](20).


It does NOT allocate a static array, and then slice it. Proof is 
that there is APPENDABLE data present, which should not happen if 
you had actually simply allocated a single element of type 
int[20] (APPENDABLE data is only present for array-style 
allocation).


AFAIK, there is no natural way to allocate either a static 
array or a slice itslef, using new syntax. It can be done via the 
wrapper struct hack though:


//
//Used to allocate a slice int[].
//Or a static array int[20] on the heap.
struct NewWrapper(T)
{
T data;
}
void main()
{
int[] arr1 = new int[20];
int[] arr2 = (new NewWrapper!(int[20])).data[];
writeln(arr1.length);   //20, as expected
writeln(arr1.capacity); //31 on my machine
writeln(arr2.length);   //20
writeln(arr2.capacity); //0
}
//

Too bad the ambiguous syntax has us resolve to these tricks. It 
also prevents value constructing an array of elements. A syntax 
where the array sizes came *before* the type could have solved 
these issue:

int size = 20;
new size int[5]([1, 2, 3, 4, 5]);
Allocate 20 (runtime) elements of type int[5], each 
initialized to the value ([1, 2, 3, 4, 5]).


But, well, that ship has set sail long ago :(


Re: Splitting Ranges using Lambda Predicates

2014-06-11 Thread monarch_dodra via Digitalmars-d-learn
On Wednesday, 11 June 2014 at 11:42:42 UTC, Artur Skawina via 
Digitalmars-d-learn wrote:

On 06/11/14 00:31, Nordlöw via Digitalmars-d-learn wrote:
Either way, it shouldn't be too hard to implement. Base it 
off splitter!pred, which is actually quite trivial. AFAIK, 
your


What do you mean by basing it off splitter!pred - should I 
start with some existing splitter algorithm in Phobos or start 
from scratch?


Starting from scratch is actually not a bad idea, at least for 
this kind
of trivial functionality. A working version can be written in 
less time

than copying, analyzing and modifying another implementation...

...

artur


I don't know about starting from scratch entirely. Maybe not 
copy paste, but it always helps to have a reference 
implementation.


For example, you should avoid countUntil and takeExactly when 
dealing with strings, since these are not O(1) operations, and 
don't actually return string slices. EG:

string s = someGGGreatVariableName.slicer().front;
Error: cannot implicitly convert expression 
(slicer(someGGGreatVariableName).front()) of type Result to 
string


That's why the splitter code uses the more verbose r.length - 
r.find!pred.


Re: Splitting Ranges using Lambda Predicates

2014-06-11 Thread monarch_dodra via Digitalmars-d-learn
On Wednesday, 11 June 2014 at 13:44:25 UTC, Artur Skawina via 
Digitalmars-d-learn wrote:

There is a reason why I never use D's std lib.

artur


Well, (IMO) it's a problem with no real solution. But for what 
it's worth, most (if not all) of the algorithms in the standard 
lib know how to handle strings efficiently and correctly (split, 
find, etc...). Things only start getting funny once you start 
mixing indexing and element counts.


Re: Nameless Static Array

2014-06-12 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 12 June 2014 at 15:58:25 UTC, Taylor Hillegeist 
wrote:

So, Lately I have been avoiding the NEW keyword.


Why? Is malloc OK?

I have recently given up static allocation of classes using 
CTFE. I guess they must be const or immutable?


Funny, because you *are* allowed to default initialized a class 
member variable to a static class instance. And basically, it's 
just a thread local global. So you can work around with:


//
class MyClass
{
int i = 5;
}

void main() {
static struct S
{
MyClass g = new MyClass();
}
static S s;
writeln(s.g.i);
}
//

Disclaimer: Not sure if actually legal, or will cease to work in 
a few releases.


So naturally i can do most of what i need to with structs. They 
are statically allocated no NEW necessary. But without the NEW 
strategy. I must allocate static arrays and set them to a 
pointer in my struct. Not too big of deal really.


uint[12] Buffer;
R_R_Buffer RRB=R_R_Buffer(Buffer);

uint[24] OtherBuffer;
R_R_Buffer RRB2 = R_R_Buffer(OtherBuffer);

I feel though i might end up having OtherOtherOtherBuffers, and 
it pollutes my local symbols. I just dont like it.


Is there a way to not give the buffer a name and do lika dis:

R_R_Buffer RRB=R_R_Buffer(uint[12]);
R_R_Buffer RRB2 = R_R_Buffer(uint[24]);

This obviously fails to compile, but i think you get the idea. 
Mostly, I don't care what the static array name is.


If you have a pointer, then at the end of the day *someone* 
*somewhere*, is going to have to declare and hold the buffers. 
That said, you could simply have a *single* static array that 
holds all your data. Furthermore, you could package it into a 
single convenient struct package:


struct Buffer(T, size_t N)
{
T[N] buffer;
size_t used;
T[] getBufferSlice(size_t n) {
assert(used + n = N, You've overused your buffer!);
auto low = used;
used += n;
return buffer[low .. used];
}
ref T[n] getBufferSlice(size_t n)() {
return *cast(T[n]*) getBufferSlice(n).ptr;
}
}

void main()
{
Buffer!(int, 36) myData;
int[] a= myData.getBufferSlice(12);
int[24]* p = myData.getBufferSlice!24();
}

Notice that with this approach, you can extract a dynamic slice 
referencing stack data, if you don't know the size you want. If 
you statically know the size you want, then you can call your 
function template style, and have a more strongly typed return 
value, that can be passed by ref.


Re: Cannot alias null

2014-06-12 Thread monarch_dodra via Digitalmars-d-learn
On Thursday, 12 June 2014 at 20:44:16 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
On Thu, Jun 12, 2014 at 03:26:13PM -0500, Tom Browder via 
Digitalmars-d-learn wrote:

This will not compile:

  alias blah = null;

[...]

'null' is a value, not a type. Try:

alias blah = typeof(null);


T


Yet you can alias variables...

int i;
alias j = i;

So there's something special about null.


Re: Cannot alias null

2014-06-12 Thread monarch_dodra via Digitalmars-d-learn

On Thursday, 12 June 2014 at 21:58:32 UTC, Adam D. Ruppe wrote:

since null is a value maybe you want

enum blah = null;

you may also give it a type after the enum word


I *think* the issue might be that null is an rvalue? Because 
you can alias variable names all you want. I do it all the time 
for templates where I *may* need a temporary.


eg:

void foo(T)(T val)
{
static if (isUnsigned!T)
alias uval = val;
else
auto uval = unsigned(val);
...
}

It's also quite useful with varargs:
alias a0 = args[0];

Also, you can't alias things like int.init either. I'm not sure 
the rvalue thing is the source, because these work:


//struct S
{
static int i;
static int j() @property;
}
alias a = S.i;
alias b = S.j;
//

I'd consider filling a bug report.


Re: Cannot alias null

2014-06-13 Thread monarch_dodra via Digitalmars-d-learn

On Thursday, 12 June 2014 at 22:54:20 UTC, Ali Çehreli wrote:

On 06/12/2014 03:38 PM, monarch_dodra wrote:
 So there's something special about null.

The difference is that null is an expression. It is the same 
limitation as not being able to alias a literal.


alias zero = 0;
alias blah = null;


Oh! Right. That makes sense.

So you should use enum instead:
enum zero = 0;
enum blah = null;

Thanks.


Re: Cannot alias null

2014-06-13 Thread monarch_dodra via Digitalmars-d-learn
On Friday, 13 June 2014 at 15:05:49 UTC, Tom Browder via 
Digitalmars-d-learn wrote:
So I'm not sure how to translate that into D.   I do know my 
first
attempt here doesn't work, even with it being surrounded by 
extern (C)

{}:

$ cat chdr.d
struct t;
struct t* t_ptr = null;


This seems to work fine for me. What's the problem?

Note this isn't *strictly* the same as what you have in C, as 
null is not strongly bindded to a single type. If you want a 
null pointer which is pre-emptivelly strongly, then you can use 
an eponymous template:


enum nullptr(T) = (T*).init;

auto p = nullptr!t;

Throw in an alias, and you got it working exactly like an C:


enum nullptr(T) = (T*).init;
alias t_nullptr = nullptr!t;
struct t* t_ptr = t_nullptr;

That said, I'd advise against this. Just use null and move on. 
It's idiomatic.


Re: User defined forward range - foreach initializes f.r.

2014-06-13 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 13 June 2014 at 18:14:10 UTC, Andre wrote:

Hi,

I have a template class List which should provide generic 
list functionality. In my use case, using a class instead a 
struct

is more comfortable.

Following unittest fails, although the forward range
implements the save method.

unittest
{
auto intList = new List!int(1,2,3);
assert(intList.length == 3);
foreach(item; intList) {}
assert(intList.length == 3);
}

...

I already tried different thinks, like using dup or importing 
std.array.

But nothing helps, the unittest fails.
Why it fails?

Kind regards
André


To add to what H.S. Teoh said, which is good advice, but doesn't 
quite explain why your unittest failed: Foreach takes a copy of 
your range, and then consumes it. This may or may not have an 
effect on the original range. If you plan to use your range again 
after a call, you are supposed to *save* it:


unittest
{
auto intList = new List!int(1,2,3);
assert(intList.length == 3);
foreach(item; intList.save) {} //HERE
assert(intList.length == 3);
}

There.


Re: User defined forward range - foreach initializes f.r.

2014-06-13 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 13 June 2014 at 19:03:12 UTC, Ali Çehreli wrote:
I am making the following comment to have others confirm, as 
well as remind others about a potential problem.


On 06/13/2014 11:14 AM, Andre wrote:

 unittest
 {
  auto intList = new List!int(1,2,3);

[...]

 class List(T)
 {
  private T[] items;

  this(T[] items...)
  {
  this.items = items;
  }

Unrelated to your question, I think that is a bug because you 
are keeping a reference to a temporary array. The compiler will 
generate a temporary array for 1, 2, and 3 and then that array 
will disappear.


Am I remembering correctly?

If so, I would recommend against 'T[] items...' but use an 
explicit slice:


this(T[] items)

The users will slightly be inconvenienced but the program will 
be correct.


Or, you can continue with 'T[] items...' and then have to take 
a copy of the argument:


this.items = items.dup;// copied

That is obviously slower when the user actually passed in a 
slice. That's why I think it is better to take an explicit 
slice as a parameter.


Ali


Yes.

`fun(T)(T[]...)` is just both `fun(T...)(T t)` and `fun(T)(T[] 
t)` both conveniently packaged into one, but with twice the 
pitfalls.


I'd suggest avoiding it altogether. It's a non-feature (IMO).


Re: Why is stdin.byLine.writeln so slow?

2014-06-13 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 13 June 2014 at 20:48:16 UTC, Jyxent wrote:

I've been playing around with D and noticed that:

stdin.byLine.writeln

takes ~20 times as long as:

foreach(line; stdin.byLine) writeln(line);

I asked on IRC and this was suggested:

stdin.byLine(KeepTerminator.yes).copy(stdout.lockingTextWriter)

which is slightly faster than the foreach case.

It was suggested that there is something slow about writeln 
taking the input range, but I'm not sure I see why.  If I 
follow the code correctly, formatRange in std.format will 
eventually be called and iterate over the range.


Because:
stdin.byLine.writeln
and
foreach(line; stdin.byLine) writeln(line);
Don't produce the same output. One prints a range that contains 
strings, whereas the second repeatedly prints strings.


Given this input:
line 1
line2
Yo!

Then stdin.byLine.writeln will produce this string:
[line 1, line\t2, Yo!]

So that's the extra overhead which is slowing you down, because 
*each* character needs to be individually parsed, and potentially 
escaped (eg: \t).


The copy option is the same as the foreach one, since each 
string is individually passed to the writeln, which doesn't parse 
your string. The lockingTextWriter is just sugar to squeeze out 
extra speed.


  1   2   3   >