www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Newbie problem

reply "Roger Stokes" <rs rogerstokes.free-online.co.uk> writes:
I'd be grateful for advice. The problem is that I can't get the 
example
on page 406-7 of the"The D Programming Language " to compile.
I've cut and pasted the text from the website, and corrected the 
typo (undefined tgt, so use stdout instead).  I get this 
diagnostic:

page406x.d(11): Error: cannot implicitly convert expression 
(__r24.front()) of type ubyte[] to immutable(ubyte)[]

from this input:

import std.algorithm, std.concurrency, std.stdio;

void main() {
    enum bufferSize = 1024 * 100;
    auto tid = spawn(&fileWriter);
    // Read loop
    foreach (immutable(ubyte)[] buffer; stdin.byChunk(bufferSize)) 
{
       send(tid, buffer);
    }
}

void fileWriter() {
    // Write loop
    for (;;) {
       auto buffer = receiveOnly!(immutable(ubyte)[])();
       stdout.write(buffer);
    }
}
Jun 19 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 19 June 2013 at 15:25:15 UTC, Roger Stokes wrote:
 page406x.d(11): Error: cannot implicitly convert expression 
 (__r24.front()) of type ubyte[] to immutable(ubyte)[]
    foreach (immutable(ubyte)[] buffer; 
 stdin.byChunk(bufferSize)) {
The problem here is that byChunk returns a mutable buffer, type ubyte[]. If you said "foreach(ubyte[] buffer; stdin.byChunk(bufferSize)) {...}" you should be able to compile it. I think this was changed after the book was written because byChunk now reuses its buffer. Each time through the loop, it overwrites the old data with the next batch, which means the old data cannot be immutable. (The reason for reusing it is to avoid allocating new memory for a fresh buffer every time.) Since you aren't keeping a copy of the buffer, just changing the type should be enough for your program to work. If you needed an immutable copy, if you were going to store it or something, the way you'd do that is to call buffer.idup: foreach(ubyte[] temporaryBuffer; stdin.byChunk(bufferSize) { immutable(ubyte)[] permanentBuffer = temporaryBuffer.idup; // you can now use the permanentBuffer }
Jun 19 2013
parent reply "Roger Stokes" <rs rogerstokes.free-online.co.uk> writes:
Many thanks for swift response. I'm still in difficulty, alas.  
There were two
possibilities suggested: firstly,

 Adam D. Ruppe wrote:
 The problem here is that byChunk returns a mutable buffer, type 
 ubyte[]. If you said "foreach(ubyte[] buffer; 
 stdin.byChunk(bufferSize)) {...}" you should be able to compile 
 it.
I tried this, which I hope is correct: --------------------------- void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (ubyte[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer); } } void fileWriter() { // Write loop for (;;) { auto buffer = receiveOnly!(immutable(ubyte)[])(); stdout.write(buffer); } } ------------------------------------------------------------ and got this compiler diagnostic: c:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(571): Error: static assert "Aliases to mutable thread-local data not allowed." page406x.d(12): instantiated from here: send!(ubyte[]) For the second possibility, ...
 Since you aren't keeping a copy of the buffer, just changing 
 the type should be enough for your program to work.

 If you needed an immutable copy, if you were going to store it 
 or something, the way you'd do that is to call buffer.idup:

 foreach(ubyte[] temporaryBuffer; stdin.byChunk(bufferSize) {
      immutable(ubyte)[] permanentBuffer = temporaryBuffer.idup;
     // you can now use the permanentBuffer
 }
I tried this --------------------------------------------------- import std.algorithm, std.concurrency, std.stdio; void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach(ubyte[] temporaryBuffer; stdin.byChunk(bufferSize)) { immutable(ubyte)[] permanentBuffer = temporaryBuffer.idup; // you can now use the permanentBuffer send(tid, permanentBuffer); } } void fileWriter() { // Write loop for (;;) { auto buffer = receiveOnly!(immutable(ubyte)[])(); stdout.write(buffer); } } -------------------------------- and the result compiled and executed with no error signals, but the resulting output of the file-copy was not the same as the input, it looked like this: std.concurrency.OwnerTerminated std\concurrency.d(248): Owner terminated ---------------- 0x004068EA 0x004081B5 0x00407AB4 0x00407C6A 0x00407CA0 0x00407D1C 0x00407883 0x004068AB 0x004020E9 0x00414D51 0x00434CB4 0x76E51603 in RtlInitializeExceptionChain 0x76E515D6 in RtlInitializeExceptionChain ---------------- [47, 47, 32, 101, 120, 97, .... .... The numbers 47, 47, 32, etc look like the ASCII indexes of the characters which should be in the output, not the characters themselves! Any further help would be much appreciated. Regards, Roger Stokes
Jun 19 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 06/19/2013 12:14 PM, Roger Stokes wrote:

 and the result compiled and executed with no error signals, but the
 resulting output of the file-copy was not the same as the input, it
 looked like this:

 std.concurrency.OwnerTerminated std\concurrency.d(248): Owner terminated
For a clean exit, the owner must tell the worker that there is no more data (see struct Done below). It must then wait for it to exit (see core.thread.thread_joinAll below): import std.stdio; import std.concurrency; import core.thread; struct Done {} void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (ubyte[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer.idup); } tid.send(Done()); import core.thread; thread_joinAll(); } void fileWriter() { // Write loop bool done = false; while (!done) { receive( (immutable(ubyte)[] buffer) { stdout.write(buffer); }, (Done _) { done = true; }); } }
 ----------------
 [47, 47, 32, 101, 120, 97, ....

 ....
 The numbers 47, 47, 32, etc look like the ASCII indexes of the characters
 which should be in the output,  not the characters themselves!
You are writing ubyte[]. What you see is the default output for such a slice. If you are sure that the data is UTF-8, then you can cast before outputting: stdout.write(cast(string)buffer); Ali
Jun 19 2013
parent "Roger Stokes" <rs rogerstokes.free-online.co.uk> writes:
Many thanks, Ali

I put together your suggestions, and it all works correctly !

Thanks again.

On Wednesday, 19 June 2013 at 19:50:55 UTC, Ali Çehreli wrote:
 On 06/19/2013 12:14 PM, Roger Stokes wrote:

 and the result compiled and executed with no error signals,
but the
 resulting output of the file-copy was not the same as the
input, it
 looked like this:

 std.concurrency.OwnerTerminated std\concurrency.d(248): Owner
terminated For a clean exit, the owner must tell the worker that there is no more data (see struct Done below). It must then wait for it to exit (see core.thread.thread_joinAll below): import std.stdio; import std.concurrency; import core.thread; struct Done {} void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (ubyte[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer.idup); } tid.send(Done()); import core.thread; thread_joinAll(); } void fileWriter() { // Write loop bool done = false; while (!done) { receive( (immutable(ubyte)[] buffer) { stdout.write(buffer); }, (Done _) { done = true; }); } }
 ----------------
 [47, 47, 32, 101, 120, 97, ....

 ....
 The numbers 47, 47, 32, etc look like the ASCII indexes of
the characters
 which should be in the output,  not the characters themselves!
You are writing ubyte[]. What you see is the default output for such a slice. If you are sure that the data is UTF-8, then you can cast before outputting: stdout.write(cast(string)buffer); Ali
Jun 20 2013
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 19 June 2013 at 19:14:58 UTC, Roger Stokes wrote:
 and got this compiler diagnostic:
Oh, I thought you were writing to a socket. Yeah, to a different thread, D will complain if you don't make a sharable copy. So you do want to idup it...
 [47, 47, 32, 101, 120, 97, ....

 ....
 The numbers 47, 47, 32, etc look like the ASCII indexes of the 
 characters
 which should be in the output,  not the characters themselves!
The reason here is this line:
       stdout.write(buffer);
The write function changes the format based on the type of input. Since the input here is a ubyte[], it doesn't realize it is a printable string and prints the numeric values of a byte array instead. Try stdout.write(cast(string) buffer)) and you should get what you expect. Another potential change would be to use stdin.byLine instead of stdin.byChunk. byLine returns char[], one line at a time, but it cuts off the newline character (if I remember correctly) and can complain if the input isn't valid UTF-8, so it wouldn't work right for a generic file copy function.
Jun 19 2013
parent "Roger Stokes" <rs rogerstokes.free-online.co.uk> writes:
Adam, many thanks for your helpful reply.

On Wednesday, 19 June 2013 at 19:53:08 UTC, Adam D. Ruppe wrote:
 On Wednesday, 19 June 2013 at 19:14:58 UTC, Roger Stokes wrote:
 and got this compiler diagnostic:
Oh, I thought you were writing to a socket. Yeah, to a different thread, D will complain if you don't make a sharable copy. So you do want to idup it...
 [47, 47, 32, 101, 120, 97, ....

 ....
 The numbers 47, 47, 32, etc look like the ASCII indexes of the 
 characters
 which should be in the output,  not the characters themselves!
The reason here is this line:
      stdout.write(buffer);
The write function changes the format based on the type of input. Since the input here is a ubyte[], it doesn't realize it is a printable string and prints the numeric values of a byte array instead. Try stdout.write(cast(string) buffer)) and you should get what you expect. Another potential change would be to use stdin.byLine instead of stdin.byChunk. byLine returns char[], one line at a time, but it cuts off the newline character (if I remember correctly) and can complain if the input isn't valid UTF-8, so it wouldn't work right for a generic file copy function.
Jun 20 2013