Re: Smartest way to read a number?

2011-11-10 Thread Kai Meyer
I don't get the exception on Linux after a new line, I have to wait 
until EOF, which is typically the end of the program if reading from 
STDIN. Not very useful.


import std.stdio;

T readNumber(T)()
{
T result;
stdin.readf("%s", &result);
return result;
}
void main()
{
try
{
int n = readNumber!int();
writeln(n);

float f = readNumber!float();;
writeln(f);
}
catch(Exception e)
{
writeln(e.msg);
}
}


Sample execution:
---
[kai.meyer@kai-rhel6 D]$ dmd -run readnum.d
a
1
1.2
** I hit Ctrl-D here, so this line isn't part of the output ***
std.conv(1157): Can't convert value `a
1
1.2
' of type LockingTextReader to type int
---

Or if you prefer with out my terminal echoing my input:
---
[kai.meyer@kai-rhel6 D]$ echo -e 'a\n1\n1.2\n' | dmd -run readnum.d
std.conv(1157): Can't convert value `a
1
1.2

' of type LockingTextReader to type int
--


On 11/10/2011 02:58 PM, Tobias Brandt wrote:

import std.stdio;

T readNumber(T)()
{
 T result;
 stdin.readf("%s",&result);
 return result;
}

Throws a ConvException if the input string wasn't in the right format.

On 10 November 2011 22:48, Fabian  wrote:

Hey guys.

I just want to write a few console applications. Usualy I have to read numbers
to calculate some values. But what's the smartest way to read and convert the
input?

I've coded these lines:

import std.stdio, std.string, std.conv;

T readNumber(T)()
{
string buffer;
stdin.readln(buffer);
buffer = chomp(buffer);

if(isNumeric(buffer))
{
return parse!T(buffer);
}
else
{
throw new Exception("Input is not a number!");
}
}

void main()
{
try
{
int n = readNumber!int();
writeln(n);

float f = readNumber!float();
writeln(f);
}
catch(Exception e)
{
writeln(e.msg);
}
}

Can I use that function or is there a cleaner way to do this job?

Greetings
Fabian





Re: Queue thread

2011-11-21 Thread Kai Meyer

On 11/20/2011 02:36 PM, bioinfornatics wrote:

Le dimanche 20 novembre 2011 à 03:09 -0800, Jonathan M Davis a écrit :

On Sunday, November 20, 2011 11:59:14 bioinfornatics wrote:

Dear,
I would like to know if they are a way to run run a queue thread an run
(nb core * 2 + 1) = nb thread in same time

something like:
size_t nb_core = 9;
Queue q = new Queue( 9, process1, process2, process3 );
q.run();


Look at std.parallelism. I don't know if it'll do quite what you want, but
it's the closest that you'll find in Phobos.

- Jonathan M Davis



i have tred to use TaskPool but i fail
Error: /parallelism.d(434): Error: no property 'opCall' for type
'fastcgi.application.Page'

the problem raise here:
https://github.com/bioinfornatics/DFastCGI/blob/master/src/fastcgi/application.d#L74
 (i think)

Any help are welcome

thanks



I looked at your code, and saw this:
https://github.com/bioinfornatics/DFastCGI/blob/master/src/fastcgi/application.d#L18
_taskPool   = new TaskPool( totalCPUs * threadsPerCPU + 1);

On my machine, that would come out to 1:

[kai.meyer@kai-rhel6 D]$ cat cpu.d
import std.stdio;
import std.parallelism : totalCPUs, TaskPool, task;
import std.cpuid : threadsPerCPU;

void main()
{
writefln("totalCPUs %s", totalCPUs);
writefln("threadsPerCPU %s", threadsPerCPU);
writefln("totalCPUs * threadsPerCPU + 1 = %s\n", totalCPUs * 
threadsPerCPU + 1);

}
[kai.meyer@kai-rhel6 D]$ dmd -run cpu.d
totalCPUs 8
threadsPerCPU 0
totalCPUs * threadsPerCPU + 1 = 1

Did you mean this?
_taskPool   = new TaskPool( totalCPUs * (threadsPerCPU + 1));


Re: Queue thread

2011-11-22 Thread Kai Meyer

On 11/21/2011 11:27 AM, Andrej Mitrovic wrote:

How come you don't have any threads per CPU? I guess this is a
difference between multi-processor and multi-core machines maybe?


I don't know, I'm not much of a hardware guy.

Here's the 8th CPU's entry from /proc/cpuinfo. This is a Dell Optiplex 980

processor   : 7
vendor_id   : GenuineIntel
cpu family  : 6
model   : 30
model name  : Intel(R) Core(TM) i7 CPU 860  @ 2.80GHz
stepping: 5
cpu MHz : 1197.000
cache size  : 8192 KB
physical id : 0
siblings: 8
core id : 3
cpu cores   : 4
apicid  : 7
initial apicid  : 7
fpu : yes
fpu_exception   : yes
cpuid level : 11
wp  : yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat 
pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp 
lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc 
aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr 
pdcm sse4_1 sse4_2 popcnt lahf_lm ida tpr_shadow vnmi flexpriority ept vpid

bogomips: 5585.03
clflush size: 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:


Re: DFastCGI

2011-11-22 Thread Kai Meyer

On 11/22/2011 07:26 AM, bioinfornatics wrote:

dear, i started to interface fastcgi to D
https://github.com/bioinfornatics/DFastCGI

They are a Readme and some example for quick start

at this time take example from examples/test3_fcgiapp.d

Any help are welcome


Thanks



I don't see a test3_fcgiapp.d, but I've tested the
test_fcgiapp on CentOS 6 with dmd (the Fedora rpm works great).

Once I fixed the build script to work properly on my machine, everything 
else worked out of the box. I installed fastcgi fresh on my server just 
to test this, no extra config required.


I'm not very good with github, or I would have forked, and submitted a 
pull request.
diff --git a/build.sh b/build.sh
index 4c2e737..cf7b64a 100755
--- a/build.sh
+++ b/build.sh
@@ -49,7 +49,7 @@ DESTDIR="../install"
 LIBDIR_PATH=""
 DFLAGS="-w -g -op -c -od../build"
 
-while getopts “hvqscf:l:p:” OPTION
+while getopts “hvqsc:f:l:p:” OPTION
 do
 case $OPTION in
 c)
@@ -202,11 +202,11 @@ case ${DC} in
 echo "not supported"
 else
 if [[ $VERBOSE -ge 2 ]]; then
-echo -e "${DC} -link *.o -of 
${LIBDIR_PATH}/libDFastCGI-${COMPILER}.a"
+echo -e "${DC} -lib *.o 
-of${LIBDIR_PATH}/libDFastCGI-${COMPILER}.a"
 fi
-${DC} -link  $(find . -name "*.o") -of 
${LIBDIR_PATH}/libDFastCGI-${COMPILER}.a
+${DC} -lib $(find . -name "*.o") 
-of${LIBDIR_PATH}/libDFastCGI-${COMPILER}.a
 if [[ $? -ge 1 ]]; then
-fail "${DC} -link"
+fail "${DC} -lib"
 fi
 fi
 ;;


Re: About File.rawWrite

2011-11-29 Thread Kai Meyer

On 11/29/2011 08:00 AM, Denis Shelomovskij wrote:

29.11.2011 15:57, bearophile пишет:

This D2 program runs in about 5.13 seconds on my PC:


import std.stdio;
void main() {
auto f = File("bytes_test.dat", "wb");
ubyte[3] RGB;
foreach (_; 0 .. 1_000_000)
f.rawWrite(RGB);
}



While this C program runs in about 0.14 seconds:


#include
int main() {
FILE *f = fopen("bytes_test.dat", "wb");
unsigned char RGB[3] = {0};
int i;
for (i = 0; i< 100; i++)
fwrite(RGB, 1, 3, f);
return 0;
}


Is my D2 program wrong, or is File.rawWrite in need of some improvements?

(Writing 3 bytes at a time is not efficient, but the C code shows that
the runtime is acceptable for me for small files).

Bye,
bearophile


Your OS is Windows, right? On Windows, rawWrite and rawRead always
flushes stream, sets binary mode, reads/writes, flushes stream again,
sets previous mode. This is definitely unnecessary slow - at least it
should change mode only if needed (the file is opened in a text mode).
The better solution is to change all other functions so the file mode
will be changed lazily (for a text file, raw* functions will change file
mode and leave file in this mode until a call of a function, that really
needs a file to be in a text mode).

By the way, why this changing mode behaviour is Windows only? Yes, it is
clearly documented that this is the case, but it isn't documented _why_
this is the case.

Quick link to the current rawRead implementation (for happy owners of
Google's Chrome, the fastest beautiful web browser that can BSOD your
Windows even without administrator rights) (the link isn't for Firefox:
it will slow down the browser and be displayed incorrectly):
https://github.com/D-Programming-Language/phobos/blob/master/std/stdio.d#L458

My firefox handled the link just fine. Ofcourse my dev machine is an 8 
core i7 with 16 GB of ram.


-Kai Meyer


std.json dynamic initialization of JSONValue

2011-12-01 Thread Kai Meyer

I'm finding std.json extremely well written, with one glaring exception.

I can't seem to figure out how to do this:

JSONValue root = JSONValue(null, JSON_TYPE.OBJECT);
root.object["first_object"] = JSONValue(null, JSON_TYPE.OBJECT);
root.object["first_string"] = JSONValue("first_string", JSON_TYPE.STRING);

which would decode to:

{"first_object":{},"first_string":"first_string"}

What I end up having to do is:
JSONValue root;
root.type = JSON_TYPE.OBJECT;
root.object["first_object"] = JSONValue();
root.object["first_object"].type = JSON_TYPE.OBJECT;
root.object["first_string"] = JSON_Value();
root.object["first_string"].type = JSON_TYPE.STRING;
root.object["first_string"].str = "first_string";

That just feels like I'm doing it wrong. Is there a way to dynamically 
initialize a JSONValue struct? If I try to intialize the JSONValue 
object with anything other than simply null, or empty string, I either 
get a compile error or a segfault at run-time.


root.object["first_object"] = JSONValue(null, JSON_TYPE.OBJECT);

compile error:
Error: overlapping initialization for integer

root.object["first_string"] = JSONValue("first_string");
run-time segfault.

Any ideas?


Download file via http

2011-12-13 Thread Kai Meyer
I've been trying to modify the htmlget.d example for std.socketstream 
(http://www.d-programming-language.org/phobos/std_socketstream.html) to 
be able to download a file. My code ends up looking like this at the end:


auto outfile = new std.stream.File(destination, FileMode.Out);
outfile.copyFrom(ss, bytes_needed);

I get bytes_needed from the Content-Length header. The I get the correct 
number of bytes from the Content-Length, bytes_needed gets the right 
value, but the resulting file isn't right. The file has the right number 
of bytes, but I appear to have an extra '0a' at the very beginning of 
the file, but if I do 'ss.getchar()', to get rid of it, I get an 
exception that there's not enough data in the stream.


Here's the output from hexdump that I'm basing my analysis from. Sorry 
if it doesn't come through 100% formatted correctly.


[kai@server _source]$ hexdump -C correct_file.exe | head
  4d 5a 60 00 01 00 00 00  04 00 10 00 ff ff 00 00 
|MZ`.|
0010  fe 00 00 00 12 00 00 00  40 00 00 00 00 00 00 00 
|@...|
0020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
||
0030  00 00 00 00 00 00 00 00  00 00 00 00 60 00 00 00 
|`...|
0040  52 65 71 75 69 72 65 73  20 57 69 6e 33 32 20 20  |Requires 
Win32  |
0050  20 24 16 1f 33 d2 b4 09  cd 21 b8 01 4c cd 21 00  | 
$..3!..L.!.|
0060  50 45 00 00 4c 01 06 00  00 00 00 00 00 00 00 00 
|PE..L...|
0070  00 00 00 00 e0 00 8e 81  0b 01 08 00 00 7e 28 00 
|.~(.|
0080  00 02 00 00 00 00 00 00  8c d7 27 00 00 20 00 00 
|..'.. ..|
0090  00 a0 28 00 00 00 40 00  00 10 00 00 00 02 00 00 
|..(...@.|

[kai@server _source]$ hexdump -C downloaded_file.exe | head
  0a 4d 5a 60 00 01 00 00  00 04 00 10 00 ff ff 00 
|.MZ`|
0010  00 fe 00 00 00 12 00 00  00 40 00 00 00 00 00 00 
|.@..|
0020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
||
0030  00 00 00 00 00 00 00 00  00 00 00 00 00 60 00 00 
|.`..|
0040  00 52 65 71 75 69 72 65  73 20 57 69 6e 33 32 20  |.Requires 
Win32 |
0050  20 20 24 16 1f 33 d2 b4  09 cd 21 b8 01 4c cd 21  | 
$..3!..L.!|
0060  00 50 45 00 00 4c 01 06  00 00 00 00 00 00 00 00 
|.PE..L..|
0070  00 00 00 00 00 e0 00 8e  81 0b 01 08 00 00 7e 28 
|..~(|
0080  00 00 02 00 00 00 00 00  00 8c d7 27 00 00 20 00 
|...'.. .|
0090  00 00 a0 28 00 00 00 40  00 00 10 00 00 00 02 00 
|...(...@|

[kai@server _source]$ hexdump -C correct_file.exe | tail
002b5c10  80 30 84 30 88 30 8c 30  90 30 94 30 98 30 9c 30 
|.0.0.0.0.0.0.0.0|
002b5c20  a0 30 a4 30 a8 30 ac 30  b0 30 b4 30 b8 30 bc 30 
|.0.0.0.0.0.0.0.0|
002b5c30  c0 30 c4 30 c8 30 cc 30  d0 30 d4 30 d8 30 dc 30 
|.0.0.0.0.0.0.0.0|
002b5c40  f4 30 f8 30 fc 30 00 31  64 31 68 31 6c 31 70 31 
|.0.0.0.1d1h1l1p1|
002b5c50  74 31 38 37 00 00 00 00  00 00 00 00 00 00 00 00 
|t187|
002b5c60  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
||

*
002b5e00  00 00 00 00 00 00 00 00  00 00 00 00 02 00 00 00 
||

002b5e10  00 00 00 00 00 00 00 00  00 00 00 00  ||
002b5e1c
[kai@server _source]$ hexdump -C downloaded_file.exe | tail
002b5c10  30 80 30 84 30 88 30 8c  30 90 30 94 30 98 30 9c 
|0.0.0.0.0.0.0.0.|
002b5c20  30 a0 30 a4 30 a8 30 ac  30 b0 30 b4 30 b8 30 bc 
|0.0.0.0.0.0.0.0.|
002b5c30  30 c0 30 c4 30 c8 30 cc  30 d0 30 d4 30 d8 30 dc 
|0.0.0.0.0.0.0.0.|
002b5c40  30 f4 30 f8 30 fc 30 00  31 64 31 68 31 6c 31 70 
|0.0.0.0.1d1h1l1p|
002b5c50  31 74 31 38 37 00 00 00  00 00 00 00 00 00 00 00 
|1t187...|
002b5c60  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
||

*
002b5e00  00 00 00 00 00 00 00 00  00 00 00 00 00 02 00 00 
||

002b5e10  00 00 00 00 00 00 00 00  00 00 00 00  ||


Re: Download file via http

2011-12-13 Thread Kai Meyer

On 12/13/2011 10:39 AM, Vladimir Panteleev wrote:

On Tuesday, 13 December 2011 at 17:29:20 UTC, Kai Meyer wrote:

I get bytes_needed from the Content-Length header. The I get the
correct number of bytes from the Content-Length, bytes_needed gets the
right value, but the resulting file isn't right. The file has the
right number of bytes, but I appear to have an extra '0a' at the very
beginning of the file, but if I do 'ss.getchar()', to get rid of it, I
get an exception that there's not enough data in the stream.


In an HTTP request, the headers are separated from the body by an empty
line. Headers use CR/LF line endings, so the body is always preceded by
a 0D 0A 0D 0A sequence. It looks like your code is not snipping the last
0A.

Where did the getchar method come from? There is no mention of it in
Phobos. Perhaps you could try the read(out ubyte) method?


http://www.d-programming-language.org/phobos/std_stream.html

Oh, I meant getc(), not getchar(), sorry. It looks like read(out ubyte) 
worked on windows.


I'm using ss.readLine() to pull headers from the stream. When the string 
returned from ss.readLine() is empty, then I move on to the stream. I'm 
going to be using this application on Windows, Linux, and Mac, which is 
why I chose D. This feels like I've just entered the newline/carriage 
return nightmare. Should I not be using readLine()? Or is there some 
generic code that will always work and stick me at the beginning of the 
file?


-Kai Meyer


Re: Download file via http

2011-12-13 Thread Kai Meyer

On 12/13/2011 11:10 AM, Regan Heath wrote:

On Tue, 13 Dec 2011 17:58:57 -, Kai Meyer  wrote:


On 12/13/2011 10:39 AM, Vladimir Panteleev wrote:

On Tuesday, 13 December 2011 at 17:29:20 UTC, Kai Meyer wrote:

I get bytes_needed from the Content-Length header. The I get the
correct number of bytes from the Content-Length, bytes_needed gets the
right value, but the resulting file isn't right. The file has the
right number of bytes, but I appear to have an extra '0a' at the very
beginning of the file, but if I do 'ss.getchar()', to get rid of it, I
get an exception that there's not enough data in the stream.


In an HTTP request, the headers are separated from the body by an empty
line. Headers use CR/LF line endings, so the body is always preceded by
a 0D 0A 0D 0A sequence. It looks like your code is not snipping the last
0A.

Where did the getchar method come from? There is no mention of it in
Phobos. Perhaps you could try the read(out ubyte) method?


http://www.d-programming-language.org/phobos/std_stream.html

Oh, I meant getc(), not getchar(), sorry. It looks like read(out
ubyte) worked on windows.

I'm using ss.readLine() to pull headers from the stream. When the
string returned from ss.readLine() is empty, then I move on to the
stream. I'm going to be using this application on Windows, Linux, and
Mac, which is why I chose D. This feels like I've just entered the
newline/carriage return nightmare. Should I not be using readLine()?
Or is there some generic code that will always work and stick me at
the beginning of the file?


I would have expected what you're doing to work.

IIRC when you make a GET request you send HTTP/1.0 or HTTP/1.1 or
similar in the GET request line, right? (my memory of the syntax is a
bit fuzzy).

Warning, wacky idea with little/no backing knowledge.. IIRC using
HTTP/1.1 introduced additional data into the response, lengths or
checksums, or something - I never did get to the bottom of it. But, if
you change to using HTTP/1.0 they go away. I wonder if the 0A is related
to that. As a simple test you could try HTTP/1.0 in your request and
look at the response content-length, it might just be 1 byte shorter as
a result.

Regan



Doing a read(out ubyte) read a single byte from the stream, and allowed 
me to continue to read the full content-length number of bytes. 
Switching read(out ubyte) for a simple getc() caused the 
not-enough-bytes in stream exception. I'm now downloading the correct 
size file with bytes in the correct places after calling read().


I may or may not play with HTTP/1.0. I need to turn my attention to 
other matters at the moment though, since it currently "works".


-Kai Meyer


Re: newbie question: Can D do this?

2011-12-19 Thread Kai Meyer

On 12/19/2011 09:17 AM, clk wrote:

Hello,
I'm new to this mailing list. I'm trying to learn D to eventually use it
in production code.
I'm a little bit intimidated by the fact that the topics in the d-learn
list look rather advanced to a newbie like me.
I have 3 fairly simple questions:

1) Does D support something like the javascript 1.8 destructuring
assigment (multiple assigment in python):

[a, b] = [b, a];


I would love multiple assignment like this, but it's tricky. But your 
usage isn't really multiple assignment as much as it is a swap. What I'd 
love is something like this:


[a, b, c] = [get_a(), get_b(), get_c()];

Or

[a, b, c] = [to!(int)(argv[1]), some_other_value, argv[4]);





2) D doesn't seem to support the list comprehension syntax available in
python and javascript. Is this correct?

[f(x) for x in list if condition]


No, D's syntax is very C-ish. I don't expect syntax like this to ever 
show up (though what you are doing is possible with things like 
std.algorithm)




3) D's slice operator apparently doesn't allow the use of a stride other
than unity as is allowed with fortran and matlab. Is there a way to
implement this feature so that

[1, 2, 3, 4, 5][0..$:2] would refer to [1, 3, 5], etc..., where 2 is the
non unit stride. Or is the find function from std.algorithm the only
option to achieve the same behavior.


Ya, std.range, like Ali said.



I find the 3 features above extremely convenient in every day coding.
Thanks,
-clk





Re: Using "in" with associative arrays and then indexing them (efficiency)

2012-01-03 Thread Kai Meyer

On 01/03/2012 04:07 AM, Jonathan M Davis wrote:

On Tuesday, January 03, 2012 11:52:13 Matej Nanut wrote:

Hello everyone,

I would like to know whether

 if (symbol in symbols)
 return symbols[symbol];

is any less efficient than

 auto tmp = symbol in symbols;
 if (tmp !is null)
 return *tmp;

Without optimisation, it looks like the first example
searches for `symbol' twice.


Of course it does. in does a search and returns a pointer to the element in
the AA (or null if it isn't there). The subscript operator also does a search,
returning the element if it's there and blowing up if it's not
(OutOfRangeError IIRC without -release and who-knows-what with -release). So,
if you use in and then the subscript operator, of course it's going to search
twice. Part of the point of using in is to not have to do a double lookup
(like you would be doing if AAs had a contains function and you called that
prior to using the substript operator).

The correct way to do it is the second way, though you should be able to
reduce it to

if(auto tmp = symbol in symbols)
 return *tmp;

- Jonathan M Davis


+1

Very slick :)


CMake for D

2012-02-13 Thread Kai Meyer
I have some D code that I would like to integrate into an existing CMake 
infrastructure. I've seen these two projects:

http://www.dsource.org/projects/cmaked
http://plplot.svn.sourceforge.net/viewvc/plplot/trunk/cmake/modules/language_support/cmake/Platform/

Both are quite old. Can anybody comment on the usability of either of 
these projects? Or perhaps point me to another project that will work?


Re: Segmentation fault hell in D

2012-06-08 Thread Kai Meyer

On 06/08/2012 11:30 AM, "Jarl André" " wrote:

Evry single time I encounter them I yawn. It means using the next
frickin hour to comment away code, add more log statements and try to
eleminate whats creating the hell of bugz, segmantation fault. Why can't
the compiler tell me anything else than the fact that i have referenced
data that does not exist? Thanks I knew that. Now, please tell me where
the error occured Jeezes.


If you build with -debug, it should enable code that will do those 
checks for you in things like arrays and associative arrays (where I 
find I have the most problems). It'll throw an exception rather than 
segfault. Very handy.


std.widows.registry

2012-08-22 Thread Kai Meyer
If I try to modify a registry value with 'key.setValue()', I get 
an error 5, which I think is ERROR_ACCESS_DENIED. Even if I right 
click my .exe and choose 'run as Administrator'. I am on Windows 
7 x64, and dmd 2.060. From my research, I think I have to modify 
my privilege tokens:


http://msdn.microsoft.com/en-us/library/windows/desktop/aa387705%28v=vs.85%29.aspx

But this example calls methods in advapi that I can't find any 
bindings for in the D source, namely:

OpenProcessToken
LookupPrivilegeValueW
AdjustTokenPrivileges

Any ideas?


Link against MinGW libraries

2012-08-22 Thread Kai Meyer
There's got to be a way to link against libraries generated by 
MinGW, right? I'm using CMake to create a very simple 1 method 
library. If I tell D to link against the .lib (simple ar 
archive), it complains that it's an invalid library. If I tell D 
to link against the .dll, it complains that there is no .lib.


I seem to remember thinking that Microsoft tools create a .dll 
and a .lib for development libraries, and you link against the 
.lib but run against the .dll. I don't know how to make MinGW (or 
cmake for that matter) generate both the .dll and .lib. I seem to 
remember that other projects I've built with the Visual Studio 
compiler, I get .lib and .dll files for my shared libraries, and 
those seem to work.


Any help would be appreciated.


Re: std.widows.registry

2012-08-22 Thread Kai Meyer

On Wednesday, 22 August 2012 at 14:52:00 UTC, Kai Meyer wrote:
If I try to modify a registry value with 'key.setValue()', I 
get an error 5, which I think is ERROR_ACCESS_DENIED. Even if I 
right click my .exe and choose 'run as Administrator'. I am on 
Windows 7 x64, and dmd 2.060. From my research, I think I have 
to modify my privilege tokens:


http://msdn.microsoft.com/en-us/library/windows/desktop/aa387705%28v=vs.85%29.aspx

But this example calls methods in advapi that I can't find any 
bindings for in the D source, namely:

OpenProcessToken
LookupPrivilegeValueW
AdjustTokenPrivileges

Any ideas?


Doh, I just found it. REGSAM.KEY_ALL_ACCESS..


Using BOM to auto-detect file encoding

2013-04-09 Thread Kai Meyer
I would like to know if there exists a 'stream' or 'file' class 
that is able to take a text file with a correct BOM, and an 
'ouput' utf encoding. It want it to be capable of detecting the 
'input' stream utf encoding by using the BOM, and do the encoding 
for me on the way out in the specified 'output' utf encoding.


Right now I am using std.stream.File (which I know is going the 
way of all the earth soon) and manually parsing the BOM myself to 
then choose whether I call 'readLine' or 'readLineW', and then 
subsequently calling 'toUTF8' after that.


It just seems like something like this would be nice to have in 
phobos if it's not already there.


datetime fails with undefined reference

2011-02-18 Thread Kai Meyer
I can't seem to use std.datetime at all. I get undefined reference on whether
I use a StopWatch, or if I just try to compile the unittest. All I have to do
is declare a StopWatch:

import std.stdio;
import std.datetime;

void main()
{
StopWatch sw;
}


This fails to compile:
[kai@worky ~]$ dmd datetime_test.d
/usr/lib/gcc/x86_64-redhat-linux/4.5.1/../../../../lib/libphobos2.a(datetime_35c_30e.o):
In function `_D3std8datetime7systimeFNeZS3std8datetime5Ticks':
std/datetime.d:(.text._D3std8datetime7systimeFNeZS3std8datetime5Ticks+0x1c):
undefined reference to `clock_gettime'
/usr/lib/gcc/x86_64-redhat-linux/4.5.1/../../../../lib/libphobos2.a(datetime_359_1fe.o):
In function `_D3std8datetime5Ticks12_staticCtor5OFNeZv':
std/datetime.d:(.text._D3std8datetime5Ticks12_staticCtor5OFNeZv+0x1b):
undefined reference to `clock_getres'
collect2: ld returned 1 exit status
--- errorlevel 1

Am I missing some libraries somewhere?

If I 'import core.sys.posix.time, core.sys.posix.sys.time;', parts of dattime
work, and others don't. A main with just:
writef("%s %s\n", (is(typeof({auto fp = &clock_gettime; };

Prints "true true", but using them like this gives undefined again:
timespec ts; writef("%d\n", clock_getres(CLOCK_REALTIME, &ts));


datetime_test.o: In function `_Dmain':
datetime_test.d:(.text._Dmain+0x34): undefined reference to `clock_getres'
collect2: ld returned 1 exit status
--- errorlevel 1


I'm running Fedora 14 x86_64, dmd-2.051-0.i386, glibc-2.13-1.i686.

Any ideas?


Re: datetime fails with undefined reference

2011-02-18 Thread Kai Meyer
Great news! Worked like a champ. Is there documentation somewhere that I 
missed? I
would love to be able to answer these questions on my own. I've been stumped on
this one for a week :(


Re: datetime fails with undefined reference

2011-02-18 Thread Kai Meyer
== Quote from Jonathan M Davis (jmdavisp...@gmx.com)'s article
> On Friday, February 18, 2011 10:12:09 Kai Meyer wrote:
> > Great news! Worked like a champ. Is there documentation somewhere that I
> > missed? I would love to be able to answer these questions on my own. I've
> > been stumped on this one for a week :(
> That should be in the dmd.conf in dmd.2.052.zip. If you're using an old
> dmd.conf, that would be the problem. Actually, I wouldn't have expected and 
> old
> dmd.conf to work at all, since the directory structure for the lib folder(s) 
> was
> changed due to the addition of 64-bit. So, I don't know what the deal with 
> your
> setup is. Regardless, make sure that your current dmd.conf is either the most
> up-to-date on or at least based on it. Otherwise, you're going to be running
> into issues.
> - Jonathan M Davis

Ok, my dmd.conf that came with the download does not have it in there. The 
package
doesn't claim ownership to /etc/dmd.conf. I removed the rpm package, deleted the
old dmd.conf, and installed the rpm again, but the dmd.conf that was generated 
is
exactly the same:
[kai@worky ~]$ cat /etc/dmd.conf

[Environment]

DFLAGS= -I/usr/include/d/dmd/phobos -I/usr/include/d/dmd/druntime/import 
-L-L/usr/lib


Should I just simply add "-L-lrt" to the dmd.conf for now? Or just put it in my
make file?

Why does the rpm not claim ownership of the config file?:
[kai@worky ~]$ rpm -qf /etc/dmd.conf
file /etc/dmd.conf is not owned by any package
[kai@worky ~]$ rpm -ql dmd | grep dmd.conf
/usr/share/man/man5/dmd.conf.5.gz

Thanks for the fast replies!


Re: datetime fails with undefined reference

2011-02-21 Thread Kai Meyer
== Quote from Jonathan M Davis (jmdavisp...@gmx.com)'s article
> On Friday, February 18, 2011 16:27:23 Russel Winder wrote:
> > As noted in my earlier email on the other list, I too got this problem.
> > Fromn what I can tell 1.066 and 2.051 have dmd.conf files but there is
> > no such thing in the 1.067 and 2.052 distributions.  So the "out of the
> > box" configuration does seem to be "broken".
> And as I said in my response to your other message, the proper dmd.conf file 
> _is_
> in the distributed zip file. So, unless you're dealing with the deb or rpm, 
> and
> they're broken, and I don't know why you wouldn't be seeing a new dmd.conf 
> with
> the 2.052 release. But I don't know what the state of the rpm or deb is. I 
> just
> always use the zip file, which is very simple.
> - Jonathan M Davis

Ok, I can fix the dmd.conf. Who does manage the RPM packaging? And how can I 
get a
hold of them?


RPM Package management

2011-02-28 Thread Kai Meyer
I would like to get involved with the rpm build process. Who can I 
contact to get more information on what help I can provide?


Help learning how to interface with c(++)

2011-03-04 Thread Kai Meyer

I can't seem to get this to work right:

gcc -m32 -shared -fPIC Test.cpp -o libTest.so
g++ -m32 test_c.cpp -L. -lTest -o test_c
wine htod.exe Test.h Test.d
dmd test_d.d Test.d -L-L. -L-lTest -oftest_d
test_d.o: In function `_Dmain':
Test.d:(.text._Dmain+0x20): undefined reference to `increment'
collect2: ld returned 1 exit status
--- errorlevel 1
make: *** [test_d] Error 1

The resulting test_c binary from g++ works as intented (With either 
LD_LIBRARY_PATH="." or LD_RUN_PATH="."):

$ ./test_c
Count = 0
Count = 1
$ ldd test_c
linux-gate.so.1 =>  (0x00ad1000)
libTest.so (0x005b9000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x4970f000)
libm.so.6 => /lib/libm.so.6 (0x4955b000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x49587000)
libc.so.6 => /lib/libc.so.6 (0x493ab000)
/lib/ld-linux.so.2 (0x4938a000)

Any ideas on what I'm doing wrong here?

I've dropbox-ed the code if it's helpful.
http://dl.dropbox.com/u/12135920/kai_test_c_interface.zip

-Kai Meyer


in/out with -release

2011-03-04 Thread Kai Meyer
I have an 'enforce' function call in an 'in' block for a function. When I
compile with "-release -O -inline", the in/out blocks appear to be skipped.
It's a simple verification for a dynamic array to not have a length of 0. In
debug mode, the test condition hits the enforce in the 'in' block, but in
release mode it does not. In both release and debug mode, the same exact
enforce function works properly.

So am I to understand that -release will skip in/out blocks entirely?


Re: in/out with -release

2011-03-07 Thread Kai Meyer

On 03/05/2011 11:14 AM, Lars T. Kyllingstad wrote:

On Sat, 05 Mar 2011 18:12:30 +, Lars T. Kyllingstad wrote:


On Sat, 05 Mar 2011 10:15:48 -0700, user wrote:


On 03/04/2011 09:22 PM, Jonathan M Davis wrote:

On Friday 04 March 2011 20:14:32 Kai Meyer wrote:

I have an 'enforce' function call in an 'in' block for a function.
When I compile with "-release -O -inline", the in/out blocks appear
to be skipped. It's a simple verification for a dynamic array to not
have a length of 0. In debug mode, the test condition hits the
enforce in the 'in' block, but in release mode it does not. In both
release and debug mode, the same exact enforce function works
properly.

So am I to understand that -release will skip in/out blocks entirely?


Of course. It uses asserts. asserts are disabled in -release. Asserts
are for debugging, testing, and verifying code when developing, not
for code which is released. So, you get the benefit of the test when
you don't have -release and the benefit of speed when you do have
-release. If an assertion fails, your code logic is invalid. It's for
validating your code, not user input or whatnot.

enforce, on the other hand, is not a language primitive. It's not
intended for testing or debugging. It's intended to be used in
production code to throw an exception when its condition fails. If an
enforce fails, that generally means that you had bad input somewhere
or that an operation failed or whatnot. It's not intended for testing
the logic of your code like assert is intended to do. It's simply a
shorthand way to throw an exception when your program runs into a
problem.

- Jonathan M Davis


I don't think I understand your response entirely. I understand that
asserts are disabled in -release mode. I understand that enforce is a
function that comes with std.exception, and the code isn't hard to
follow.

What I'm confused about is the in block, and why it is skipped in
-release mode. You say "It uses asserts." I didn't put an assert in my
in block, I put an enforce. So I'm guessing that you are indicating
that the in block is treated like an assert, and is disabled with the
-release flag.

But I think after reading your post you've helped clarify that what I'm
checking (that you can't pop an empty stack) based on user input is
something I should be checking with an enforce inside the function, and
not an assert or enforce inside the in block.

I still think I would like it if you could be a little more explicit
about the in/out blocks. Are they always disabled entirely (skipped)
with -release, or just certain things?

Thanks for your help!

-Kai Meyer


That's right.  in, out and invariant blocks are not included in release
mode.

-Lars


It's documented here, by the way:
http://www.digitalmars.com/d/2.0/dmd-linux.html#switches

(Scroll down to -release.)

-Lars


All very welcome responses. Thanks for your time :) Got lots of reading 
to do.


-Kai Meyer


Re: Help learning how to interface with c(++)

2011-03-07 Thread Kai Meyer

On 03/05/2011 06:24 AM, Kagamin wrote:

Kai Meyer Wrote:


I can't seem to get this to work right:

gcc -m32 -shared -fPIC Test.cpp -o libTest.so
g++ -m32 test_c.cpp -L. -lTest -o test_c
wine htod.exe Test.h Test.d
dmd test_d.d Test.d -L-L. -L-lTest -oftest_d
test_d.o: In function `_Dmain':
Test.d:(.text._Dmain+0x20): undefined reference to `increment'
collect2: ld returned 1 exit status
--- errorlevel 1
make: *** [test_d] Error 1

The resulting test_c binary from g++ works as intented (With either
LD_LIBRARY_PATH="." or LD_RUN_PATH="."):
$ ./test_c
Count = 0
Count = 1
$ ldd test_c
linux-gate.so.1 =>   (0x00ad1000)
libTest.so (0x005b9000)


try non-shared libTest, dmd prefers single executable compilations.


Is that the only option? I know it's possible to link to external c 
libraries, and I'd like to learn how.


Re: Help learning how to interface with c(++)

2011-03-07 Thread Kai Meyer

On 03/07/2011 08:57 AM, Kai Meyer wrote:

On 03/05/2011 06:24 AM, Kagamin wrote:

Kai Meyer Wrote:


I can't seem to get this to work right:

gcc -m32 -shared -fPIC Test.cpp -o libTest.so
g++ -m32 test_c.cpp -L. -lTest -o test_c
wine htod.exe Test.h Test.d
dmd test_d.d Test.d -L-L. -L-lTest -oftest_d
test_d.o: In function `_Dmain':
Test.d:(.text._Dmain+0x20): undefined reference to `increment'
collect2: ld returned 1 exit status
--- errorlevel 1
make: *** [test_d] Error 1

The resulting test_c binary from g++ works as intented (With either
LD_LIBRARY_PATH="." or LD_RUN_PATH="."):
$ ./test_c
Count = 0
Count = 1
$ ldd test_c
linux-gate.so.1 => (0x00ad1000)
libTest.so (0x005b9000)


try non-shared libTest, dmd prefers single executable compilations.


Is that the only option? I know it's possible to link to external c
libraries, and I'd like to learn how.


So I monkeyed around a little bit, and found out that if I change 
"extern (C)" to "extern (C++)", the library links correctly and the 
program runs.


That lead me to believe that if I added the "-cpp" option to htod.exe, 
it would generate extern(C++) functions. But I got a blank Test.d file 
doing it that way.


So, gcc created a libTest.so with a function in it, and dmd only finds 
the function with extern(C++) and not with extern(C).


Now I'm just confused, yet pleased something worked.

-Kai Meyer


Re: Dynamic array void initialization

2011-03-08 Thread Kai Meyer

On 03/08/2011 02:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


Any reason you don't just do this:

S[] ss;
ss.reserve(5)
foreach(i; 0..i)
  ss ~= S(1, 2);

I think that would not do default initialization on any of the elements, 
and it would ensure that the dynamic array is own "grown" once.


Re: Dynamic array void initialization

2011-03-08 Thread Kai Meyer

On 03/08/2011 05:42 PM, Kai Meyer wrote:

On 03/08/2011 02:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


Any reason you don't just do this:

S[] ss;
ss.reserve(5)
foreach(i; 0..i)
ss ~= S(1, 2);

I think that would not do default initialization on any of the elements,
and it would ensure that the dynamic array is own "grown" once.


Sorry,
foreach(i; 0..5)

That's what I get for writing code with out trying to run it


Re: Iterating over 0..T.max

2011-03-09 Thread Kai Meyer

On 03/09/2011 09:09 AM, Magnus Lie Hetland wrote:

In a (template) data structure I'm working on, I had the following thinko:

auto a = new T[n];
foreach (T i, ref e; a) {
e = i;
}

Then I instantiated it with T=bool, and n=256. Infinite loop, of course
-- the problem being that i wraps around to 0 after the last iteration.
Easily fixed, and not that much of a problem (given that I caught it) --
I'll just use e = cast(T) i. (Of course, even with that solution, I'd
get wrap problems if n=257, but I just want to make sure I allow T.max
as a size.)

But I'm wondering: given D's excellent valua range propagations and
overflow checking, would it be possible to catch this special case
(i.e., detect when the array can be too long for the index type)? Or are
any other safeguards possible to prevent this sort of thing?



I don't see how that works in dmd2, and I don't have much experience 
with dmd1, so I'll admit that this may be different on dmd1. I get 
compilation errors with your code:


import std.stdio;

void main()
{
make_new!(bool)(256);
}

void make_new(T)(size_t n)
{
auto a = new T[n];
foreach (T i, ref e; a) {
e = i;
}
}

This gives me:
tmax.d(12): Error: operation not allowed on bool 'i'
tmax.d(5): Error: template instance tmax.make_new!(bool) error instantiating

As far as I understand, a foreach over an array makes the first value 
(i) a uint for the index, and the second value (e) a copy of the value 
in the array (in our case a bool).


import std.stdio;

void main()
{
make_new!(bool)(1);
}

void make_new(T)(size_t n)
{
auto a = new T[n];
writef("%s\n", typeof(a).stringof);
foreach (i,e; a) {
writef("%s\n", typeof(i).stringof);
writef("%s\n", typeof(e).stringof);
}
}

/*
Output:
bool[]
uint
bool
*/



But to the question about boundaries, 'i' is a uint (size_t), and on a 
4GB machine, I can't call "auto a = new bool[size_t.max];". The program 
segfaults. size_t.max / 2 for a size gives me "Memory allocation 
failed". size_t.max / 4 works fine.


I'm not sure how to get a program to do what you describe.


Re: Best way in D2 to rotate a ubyte[4] array

2011-03-09 Thread Kai Meyer

On 03/09/2011 03:41 PM, Tom wrote:

What is the most efficient way of implement a rotation of ubyte[4] array?

By rotation I mean: rotateRight([1, 2, 3, 4]) -> [4, 1, 2, 3]

TIA,
Tom;


I don't know of anything more efficient than:
ubyte[4] bytes = [1,2,3,4];
bytes = bytes[$-1] ~ bytes[0..$-1]; // Rotate left
bytes = bytes[1..$] ~ bytes[0]; // Rotate right

Both static arrays and dynamic arrays (ubyte[] bytes = [1,2,3,4];) 
perform about the same between 1 and 10 milling rotations in either 
direction. I think a temporary array might be created for the rhs, and 
then have the values of the rhs array copied to the lhs array, but I 
don't know. With static arrays, I'm not sure there would be a way to get 
around it with out at least a temporary value for the one that's moving 
between the first and last positions.


Re: Best way in D2 to rotate a ubyte[4] array

2011-03-09 Thread Kai Meyer

On 03/09/2011 04:25 PM, bearophile wrote:

Tom:


What is the most efficient way of implement a rotation of ubyte[4] array?

By rotation I mean: rotateRight([1, 2, 3, 4]) ->  [4, 1, 2, 3]


Two versions, I have done no benchmarks so far:

import std.c.stdio: printf;

union Four {
 ubyte[4] a;
 uint u;
}

void showFour(Four f) {
 printf("f.u: %u\n", f.u);
 printf("f.a: [%d, %d, %d, %d]\n",
cast(int)f.a[0], cast(int)f.a[1],
cast(int)f.a[2], cast(int)f.a[3]);
}

void main() {
 Four f;
 f.a[] = [1, 2, 3, 4];
 showFour(f);
 f.u = (f.u<<  8) | (f.u>>  24);
 showFour(f);
 printf("\n");

 // alternative
 f.a[] = [1, 2, 3, 4];
 uint u2 = f.u;
 showFour(f);
 printf("u2: %u\n", u2);
 asm {
 rol  u2, 8;
 }
 f.u = u2;
 showFour(f);
}

/*

dmd -O -release test.d

__Dmain comdat
 pushEBP
 mov EBP,ESP
 sub ESP,8
 push4
 mov EAX,offset FLAT:_D12TypeInfo_xAh6__initZ
 push4
 push3
 push2
 push1
 push4
 mov dword ptr -8[EBP],0
 pushEAX
 callnear ptr __d_arrayliteralT
 add ESP,018h
 pushEAX
 lea EAX,-8[EBP]
 pushEAX
 callnear ptr _memcpy
 mov EAX,-8[EBP]
 callnear ptr _D4test8showFourFS4test4FourZv
 mov EAX,-8[EBP]
 mov ECX,-8[EBP]
 shl EAX,8;<=
 shr ECX,018h
 or  EAX,ECX
 mov -8[EBP],EAX
 mov EAX,-8[EBP]
 callnear ptr _D4test8showFourFS4test4FourZv
 mov EAX,offset FLAT:_DATA[024h]
 pushEAX
 callnear ptr _printf
 mov EAX,offset FLAT:_D12TypeInfo_xAh6__initZ
 push4
 push4
 push3
 push2
 push1
 push4
 pushEAX
 callnear ptr __d_arrayliteralT
 add ESP,018h
 pushEAX
 lea EAX,-8[EBP]
 pushEAX
 callnear ptr _memcpy
 mov EAX,-8[EBP]
 mov -4[EBP],EAX
 mov EAX,-8[EBP]
 callnear ptr _D4test8showFourFS4test4FourZv
 mov EAX,offset FLAT:_DATA[028h]
 pushdword ptr -4[EBP]
 pushEAX
 callnear ptr _printf
 add ESP,024h
 rol -4[EBP],8   ;<=
 mov EAX,-4[EBP]
 mov -8[EBP],EAX
 mov EAX,-4[EBP]
 callnear ptr _D4test8showFourFS4test4FourZv
 mov ESP,EBP
 pop EBP
 ret
*/

In theory a C/C++/D compiler has to compile an expression like (x<<  8)|(x>>24) 
with a ROL instruction, in practice DMD doesn't do it. Months ago I have asked the two 
(four in X86) roll instructions to be added to the Phobos core intrinsics module, but I am 
not sure what Walter answered me.

Bye,
bearophile


I love it.
I've done a little benchmark that just repeats the rotate left a certain 
number of times, and then a rotate right a certain number of times. It 
looks like shifting ( << | >> ) is faster than the process of copying 
the uint value, shifting it, and copying it back. If I move the 
assignment for the rol outside of the for loop, the rol is about twice 
as fast.

http://dl.dropbox.com/u/12135920/rotate.d

Both are anywhere from 30 to 80 times faster than the slicing method I 
proposed (also included in the rotate.d file).



--
Rotating static array left to right 500 times
Finished in1971.46 milliseconds
Rotating static array right to left 500 times
Finished in1987.60 milliseconds
Rotating dynamic array left to right 500 times
Finished in1932.40 milliseconds
Rotating dynamic array right to left 500 times
Finished in1981.71 milliseconds
Shifting Union left to right 500 times
Finished in  33.46 milliseconds
Shifting Union right to left 500 times
Finished in  34.26 milliseconds
Rolling Union left to right 500 times
Finished in  67.51 milliseconds
Rolling Union right to left 500 times
Finished in  67.47 milliseconds
Rolling Union left to right 500 times with assignment with temporary 
variable outside of the loop

Finished in  28.81 milliseconds
Rolling Union right to left 500 times with assignment with temporary 
variable outside of the loop

Finished in  25.57 milliseconds



Re: Reading a line from stdin

2011-03-16 Thread Kai Meyer

On 03/16/2011 07:54 AM, Ali Çehreli wrote:

On 03/16/2011 05:49 AM, Kagamin wrote:

Ali ǥhreli Wrote:


The following program may be surprising to the novice:

import std.stdio;

void main()
{
write("What is your name? ");
string name = readln();
writeln("Hi ", name, "!");
}


What if the user typed leading spaces? Will the program operate as you
expect?


I would not like the leading spaces either, and that's another issue:
contrary to readln(), readf() leaves the newline character in the input.
I was about to start adopting the guideline of using " %s" (note the
space) when reading formatted unless there is a reason not to. Most of
the time the newline left from the previous input has nothing to do with
the next read.

Otherwise the following program gets stuck:

import std.stdio;

void main()
{
int i, j;
readf("%s%s", &i, &j);
}

As a result, my current guideline is "put a space before every format
specifier":

readf(" %s %s", &i, &j);

This is a departure from C's scanf but is more consistent.

I don't want to accept and teach buggy behavior and that's why I asked
on the D forum. Unfortunately I failed to attract interest there.

After accepting the above, I wanted to readf() lines too:

import std.stdio;

void main()
{
string s;
readf(" %s", &s);
writeln(s);
}

As another departure from C, readf() does not stop at the first
whitespace. It reads until the end of the input. Ok, I like that
behavior but it's not useful for "What is your name? " like inputs.

So it led me to readln().

I don't have a problem with whitespace being left in the line, I just
want to know whether that's the intended or accepted behavior.

Ali


I think there are two issues here. First, I think is perfectly 
reasonable to let the programmer use a simple mechanism like 
"string.chomp(stdin.readline())" or simply "chomp(readln())" when they 
don't want the new line.


Second, D doesn't seem to have a graceful way of reading an endless 
stream of  delimited by delimiting character>. I think readf is rigid, and works great in some 
cases. I would greatly appreciate something more flexible like C++'s 
extraction operator (operator>>) though. For example:

int i = 0;
while(cin >> i)
{
//Do something
}
// Done doing something


Re: How do I iteratively replace lines in a file?

2011-03-20 Thread Kai Meyer

On 03/19/2011 05:51 PM, Andrej Mitrovic wrote:

I'm trying to do something like the following:

File inputfile;
foreach (string name; dirEntries(r".\subdir\", SpanMode.shallow))
{
 if (!(isFile(name)&&  getExt(name) == "d"))
 {
 continue;
 }

 inputfile = File(name, "a+");

 foreach (line; inputfile.byLine)
 {
 if (line == "import foo.d")
 {
 inputfile.write("import bar.d");  // or ideally `line = "import 
bar.d"`
 }
 }
}

That obviously won't work. I think I might need to use the `fseek` function to 
keep track of where I am in the file, or something like that. File I/O in D is 
no fun..



The only problem with your approach that a "line" is an abstract 
concept. In a filesystem, there are only blocks of bytes. When you write 
(flush) a byte to a file, the file transaction is actually an entire 
block at a time (ext3 defaults to a 4k block, for example.) Lines are 
just an array of bytes. When dealing with (relatively) fast memory, 
modifying a line is pretty transparent. If you open a 1GB file and add 
bytes at the very beginning, the filesystem is quite likely to write out 
the entire file again.


I would suggest you write out to a temporary file, and then move the 
file on top of the original file.


foreach(name ...)
{
  inputfile = File(name, "r");
  outputfile = File("/tmp/" ~ name, "a");
  foreach(line ...)
  {
do something to line
outputfile.write(line);
  }
  outputfile.close();
  rename("/tmp" ~ name, name);
}

This will allow you to manipulate line by line, but it won't be 
in-place. This is the type of approach that a lot of text editors take, 
and a very common work around. If you were to encounter a language that 
allows you to read and write lines iteratively and in-place like this in 
a file, I'll bet you they are writing your changes to a temp file, and 
moving the file over the top of the original at the end (perhaps when 
you close()).




Re: How do I iteratively replace lines in a file?

2011-03-20 Thread Kai Meyer

On 03/20/2011 09:46 AM, Andrej Mitrovic wrote:

Yeah, I've already done exactly as you guys proposed. Note however
that `inputfile` and `outputfile` should be declared inside the
foreach loop. Either that or you have to call `close()` explicitly. If
you don't do that, file handles don't get released, and you'll
eventually get back a stdio error such as "too many file handles
opened". You could loose files this way. I know this because it just
happened yesterday while testing. :p

Anywho, I needed a quick script to append a semicolon to import lines
because I managed to screw up some files when using sed to replace
some lines. It's a quick hack but worked for me:

import std.stdio;
import std.file;
import std.stdio;
import std.path;
import std.string;

void main()
{
 File inputfile;
 File outputfile;
 string newname;

 foreach (string name; dirEntries(r".", SpanMode.breadth))
 {
 if (!(isFile(name)&&  getExt(name) == "d"))
 {
 continue;
 }

 newname = name.idup ~ "backup";
 if (exists(newname))
 {
 remove(newname);
 }

 rename(name, newname);

 inputfile = File(newname, "r");
 outputfile = File(name, "w");

 foreach (line; inputfile.byLine)
 {
 if ((line.startsWith("private import") ||
line.startsWith("import"))&&
 !line.endsWith(",")&&
 !line.endsWith(";"))
 {
 outputfile.writeln(line ~ ";");
 }
 else
 {
 outputfile.writeln(line);
 }
 }

 inputfile.close();
 outputfile.close();
 }

 foreach (string name; dirEntries(r".", SpanMode.breadth))
 {
 if (getExt(name) == "dbackup")
 {
 remove(name);
 }
 }
}



Funny, I would have just fixed it with sed.

sed -ir 's/^(import.*)/\1;' *.d

Infact, I think sed is actually a great example of an application that 
you apply a search and replace on a per-line basis. I'd be curious if 
somebody knows how their '-i' flag (for in-place) works. Based on the 
man page, I'll bet it opens the source read-only, and opens the 
destination write-only like Andrej's example.

   -i[SUFFIX], --in-place[=SUFFIX]
  edit files in place (makes backup if extension supplied)

The SUFFIX option just renames the original instead of deleting at the end.


Re: Want to help DMD bugfixing? Write a simple utility.

2011-03-20 Thread Kai Meyer

On 03/19/2011 06:11 PM, Don wrote:

Here's the task:
Given a .d source file, strip out all of the unittest {} blocks,
including everything inside them.
Strip out all comments as well.
Print out the resulting file.

Motivation: Bug reports frequently come with very large test cases.
Even ones which look small often import from Phobos.
Reducing the test case is the first step in fixing the bug, and it's
frequently ~30% of the total time required. Stripping out the unit tests
is the most time-consuming and error-prone part of reducing the test case.

This should be a good task if you're relatively new to D but would like
to do something really useful.
-Don


Is there a copy of the official D grammar somewhere online? I wrote a 
lexer for my Compiler class and would love to try and apply it to 
another grammar.


-Kai Meyer


Re: fun with properties

2011-03-23 Thread Kai Meyer

On 03/23/2011 06:48 AM, teo wrote:

How can I use properties with increment/decrement and +=/-= operators?

I did following tests (the errors are from dmd v2.052):

class T
{
 private int _x;
 @property
 public int x() { return _x; }
}

void main()
{
 int[] a;
 // case #1.1
 a.length++;// Error: a.length is not an lvalue
 // case #1.2
 a.length += 1; // Ok


 auto t = new T();
 // case #2.1
 t.x++;  // Error: t.x() is not an lvalue
 // case #2.2
 t.x += 1;   // Error: 't.x' is not a scalar, it is a @property int()
 // Error: incompatible types for ((t.x) += (1)):
'@property int()' and 'int'
 // case #2.3
 t.x()++;// Error: t.x() is not an lvalue
 // case #2.4
 t.x() += 1; // Error: t.x() is not an lvalue
}

Basically I want to change the value of a member variable, which is
accessed only through a property.
It looks like that is partially possible with the length property of
dynamic arrays although they probably are implemented in a different way.


You need a "write" property:

@property
{
public int x() { return _x; } // Read property
public void x(int x1) { _x = x1; } // Write property
}

As for the dynamic array length property:

void main()
{
int[] a;
++a.length; // Works
a.length += 1; // Works
a.length++; // Error: a.length is not an lvalue
}

I don't get why the error on a.length++ either. I'm curious about the 
answer.


Re: Want to help DMD bugfixing? Write a simple utility.

2011-03-23 Thread Kai Meyer
 that work.  The Q's are how hard is it to get
the symbols from the linker and then how hard is it to match those to
source.  IIRC there are functions in phobos to convert to/from symbol
names, so if the app had sufficient lexing and parsing capability it could
match on those.


That would require a full-blown D lexer and parser.

- Jonathan M Davis


Why are we talking about having to recreate a full-blown lexer and 
parser when there has to be one that exists for D anyway? This is 
sounding more and more like you're asking the wrong crowd to solve a 
problem. To do it right, the people who have access to the real D lexer 
and parser would need to write this utility, and in some ways, it's 
already written since compiling with out a -unittest flag already omits 
all the unittests.


So I'm a bit confused about two things.

1) Why ask the wrong people to write the tool in the first place?
2) Why are we the wrong people any way?

-Kai Meyer


Re: fun with properties

2011-03-23 Thread Kai Meyer

On 03/23/2011 10:09 AM, teo wrote:

On Wed, 23 Mar 2011 08:28:46 -0600, Kai Meyer wrote:


On 03/23/2011 06:48 AM, teo wrote:

How can I use properties with increment/decrement and +=/-= operators?

I did following tests (the errors are from dmd v2.052):

class T
{
  private int _x;
  @property
  public int x() { return _x; }
}

void main()
{
  int[] a;
  // case #1.1
  a.length++;// Error: a.length is not an lvalue // case #1.2
  a.length += 1; // Ok


  auto t = new T();
  // case #2.1
  t.x++;  // Error: t.x() is not an lvalue // case #2.2
  t.x += 1;   // Error: 't.x' is not a scalar, it is a @property
  int()
  // Error: incompatible types for ((t.x) += (1)):
'@property int()' and 'int'
  // case #2.3
  t.x()++;// Error: t.x() is not an lvalue // case #2.4
  t.x() += 1; // Error: t.x() is not an lvalue
}

Basically I want to change the value of a member variable, which is
accessed only through a property.
It looks like that is partially possible with the length property of
dynamic arrays although they probably are implemented in a different
way.


You need a "write" property:

  @property
  {
  public int x() { return _x; } // Read property public void
  x(int x1) { _x = x1; } // Write property
  }



I've already tried that, but to no avail. I am getting the errors stated
above. Can you give me a complete working example please?


Sorry, you're right. I don't think properties are done, especially given 
these features don't work as expected.


Re: clear()

2011-03-28 Thread Kai Meyer

On 03/25/2011 01:10 PM, Dr.Smith wrote:

To empty many arrays of various types, rather than:

clear(arr1);
clear(arr2);
...
clear(arrN);

is there something like:

clear(ALL);


No, but perhaps you can do a:
foreach(a; ALL)
  a.clear()

But that would require you having an iterable sequence that contains all 
of your arrays, which may or may not be worth your time to explore.




Also, after "clear(arr)", will "arr ~= value" assign starting from element 0?


Yes


Re: Little quiz

2011-03-28 Thread Kai Meyer

On 03/24/2011 06:50 PM, bearophile wrote:

A little quiz for people here: guess the output of this little D2 program (it 
compiles correctly and doesn't crash at run time, so it's a fair question):


import std.typecons: tuple;
import std.c.stdio: printf;

auto foo() {
 printf("foo\n");
 return tuple(1, 2);
}

void main() {
 foreach (x; foo().tupleof)
 printf("%d\n", x);
}


Bye,
bearophile


That's pretty cool :) Seems like we should be able to expect the same 
behavior in all of these, but that doesn't appear to be the case at all.




import std.typecons: tuple;
import std.c.stdio: printf;

auto foo() {
printf("foo\n");
return tuple(1, 2);
}

void main() {
printf("-\n");
foreach (x; foo().tupleof)
printf("%d\n", x);
printf("-\n");
auto f = foo();
printf("-\n");
foreach (x; f.tupleof)
printf("%d\n", x);
printf("-\n");
auto f2 = foo().tupleof;
printf("-\n");
foreach (x; f2)
printf("%d\n", x);
printf("-\n");
}



Re: Contracts or Exceptions?

2011-03-29 Thread Kai Meyer

On 03/29/2011 12:40 PM, Mike Linford wrote:

Hello,

So I'm writing a function for a library. It takes a struct as an
argument. The struct's fields can't just be any old values, though. The
function won't work if some of the fields are weird. It could return an
erroneous value, or even crash.

The thing is, though, that I can't tell whether the best approach is to
use an in-contract or throw an exception if it doesn't pass my test. What
would you guys recommend?





I was given two words of advice on exceptions:
"Use exceptions for the exceptional"
"Use exceptions only for the exceptional"

Meaning, if you expect something to fail frequently, using a try/catch 
is much more expensive than an if/else. "The exceptional" is something 
that should rarely ever occur, like running out of memory.


For contracts, they are usually meant as a developer tool to warn them 
when that they will be in no-man's land if they attempt to proceed any 
further. They are, therefore, not compiled in when you pass the D 
compiler the -release flag.


I don't think that contracts and exceptions are mutually exclusive. They 
provide two different safeguards. One is a tool to aid in the 
development process, one is a tool to safeguard against exceptional 
run-time scenarios.


However, I think if I rephrase your question a little bit, it might 
provide you what I think you're after. I'm making an assumption here, so 
I may be way off the mark.


"Who's responsibility is it to check whether or not the data passed into 
the function is valid? Should I accept whatever the user wants to pass 
in, and let them know when it's invalid, or should I trust that the user 
is sending in good data?"


I think that's a choice for you to make. Contract programming is often 
used to put the burden of validation on the user of the library (meaning 
programmer writing software taht uses your library). Exceptions could be 
used to indicate that the library writer is accepting responsibility for 
validating the data before using it.


But validating data is not the only reason to use exceptions, and it's 
not unusual for a library to skip all validations and force the user to 
do all the checking before hand. Arrays are a good example. When not in 
-release mode, array boundaries are checked upon every access to the 
array, and an exception is thrown if access goes out of bounds. In 
-release mode, if you go out of bounds you get a segfault. This is one 
example of giving the user (programmer) of arrays the responsibility to 
check boundaries so that the library can focus on being fast.


I think the choice comes down to a balance between performance, 
responsibility, and maintainability. (Oh, and you'll usually get it 
wrong the first time, so don't be sad.)


Re: Contracts or Exceptions?

2011-03-30 Thread Kai Meyer

On 03/30/2011 08:25 AM, Kagamin wrote:

Kai Meyer Wrote:


do all the checking before hand. Arrays are a good example. When not in
-release mode, array boundaries are checked upon every access to the
array, and an exception is thrown if access goes out of bounds. In
-release mode, if you go out of bounds you get a segfault.


No, you get a remote root vulnerability.


Sure, but the point is that arrays can be used in a way that performs as 
fast as possible, therefore it becomes the programmer's job to ensure 
that all access to the array is within bounds, which is faster than 
making the array check itself every time.


Re: Contracts or Exceptions?

2011-03-30 Thread Kai Meyer

On 03/29/2011 09:32 PM, Ali Çehreli wrote:

On 03/29/2011 03:40 PM, Kai Meyer wrote:

 > I was given two words of advice on exceptions:
 > "Use exceptions for the exceptional"
 > "Use exceptions only for the exceptional"

Those advices are given by wise people: they are wise only because they
leave the definition as vague as "exceptional." :)



Ya, now that I'm thinking about it a little more, we were talking about 
what sort of things you can do to increase performance. This was 
actually pretty far down the list, after considering things like 
profiling, improving algorithms, using built-in types instead of 
classes, ect. Exceptions are a little more expensive than condition 
statements.



And what do we do for the "not so exceptional"? Do we return error
codes? So the function implementation will be complicated and the caller
code will be complicated.


You're right. I would consider those complications only if the 
optimisation I'm after justifies them. For example, if our profiler 
indicates that the function is running slowly due to handling a lot of 
exceptions (which probably won't be the first thing the profiler finds 
is running slow), we could use conditional statements to speed things up 
a bit.


if (good data)
  do work
else
  report "can't do work"

Would be faster than:

try
  do work
catch
  report "can't do work"

I'll also add that the same person who gave me this advice also likes to 
say "Premature optimisation is the root of all evil."




Exceptions are a great tool to eliminate the need for error codes.

Here is what I follow:

- Functions have specific tasks to do; if those tasks cannot be
accomplished, the function must throw.

In some cases the function can continue, but that behavior must be
documented. For example, if an HTML library function is responsible for
making HTML headers, of which only the levels in the range of 1-6 are
valid, that function may throw when the level is outside of the valid
range, for in that case it cannot "make an HTML header"; or it can
document that if the level is outside of the range, 1 or 6 will be used.

- Catch exceptions only when there is a sensible thing to do at that
level: log an error, skip that operation, go back to the user with an
error code, take corrective action, etc.

Disclaimer: That is what I follow in C++ code. I don't have experience
with exception safety in D. I don't know issues that may be specific to D.

Ali




Thanks for your insight Ali :) I'm not sure D's exceptions are much 
different than C++'s. I think you're right on.


Re: How to spawn processes while keeping the parent process open ?

2011-04-04 Thread Kai Meyer

On 04/03/2011 07:31 AM, Tarun Ramakrishna wrote:

Hi,

Apparently std.process.exec (D2.052/windows) doesn't work the way the
documentation describes. It terminates the parent process. Is there a
way to keep the parent process open in D ? I also vaguely remember
seeing some mails on this list about an improved process library in D.

Any tips appreciated,
Thanks,
Tarun


I think exec is meant to replace the current running process with the 
new one. I think the one you want is either "shell" or "system".

http://www.digitalmars.com/d/2.0/phobos/std_process.html


Re: Array operation doesn't check array bounds

2011-04-04 Thread Kai Meyer

On 04/03/2011 05:06 PM, Jonathan M Davis wrote:

On 2011-04-03 04:10, simendsjo wrote:

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

int[4] b;
assert(b == [0,0,0,0]);
b = a[] * 3; // oops... a[] * 3 takes element outside a's bounds
assert(b[$-1] == 0); // fails.. last element is *(a.ptr+3) * 3


Array bounds checking is done on code which is not compiled with the -
noboundscheck flag and which is either not built with -release or is @safe.

I assume that you're not compiling with -noboundscheck (which turns off all
array bounds checking). So, you're likely compiling with -release on code
which isn't @safe. @system is the default, so unless you've marked your code
@safe or you're not compiling with -release, I wouldn't expect there to be any
bounds checking. If you want to guarantee that there's always bounds checking,
then you need to mark your code @safe and not use -noboundscheck. However,
given how little of Phobos is currently @safe or @trusted, odds are that
trying to mark your code @safe will get _really_ annoying at this point. And
to fix that, we'd likely need conditional @safe and conditional @trusted for
the same reasons that we need conditional pure. And those haven't been taken
care of yet (there isn't even an official plan to as far as I know - though
hopefully there will be).

- Jonathan M Davis


This is the really verbose answer to the question I thought you were 
asking as well.


I think this problem is better expressed like this:


import std.stdio;
void main()
{
int[] a = [1,2,3];
int[4] b;
int[4] c = [0,1,2,3];
int[5] d = [0,1,2,3,4];
assert(b == [0,0,0,0]);
b = c[] * 3; // like foreach(val; c) b.append(val*3);
writef("%s %s %s\n", a, b, c);
b = a[] * 3; // No error
writef("%s %s %s\n", a, b, c);
b = a[]; // object.Exception: lengths don't match for array copy
writef("%s %s %s\n", a, b, c);
writef("%s\n", a[] * 3); // bounds.d(15): Error: Array operation 
a[] * 3 not implemented

assert(b[$-1] == 0);
}

I think bearophile addressed this, but I can't quite tell.

So now I'm curious, why does the multiply operation break the bounds 
check? Also, why does it fail to print? The result can be stored in 
another array, so I would think it would print.




time_t to simple date string conversion

2011-04-05 Thread Kai Meyer
I'm reading documentation on std.datetime, and it appears there are 
added features that I don't have in 2.51 (Linux). Did features like 
'SysTime' get added after 2.51?


Does anybody have a one-liner to convert a time_t to a date string that 
should work for me?


-Kai Meyer


Re: time_t to simple date string conversion

2011-04-05 Thread Kai Meyer

On 04/05/2011 03:59 PM, Jonathan M Davis wrote:

I'm reading documentation on std.datetime, and it appears there are
added features that I don't have in 2.51 (Linux). Did features like
'SysTime' get added after 2.51?

Does anybody have a one-liner to convert a time_t to a date string that
should work for me?


std.datetime was completely revamped with 2.52. What existed from in 2.51 has
little to do with what's in 2.52, and it wasn't even publically documented
anyway. So, if you're using 2.51, you're still stuck using std.date, which is
rather broken. I'd definitely recommend that you upgrade to 2.52 if you're
still using 2.51.

If you're using 2.51 and for some reason can't upgrade, then I'd recommend
that you just use the standard C functions. That would be less error-prone
than trying to use std.date, which is scheduled for deprecation anyway.

And assuming that you can't upgrade, if the reason for that is because you're
installed dmd with your distro, I'd recommend uninstalling it and just
downloading the zip file from the main site. Your distro is not likely to keep
dmd as up-to-date as downloading it yourself will, and it improves too quickly
to stick with a version which is months old. It's easy to use the zip. All you
have to do is unzip it to wherever you want to unzip it, and the add
/path/to/unzipped/dmd2/linux/bin to your path, and it works (unless you're on
a 64-bit box, then you need to install certain 32-bit packages, but it's a
fairly short list, and if your distro actually includes a package for dmd,
then it should be easy to figure out what they are by looking at the
dependencies for that package).

In any case, prior to dmd 2.52, there effectively was no std.datetime. The
date stuff was the rather buggy std.date, which is now scheduled for
deprecation. So, either you need to upgrade to 2.52, use std.date, or use the
standard C functions.

- Jonathan M Davis



So who do I bug to update the RPM build on the Downloads page? The zip 
and windows versions are 2.52, but the Linux RPM version is 2.51.


Re: time_t to simple date string conversion

2011-04-05 Thread Kai Meyer

On 04/05/2011 03:40 PM, Steven Schveighoffer wrote:

On Tue, 05 Apr 2011 17:24:11 -0400, Kai Meyer  wrote:


I'm reading documentation on std.datetime, and it appears there are
added features that I don't have in 2.51 (Linux). Did features like
'SysTime' get added after 2.51?

Does anybody have a one-liner to convert a time_t to a date string
that should work for me?


auto t = time();
auto systime = SystemTime(unixTimeToStdTime(t)); // to system time

from there, you have many options to create the right string. You can
start with just writing it (via toString):

writeln(systime);

There's also:

http://www.digitalmars.com/d/2.0/phobos/std_datetime.html#toSimpleString
http://www.digitalmars.com/d/2.0/phobos/std_datetime.html#toISOString
http://www.digitalmars.com/d/2.0/phobos/std_datetime.html#toISOExtendedString


and doing it directly:

writefln("%s/%s/%s", t.month, t.day, t.year);

Don't see a way to print the month in text format, but maybe I'm
overlooking it.

-Steve


Ok, that works. Thanks :)


Re: "Before and after" in contracts?

2011-04-11 Thread Kai Meyer

On 04/11/2011 06:05 AM, Magnus Lie Hetland wrote:

I'd like to write a contract for a method to ensure that a given
attribute does not decrease when calling the method. In order to do
that, I need to store the "before" value, and compare it to the after
value.

My first intuition was to declare a variable in the in-block, and then
access that in the out-block. No dice, it seems. I tried declaring one
in the body (with a version(unittest) qualifier). Still no dice. I ended
up using a separate *attribute* for this, which seems particularly ugly
to me.

Is it philosophically "wrong" to write stateful "before/after" contracts
like this? If not, can it be done in a less ugly manner? (Or should I
just learn to like this way of doing it?)



I don't know if I can speak to the philosophical points here, but you 
can put your attribute declarations in a version block, and as long as 
the usage of that attribute is only used when that version is used, you 
should be fine.


Re: Semicolon can be left out after do-while

2011-04-13 Thread Kai Meyer

On 04/13/2011 07:44 AM, Emil Madsen wrote:

On 13 April 2011 14:36, Steven Schveighoffer mailto:schvei...@yahoo.com>> wrote:

On Tue, 12 Apr 2011 18:00:40 -0400, spir mailto:denis.s...@gmail.com>> wrote:

On 04/12/2011 11:51 PM, Steven Schveighoffer wrote:

On Tue, 12 Apr 2011 17:21:57 -0400, spir
mailto:denis.s...@gmail.com>> wrote:

On 04/12/2011 09:21 PM, Steven Schveighoffer wrote:

int main(){
int a,b;
do{
scanf("%d %d",&a,&b);
}while(ahttp://www.digitalmars.com/d/2.0/statement.html#DoStatement)
[...]
I think the grammar should be changed...


yop!

This is almost as bad as go's
requirement for if statement opening block to be on
the same line...


why? I like Go's syntactuc diffs. (except for its
"multi-for")


in Go, this:

if(x)
{
gosWriteRoutineThatIDontKnowTheSyntaxOf("hello")
}

is equivalent to this in D:

if(x)
{
}

writeln("hello");

This is frankly unforgivable IMO.

Of course it's fixable, but the attitude that "the coder
should know better"
doesn't really make me comfortable with it. And I hate the
"brace on the same
line" format (but this of course is not a real argument
against it).


Oh, that's what you meant! I find this a Good Thing, in that it
enforces one bracing style (the right one, that does not eats
one more line for just a '{').


No, it doesn't enforce anything.  The above compiles and runs.  What
it does is introduce subtle bugs.

The way to fix it is to make the above an error.


About knowing or not about this (non/mis/-)feature, it's written
down, and clearly, in all Go docs I've read. And one cannot miss
it for very long anyway ;-)


I know that if(xyz); is not *ever* what I meant, but in C it
compiles.  However, in D, it tells me I shouldn't do that.  What
results is less bugs because I can't make that mistake without the
compiler complaining.

I'm not saying that the spec isn't well defined, or the manual isn't
clear, what I'm saying is, the attitude reflected in the rule is
that greater burden is put on the developer to make sure they follow
the rules without compiler enforcement.  It makes me want to not use
Go.  And in fact, I will probably never use it as long as this rule
is in place.


Maybe, if not done already, a line starting with an opening
brace should generate a parsing error.


Typically this is used to create a new scope in C/D/Java/C#.  This
allows declaring temporary variables, not sure how it is in Go, but
I'd assume something similar.

-Steve



Does D throw an error at; if(expression && expression)*; *or only at
if(expression);
Because you could actually use the first one, alike this:

#include 

bool test()
{
 printf("test\n");
 return false;
}

bool test2()
{
 printf("test2\n");
 return true;
}

int main()
{
 if(test() && test2());
}

Output = "test"
if test returns true, then: Output = "test" + "test2"

Simply because its conditional, and if the first one fails, why bother
evaluating the rest?

--
// Yours sincerely
// Emil 'Skeen' Madsen


I would argue that the more correct way to do this would be to separate 
the statements that are used in the condition from the statements that 
are not used in the condition.


if(test())
test2();

Since test2's return statement isn't used for anything means to me that 
it doesn't belong in the conditional statement.


Re: std.regex with multiple matches

2011-04-21 Thread Kai Meyer

On 04/21/2011 11:43 AM, David Gileadi wrote:

I was using std.regex yesterday, matching a regular expression against a
string with the "g" flag to find multiple matches. As the example from
the docs shows (BTW I think the example may be wrong; I think it needs
the "g" flag added to the regex call), you can do a foreach loop on the
matches like:

foreach(m; match("abcabcabab", regex("ab")))
{
writefln("%s[%s]%s", m.pre, m.hit, m.post);
}

Each match "m" is a RegexMatch, which includes .pre, .hit, and .post
properties to return ranges of everything before, inside, and after the
match.

However what I really wanted was a way to get the range between matches,
i.e. since I had multiple matches I wanted something like m.upToNextMatch.

Since I'm not very familiar with ranges, am I missing some obvious way
of doing this with the existing .pre, .hit and .post properties?

-Dave


There's two ways I can think of off the top of my head.

I don't think D supports "look ahead", but if it did you could match 
something, then capture the portion afterwards (in m.captures[1]) that 
matches everything up until the look ahead (which is what you matched in 
the first place).


Otherwise, you could manually capture the ranges like this (captures the 
first word character after each word boundry, then prints the remaining 
portion of the word until the next word boundary followed by a word 
character):


import std.stdio;
import std.regex;

void main()
{
size_t last_pos;
size_t last_size;
string abc = "the quick brown fox jumped over the lazy dog";
foreach(m; match(abc, regex(r"\b\w")))
{
writefln("between: '%s'", abc[last_pos + last_size..m.pre.length]);
writefln("%s[%s]%s", m.pre, m.hit, m.post);
last_size = m.hit.length;
last_pos = m.pre.length;
}
writefln("between: '%s'", abc[last_pos + last_size..$]);
}
// Prints:
// between: ''
// [t]he quick brown fox jumped over the lazy dog
// between: 'he '
// the [q]uick brown fox jumped over the lazy dog
// between: 'uick '
// the quick [b]rown fox jumped over the lazy dog
// between: 'rown '
// the quick brown [f]ox jumped over the lazy dog
// between: 'ox '
// the quick brown fox [j]umped over the lazy dog
// between: 'umped '
// the quick brown fox jumped [o]ver the lazy dog
// between: 'ver '
// the quick brown fox jumped over [t]he lazy dog
// between: 'he '
// the quick brown fox jumped over the [l]azy dog
// between: 'azy '
// the quick brown fox jumped over the lazy [d]og
// between: 'og'

If you replace '\b\w' with '\s' it should help illuminate the way it works:

between: 'the'
the[ ]quick brown fox jumped over the lazy dog
between: 'quick'
the quick[ ]brown fox jumped over the lazy dog
between: 'brown'
the quick brown[ ]fox jumped over the lazy dog
between: 'fox'
the quick brown fox[ ]jumped over the lazy dog
between: 'jumped'
the quick brown fox jumped[ ]over the lazy dog
between: 'over'
the quick brown fox jumped over[ ]the lazy dog
between: 'the'
the quick brown fox jumped over the[ ]lazy dog
between: 'lazy'
the quick brown fox jumped over the lazy[ ]dog
between: 'dog'


Re: How to get the dang thing to work (Was: Linux: How to statically link against system libs?)

2011-04-27 Thread Kai Meyer

On 04/26/2011 02:28 PM, Nick Sabalausky wrote:

Ok, so I guess statically linking against the stuff isn't the way to go, and
apparently DLL hell is worse on linux. Sooo...What do I do?

In the other thread, Spacen said: "The way to do this is to link against the
oldest libc you need to
support, thus making the binaries forward compatible"

I know my way around Linux as a user, but with deeper system stuff like that
I'm pretty much lost. I don't have a clue how to do what Spacen suggests or
how to determine what version of libc I need. Can anyone help me out with
that?




Can you backup, and help me understand what the first problem was? The 
one you thought was solvable by statically linking against glibc?


-Kai Meyer


Re: How to get the dang thing to work (Was: Linux: How to statically link against system libs?)

2011-04-27 Thread Kai Meyer

On 04/27/2011 11:51 AM, Nick Sabalausky wrote:

"Kai Meyer"  wrote in message
news:ip9bro$1lak$1...@digitalmars.com...

On 04/26/2011 02:28 PM, Nick Sabalausky wrote:

Ok, so I guess statically linking against the stuff isn't the way to go,
and
apparently DLL hell is worse on linux. Sooo...What do I do?

In the other thread, Spacen said: "The way to do this is to link against
the
oldest libc you need to
support, thus making the binaries forward compatible"

I know my way around Linux as a user, but with deeper system stuff like
that
I'm pretty much lost. I don't have a clue how to do what Spacen suggests
or
how to determine what version of libc I need. Can anyone help me out with
that?




Can you backup, and help me understand what the first problem was? The one
you thought was solvable by statically linking against glibc?



It was the thread "D CGI test: linux.so.2: bad ELF interpreter: No such file
or directory".

Reposted here:

-

I've made a little test CGI app:

import std.conv;
import std.stdio;

void main()
{
  auto content = "Hello world";
  auto headers =
`HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: `~to!string(content.length);

  while(readln().length>  1) {}

  writeln(headers);
  writeln();
  writeln(content);
}

Works on Windows command line and through IIS. And it works on my Kubuntu
10.6 (CORRECTION: It's v10.04) command line. But if I copy the executable
from my Kubuntu box to my
web host's Debian server (CORRECTION: It's Red Hat, but there is another
server I'd like to also run on that is Debian): Running it through Apache
gives me a 500, and running it directly with ssh gives me:

linux.so.2: bad ELF interpreter: No such file or directory

I assume that error message is the cause of the 500 (can't tell for sure
because the 500 isn't even showing up in my Apache error logs). But I'm not
enough of a linux expert to have the slightest clue what that error message
is all about. I don't need to actually compile it *on* the server do I? I
would have thought that all (or at least most) Linux distros used the same
executable format - especially (K)Ubuntu and Debian.





Ya, glibc tries very hard to be forward compatible, but it is quite 
often not very backwards compatible. Meaning, if you build on an older 
system, it should run on newer systems (forward compatible.) But if you 
build on newer systems, it's not always going to run on older systems 
(backwards compatible.)


The best solution is to either use LSB (which is a big hoary mess to get 
into, and isn't fully supported everywhere, and I don't think there's 
anything you can do to D to make it LSB compatible), build on the oldest 
distro, or build on each distro.


Ideally, for performance, you should build a binary for each distro. You 
should build one for Ubuntu separately from Debian, but if you don't 
ahve the time, building on Debian will likely run on Ubuntu, but not 
visa versa. Statically linking or dynamic linking isn't the answer, it's 
forward and backwards compatibility.


Personally, I build rpms for both RHEL/CentOS and Fedora on a 
semi-regular basis, and I usually build one to distribute on RHEL/CentOS 
separate from a build to distribute on Fedora.


Re: correct way to create boiler plate code

2011-05-16 Thread Kai Meyer

On 05/16/2011 01:08 PM, dmerrio wrote:

I am parsing some formulas from a spreadsheet file. To duplicate
the behavior of the spreadsheet functions, I am having to create a
lot of boiler plate code that maps from the spreadsheet functions
to the built-in functions. Mixin would seem to allow me to
automate the boiler-plate creation, but i am not utilizing it
correctly. What is the correct to call Mixin in this situation, or
is their a better way to create the boiler-plate code?

For background, i am new to D. D is my second language with my
primary experience being a script kiddie in Excel VBA, so take it
slow, please.



import main; //class definition of rng
import std.math; //trig functions
import std.conv; //to!double
import std.string; //toupper

double transFunc(alias transedentalFunc)(rng aRng){
try{return(transedentalFunc(aRng.getCellValue().coerce!
(double)));} //cellValue stored as a Variant
catch{return(transedentalFunc(to!double(aRng.getCellValue
().coerce!(string;} //replicate spreadsheet behavior and
convert to a number
}

//Example 1 of boilerplate code
double SIN(double aReal){return(sin(aReal));}
double SIN(string aStr){return(sin(to!double(aStr)));}
double SIN(rng aRng){return(transFunc!(sin)(aRng));}

//Example 2 of boilerplate code
double COS(double aReal){return(cos(aReal));}
double COS(string aStr){return(cos(to!double(aStr)));}
double COS(rng aRng){return(transFunc!(cos)(aRng));}

string[] funcs = ["tan"];
void createFuncs(){
foreach(func; funcs){
mixin("double " ~ toupper(func) ~ "(double aReal)
{return(" ~ func ~ "(aReal));}");
}
}

calling mixin a compile time has the following error...

Error   1   Error: variable func cannot be read at compile time
C:\D\SVNProjects\trunk\xcellD\xcell1\trig.d 22


thanks for your help


This works:

//import main; //class definition of rng
import std.math; //trig functions
import std.conv; //to!double
import std.string; //toupper
import std.stdio;

void main()
{
mixin(createFunc!("sin"));
mixin(createFunc!("cos"));
mixin(createFunc!("tan"));
writeln(SIN(0)); // 0
writeln(COS(0)); // 1
writeln(TAN(0)); // 0
return;
}
template createFunc(string func){
const char[] createFunc = "double " ~ toupper(func) ~ "(double aReal)
{return(" ~ func ~ "(aReal));}";
}

Stole it from http://www.digitalmars.com/d/2.0/mixin.html

I don't think there's a way to use an array of strings, since (as 
pointed out by others and your error message) that mixins are done 
compile-time and foreach are done (mostly) at run-time.


dmd 32bit

2011-06-07 Thread Kai Meyer
How do I generate 32bit binaries with dmd64 (2.053) on Linux? I can't 
find the flag for it.


-Kai Meyer


Re: dmd 32bit

2011-06-07 Thread Kai Meyer

On 06/07/2011 01:39 PM, Kai Meyer wrote:

How do I generate 32bit binaries with dmd64 (2.053) on Linux? I can't
find the flag for it.

-Kai Meyer


Nevermind, found it.
http://digitalmars.com/d/2.0/dmd-linux.html

I kept putting a space between -m and 32 :(


Re: Is it reasonable to learn D

2011-06-07 Thread Kai Meyer

On 06/07/2011 01:47 PM, Fabian wrote:

Dear D Community,
is it reasonable to learn D?
I've found a lot of good points for D but I've found a lot of negative
points too. I believe that I needn't to list all the point for D but I
want to give a few examples against learning D I've read in some German
and English boards:

- The D compiler has only bad code optimization
- There are no maintained GUI libraries
- The development of the compiler is very slow
- Only a small community
=> no real German community

So I ask you - Is it reasonable to learn D?
I'm looking forward to your answers.

Greetings Fabian

PS: If you want to contact me you are allowed to write an Email to me.
contact-...@freemail.de


I think your question is highly subjective. D is still a young language, 
which I think accounts for all of the negative feedback you've listed.


Re: An effort at creating a free ebook for learning D

2011-06-20 Thread Kai Meyer

On 06/20/2011 03:46 PM, Jose Armando Garcia wrote:

On Mon, Jun 20, 2011 at 6:30 PM, Jimmy Cao  wrote:

I helped with something last summer: an attempt at creating a wikibook for
D.  At that time, my D skills were very bad, so I had to concentrate on
learning D first before contributing to more lessons.
One thing that has always bothered me is, there aren't many good *free*
ebooks for learning D.
Well, I'll try to continue what I had started less than a year ago.  I'll
probably make many mistakes while writing, so can you guys check on my
progress once in a while?
http://en.wikibooks.org/wiki/D_(The_Programming_Language)/d2/Lesson_1/Phobos
What do you think?
Thanks.


Good idea. Small notes:

*) In the tip section 'write("Hello\n") and writeln("Hello")' are not
the same. writeln and writefln flush. write doesn't.
*) Not sure if you want to also encourage portable code. "\n" should
be replace with newline which I think it is define in std.string.


I wrote some code a while back that was intended to be portable (between 
windows and linux anyway). I used 'writef("Hello\n");' a lot, and those 
always printed correctly on windows. Does writef do something different 
than write with the '\n' character?


-Kai Meyer


Re: readf with strings

2011-06-22 Thread Kai Meyer

On 06/22/2011 09:30 AM, Ali Çehreli wrote:

On Wed, 22 Jun 2011 14:57:57 +, GreatEmerald wrote:


This should be a very elementary question. How do you get a string off
stdin? Or an integer, or a boolean, for that matter? If I use this:

   float MyFloat;
   string MyString;
   readf("%f",&MyFloat);
   writeln(MyFloat);
   readf("%s",&MyString);
   writeln(MyString);

I get the float printed correctly, but when it asks to input the string,
whatever I input gets ignored - I can't reach the writeln part in any
way and I have to forcibly close the program. The same thing is with
ints - if I enter an int, it acts as if I didn't enter anything at all.
But floats work fine for some reason. Any thoughts about what is
happening there?

I'm using openSUSE 11.4 and DMD 2.053.


Reading from an input stream is sometimes confusing.

Things to remember:

- Use %s for any type unless there is reason not to

- The line terminator from the previous entry is still in the input. (You
may call readf(" ") to flush those white space characters. (I've just
discovered this.))

- string can hold any character including space and the line terminator.
That's why pressing the Enter doesn't terminate reading a string.

- Use a space character before any format specifier to ignore zero or
more whitespace characters before the previous input: " %s".

- To read a string (actually a line), use chomp(readln())

- I don't know whether this is intended and I don't think that we should
routinely use this: The EOF (Ctrl-D on Unix consoles, Ctrl-Z on Windows)
terminates reading the string but strangely not the entire input.

import std.stdio;
import std.string;

void main()
{
 float MyFloat;
 readf(" %s",&MyFloat);
 writeln(MyFloat);

 readf(" ");

 string MyString = chomp(readln());
 writeln(MyString);
}

Ali


Remember that readf is reading characters, and converting them to types 
for you. I've just gotten in the habbit of reading in the string, and 
then parsing the string on my own. Readf doesn't grant me anything 
special that I can't do on my own. It's easy enough to do something like 
this:


[kai.meyer@kai-rhel6 sandbox]$ cat d_read.d
import std.stdio;
import std.string;
import std.conv;

void main()
{
string[] buffer;
int a;
float b;
string c;
buffer = chomp(readln()).split(" ");
a = to!(int)(buffer[0]);
b = to!(float)(buffer[1]);
c = buffer[2..$].join(" ");
writef("Read in: '%d' '%f' '%s'\n", a, b, c);
}


If I type:
1 1.3 this is a string

On the command line after the execution, I get this back:
Read in: '1' '1.30' 'this is a string'

It's not very stream-ish, because readln breaks on a new line. You could 
call the "buffer = chomp..." line again if (buffer.length == 0) before 
you attempt another conversion.




Re: readf with strings

2011-06-23 Thread Kai Meyer

On 06/23/2011 02:27 AM, Dainius (GreatEmerald) wrote:

I have a related enhancement request since lot of time:
http://d.puremagic.com/issues/show_bug.cgi?id=4716

Bye,
bearophile



That's exactly what I'd like to see. Voted.

After all, D is created with practicality in mind, and doing all that
parsing is the opposite of what it's trying to achieve.


The goal here is to have semantics for "Read an int from STDIN." I think 
the difficulty here is this really *should* be "Read a T from a stream." 
In C++, we have the stream operators ">>" and "<<". I really really 
really really miss these. I would love to have my stream operators back 
(and then implement the operators for classes and structs.) I think that 
"a = stdin.type_read!int();" or "std.type_read!int(&a);" would go a long 
way in getting there, as long as we could extend the template. I don't 
like the way python takes input from STDIN with raw_input() and input(). 
I'm not opposed to having a language support those semantics, but I 
would rather have a generic stream reader that does the conversion to a 
type for me that allows me to extend the conversion to include my own types.


Re: Any way to get the name of a function?

2011-07-07 Thread Kai Meyer

On 07/06/2011 08:47 PM, Andrej Mitrovic wrote:

void foo(){};
void bar(){};

void main()
{
 auto funcs = [&foo,&bar];
}

I'm using this in a foreach loop and invoking each function with some
predefined arguments. But I'd also like to extract the name of each
function because each function does some image processing and then I
save that image to disk.

Basically I want to do:

 foreach (func; funcs)
 {
 func(arguments..);
 writeToFile(func.stringof);
 }

Obviously I can't use arrays since they don't hold any name
information, they just store the pointers.

Can I use tuples somehow? The functions are predefined, I just need to
iterate through all of them and call them and extract their name.


I assume the function signatures are all the same? Then you can do an 
associative array:


import std.stdio;
int func1(int a) {return a + 1;}
int func2(int a) {return a + 2;}
int func3(int a) {return a + 3;}
void main()
{
int function (int)[string] funcs = ["func1":&func1, \
"func2":&func2, "func3":&func3];
foreach(name, func; funcs)
writef("%s %d\n", name, func(1));
}


Perhaps a mixin would be helpful to limit cut-and-paste issues. If they 
are methods that are part of a class, you would need to declare them as 
"int delegate (int)[string] funcs".


Encoding help

2011-07-11 Thread Kai Meyer
I have a need to be able to read/write a win32 UNICODE file from a linux 
machine. I've heard D has some great encoding libraries. I'm struggling 
to get some simple reads done. How can I read a line from a UTF-16LE 
file on a linux box in D? I'm running dmd 2.053


-Kai Meyer


Re: Encoding help

2011-07-11 Thread Kai Meyer

On 07/11/2011 10:56 AM, Kai Meyer wrote:

I have a need to be able to read/write a win32 UNICODE file from a linux
machine. I've heard D has some great encoding libraries. I'm struggling
to get some simple reads done. How can I read a line from a UTF-16LE
file on a linux box in D? I'm running dmd 2.053

-Kai Meyer


Ok, fine. So I can't put readline in a foreach loop. Got it...

-Kai Meyer


hex string to int?

2011-07-11 Thread Kai Meyer

Is there a built-int ton convert a hex string like "0x0A" to the int "10"?


Re: Frontend and backend communication

2011-07-28 Thread Kai Meyer

On 07/27/2011 04:40 PM, Dainius (GreatEmerald) wrote:

No no. It's the other way round. Shuffle() is in the library
(backend). PlaySound() is in the executable (frontend). Since I don't
want the library to be dependent on any sound libraries, I can't have
PlaySound() in it. And there is no other way that I can think of to
execute PlaySound() just at the end of Shuffle() without capturing
events (since Shuffle() itself is called by a whole lot of different
functions across the library, and not from the executable itself).



One reason for the confusing responses is that in your original post you 
said:

"a frontend (a library)", "a backend (an
executable)", "Shuffle() is a backend function", and "PlaySound()
is a frontend one".

Frontend->library->Shuffle()
Backend->executable->PlaySound()

Then in this email, you say:

"Shuffle() is in the library (backend)", and "PlaySound() is in the 
executable (frontend)"


Backend->library->Shuffle()
Frontend->executable->PlaySound()

I'm assuming that this is the more correct version.

Depending on what PlaySound needs, you can pass the function as a 
parameter to Shuffle().


Re: Frontend and backend communication

2011-07-28 Thread Kai Meyer

On 07/28/2011 01:18 AM, Dainius (GreatEmerald) wrote:

Hmm, there are still a whole lot of functions that call Shuffle(), so
it might not be ideal. However, this gives me an idea - if a pointer
to a function can be a parameter, can it be a global variable? In that
case, the frontend would indeed be able to overwrite the function that
the backend calls by simply altering that pointer.


Yes, you could create a "function table" and keep a list of all the 
functions that need to be called. You can then alter the behavior of one 
method at runtime with out having to pass a function as a parameter. Of 
course, global variables are tricky things, especially whe you're 
threaded. It's probably simplest to just pass the function pointer as a 
parameter to Shuffle(). If Shuffle() indeed has multiple entry points, 
and they all fight to have their version of PlaySound() run at the end 
of Shuffle(), then you may run into problems.


-Kai Meyer


Re: Hexadecimal string to integer

2011-08-04 Thread Kai Meyer

On 08/03/2011 10:44 AM, Stijn Herreman wrote:

On 3/08/2011 2:32, Johann MacDonagh wrote:

On 8/2/2011 8:17 PM, Stijn Herreman wrote:

std.conv does not support conversion from a hexadecimal string to an
integer. Is there a technical reason for this limitation?

This is the best I could do, can it be improved still?
int i = to!int(parse!float("0x1ap0"));


parse!int("1a", 16);

I tried multiple combinations but not that one, thanks.


I am doing:
to!(int)(BigInt("0x1a").toInt());
toInt actually returns a long:
http://www.d-programming-language.org/phobos/std_bigint.html

It's kinda frustrating, but it's there.


Re: Minimum value in a range

2011-08-04 Thread Kai Meyer

On 08/02/2011 06:03 AM, Andrej Mitrovic wrote:

import std.algorithm;

void main()
{
 auto x = min([1, 2, 3]);  // x would be 1
}

min() isn't equipped to do this on a single range. What can I use
instead? I haven't had my coffee yet. :)


Looking at std.algorithm, I think what you really want is minCount:
http://www.d-programming-language.org/phobos/std_algorithm.html#minCount



Multi-file byte comparison tool. What would you have done differently?

2011-08-04 Thread Kai Meyer
I have a need for detecting incorrect byte sequences in multiple files 
(>2) at a time (as a part of our porting effort to new platforms.) 
Ideally the files should be identical for all but a handful of byte 
sequences (in a header section) that I can just skip over. I thought 
this would be a fun exercise for my D muscles. I found success creating 
a dynamic array of structs to keep information about each file passed in 
via command-line parameters. I'll append the code at the end (and I'm 
sure it'll get mangled in the process...)


(I'm not one for coming up with creative names, so it's SOMETHING) Then 
I loop around a read for each file, then manually run a for loop from 0 
to BLOCK_SIZE, copy the size_t value into a new dynamic array (one for 
each of the files opened), and run a function to ensure all values in 
the size_t array are the same. If not, I compare each ubyte value (via 
the byte_union) to determine which bytes are not correct by adding each 
byte to a separate array, and comparing each value in that array, 
printing the address and values of each bad byte as I encounter them.


This appears to work great. Some justifications:
I used size_t because I'm under the impression it's a platform specific 
size that best fits into a single register, thus making comparisons 
faster than byte-by-byte.

I used a union to extract the bytes from the size_t
I wanted to create a SOMETHING for each file at run-time, instead of 
only allowing a certain number of SOMETHINGS (either hard coded, or a 
limit).
Originally I wrote my own comparison function, but in my search for 
something more functional, I tried out std.algorithm's count. Can't say 
I can tell if it's better or worse.


Features I'll probably add if I have to keep using the tool:
1) Better support for starting points and bytes to read.
2) Threshold for errors encountered, perferrably managed by a 
command-line argument.

3) Coalescing error messages in sequential byte sequences.

When I run the program, it's certainly I/O bound at 30Mb/s to an 
external USB drive :).


So the question is, how would you make it more D-ish? (Do we have a term 
analogous to "pythonic" for D? :))



Code:

import std.stdio;
import std.file;
import std.conv;
import std.getopt;
import std.algorithm;

enum BLOCK_SIZE = 1024;
union byte_union
{
size_t val;
ubyte[val.sizeof] bytes;
}
struct SOMETHING
{
string file_name;
size_t size_bytes;
File fd;
byte_union[BLOCK_SIZE] bytes;
}

void main(string[] args)
{
size_t bytes_read;
size_t bytes_max;
size_t size_smallest;
size_t[] comp_arr;
SOMETHING[] somethings;
getopt(args,
"seek", &bytes_read,
"bytes", &bytes_max
);
if(bytes_max == 0)
bytes_max = size_t.max; // Limit on the smallest file size
else
bytes_max += bytes_read;
//bytes_read = bytes_read - (bytes_read % (BLOCK_SIZE * 
SOMETHING.size_bytes.sizeof));

size_smallest = bytes_max;
somethings.length = args.length - 1;
comp_arr.length = args.length - 1;
for(size_t i = 0; i < somethings.length; i++)
{
somethings[i].file_name = args[i + 1];
somethings[i].size_bytes = getSize(somethings[i].file_name);
stderr.writef("Opening file: %s(%d)\n", 
somethings[i].file_name, somethings[i].size_bytes);

somethings[i].fd = File(somethings[i].file_name, "r");
somethings[i].fd.seek(bytes_read);
if(somethings[i].fd.tell() != bytes_read)
{
stderr.writef("Failed to seek to position %d in %s\n", 
bytes_read, args[i + 1]);

}
// Pick the smallest file, or the limit
size_smallest = min(size_smallest, somethings[i].size_bytes);
}
// Check file sizes
for(size_t i = 0; i < somethings.length; i++)
comp_arr[i] = somethings[i].size_bytes;
writef("count: %s\n", count(comp_arr, comp_arr[0]));
if(count(comp_arr, comp_arr[0]) != comp_arr.length)
{
stderr.writef("Files are not the same size!");
foreach(s; somethings)
stderr.writef("[%s:%d]", s.file_name, s.size_bytes);
stderr.writef("\n");
}

// While bytes_read < size of smallest file
size_t block_counter;
while(bytes_read < size_smallest)
{
// Read bytes
//stderr.writef("tell: ");
for(size_t i = 0; i < somethings.length; i++)
{
//stderr.writef("Reading file %s\n", file_names[i]);
//stderr.writef("%d ", somethings[i].fd.tell());
//if(somethings[0].fd.tell() + BLOCK_SIZE * 
SOMETHING.size_bytes.sizeof > somethings[0].size_bytes)

//{
//stderr.writef("Warning, reading last block : 
[%d:%d:%d]\n", somethings[0].fd.tell(), somethings[0].size_bytes, 
somethings[0].fd.tell() + BLOCK_SIZE * SOMETHING.size_bytes.sizeof);

//for(size_t j = 0; j < somethings[i].bytes.length; j++)
//{
//somethings[i].bytes[i].val = 0;
   

Re: Minimum value in a range

2011-08-05 Thread Kai Meyer

On 08/04/2011 07:54 PM, bearophile wrote:

Kai Meyer:


Looking at std.algorithm, I think what you really want is minCount:
http://www.d-programming-language.org/phobos/std_algorithm.html#minCount


It's a bad design.

Bye,
bearophile


minCount is, or the usage of minCount in his particular problem?


Re: Multi-file byte comparison tool. What would you have done differently?

2011-08-05 Thread Kai Meyer

On 08/04/2011 05:03 PM, Timon Gehr wrote:

Kai Meyer wrote:

So the question is, how would you make it more D-ish? (Do we have a term
analogous to "pythonic" for D? :))


An easy first step to improve the D-Factor would be to replace all these for 
loops
with foreach loops and ref foreach loops.

-Timon


I like D-Factor :)

I haven't done foreach(ref s; somethings) before. Interesting, thanks :)


Re: Multi-file byte comparison tool. What would you have done differently?

2011-08-05 Thread Kai Meyer

On 08/05/2011 03:02 AM, Pelle wrote:

On Fri, 05 Aug 2011 00:25:38 +0200, Kai Meyer  wrote:


I have a need for detecting incorrect byte sequences in multiple files
(>2) at a time (as a part of our porting effort to new platforms.)
Ideally the files should be identical for all but a handful of byte
sequences (in a header section) that I can just skip over. I thought
this would be a fun exercise for my D muscles. I found success
creating a dynamic array of structs to keep information about each
file passed in via command-line parameters. I'll append the code at
the end (and I'm sure it'll get mangled in the process...)

(I'm not one for coming up with creative names, so it's SOMETHING)
Then I loop around a read for each file, then manually run a for loop
from 0 to BLOCK_SIZE, copy the size_t value into a new dynamic array
(one for each of the files opened), and run a function to ensure all
values in the size_t array are the same. If not, I compare each ubyte
value (via the byte_union) to determine which bytes are not correct by
adding each byte to a separate array, and comparing each value in that
array, printing the address and values of each bad byte as I encounter
them.

This appears to work great. Some justifications:
I used size_t because I'm under the impression it's a platform
specific size that best fits into a single register, thus making
comparisons faster than byte-by-byte.
I used a union to extract the bytes from the size_t
I wanted to create a SOMETHING for each file at run-time, instead of
only allowing a certain number of SOMETHINGS (either hard coded, or a
limit).
Originally I wrote my own comparison function, but in my search for
something more functional, I tried out std.algorithm's count. Can't
say I can tell if it's better or worse.

Features I'll probably add if I have to keep using the tool:
1) Better support for starting points and bytes to read.
2) Threshold for errors encountered, perferrably managed by a
command-line argument.
3) Coalescing error messages in sequential byte sequences.

When I run the program, it's certainly I/O bound at 30Mb/s to an
external USB drive :).

So the question is, how would you make it more D-ish? (Do we have a
term analogous to "pythonic" for D? :))


Code:

import std.stdio;
import std.file;
import std.conv;
import std.getopt;
import std.algorithm;

enum BLOCK_SIZE = 1024;
union byte_union
{
size_t val;
ubyte[val.sizeof] bytes;
}
struct SOMETHING
{
string file_name;
size_t size_bytes;
File fd;
byte_union[BLOCK_SIZE] bytes;
}


I would use TypeNames and nonTypeNames, so, blockSize, ByteUnion,
Something, sizeBytes, etc.

I haven't used TypeNames or nonTypeNames. Do have some reference 
material for me? Searching http://www.d-programming-language.org/ didn't 
give me anything that sounds like what you're talking about.

void main(string[] args)
{
size_t bytes_read;
size_t bytes_max;
size_t size_smallest;
size_t[] comp_arr;
SOMETHING[] somethings;


Don't declare variables until you need them, just leave bytes_read and
bytes_max here.

Is there a performance consideration? Or is it purely a style or 
D-Factor suggestion?

getopt(args,
"seek", &bytes_read,
"bytes", &bytes_max
);
if(bytes_max == 0)
bytes_max = size_t.max; // Limit on the smallest file size
else
bytes_max += bytes_read;
//bytes_read = bytes_read - (bytes_read % (BLOCK_SIZE *
SOMETHING.size_bytes.sizeof));
size_smallest = bytes_max;
somethings.length = args.length - 1;
comp_arr.length = args.length - 1;
for(size_t i = 0; i < somethings.length; i++)
{
somethings[i].file_name = args[i + 1];
somethings[i].size_bytes = getSize(somethings[i].file_name);
stderr.writef("Opening file: %s(%d)\n", somethings[i].file_name,
somethings[i].size_bytes);
somethings[i].fd = File(somethings[i].file_name, "r");
somethings[i].fd.seek(bytes_read);
if(somethings[i].fd.tell() != bytes_read)
{
stderr.writef("Failed to seek to position %d in %s\n", bytes_read,
args[i + 1]);
}
// Pick the smallest file, or the limit
size_smallest = min(size_smallest, somethings[i].size_bytes);
}


Use foreach (ref something; somethings) and something instead of
somethings[i].


I didn't know ref could be used like that :) Thanks!

// Check file sizes
for(size_t i = 0; i < somethings.length; i++)
comp_arr[i] = somethings[i].size_bytes;
writef("count: %s\n", count(comp_arr, comp_arr[0]));
if(count(comp_arr, comp_arr[0]) != comp_arr.length)
{
stderr.writef("Files are not the same size!");
foreach(s; somethings)
stderr.writef("[%s:%d]", s.file_name, s.size_bytes);
stderr.writef("\n");
}


You can use writefln() istead of writef("\n") everywhere.


It's hard to fix my printf habits :)


// While bytes_read < size of smallest file
size_t block_counter;
while(bytes_read < size_smallest)
{
// Read b

Re: Multi-file byte comparison tool. What would you have done differently?

2011-08-05 Thread Kai Meyer

On 08/05/2011 11:13 AM, Jonathan M Davis wrote:

On 08/05/2011 03:02 AM, Pelle wrote:

On Fri, 05 Aug 2011 00:25:38 +0200, Kai Meyer  wrote:

I have a need for detecting incorrect byte sequences in multiple files
(>2) at a time (as a part of our porting effort to new platforms.)
Ideally the files should be identical for all but a handful of byte
sequences (in a header section) that I can just skip over. I thought
this would be a fun exercise for my D muscles. I found success
creating a dynamic array of structs to keep information about each
file passed in via command-line parameters. I'll append the code at
the end (and I'm sure it'll get mangled in the process...)

(I'm not one for coming up with creative names, so it's SOMETHING)
Then I loop around a read for each file, then manually run a for loop
from 0 to BLOCK_SIZE, copy the size_t value into a new dynamic array
(one for each of the files opened), and run a function to ensure all
values in the size_t array are the same. If not, I compare each ubyte
value (via the byte_union) to determine which bytes are not correct by
adding each byte to a separate array, and comparing each value in that
array, printing the address and values of each bad byte as I encounter
them.

This appears to work great. Some justifications:
I used size_t because I'm under the impression it's a platform
specific size that best fits into a single register, thus making
comparisons faster than byte-by-byte.
I used a union to extract the bytes from the size_t
I wanted to create a SOMETHING for each file at run-time, instead of
only allowing a certain number of SOMETHINGS (either hard coded, or a
limit).
Originally I wrote my own comparison function, but in my search for
something more functional, I tried out std.algorithm's count. Can't
say I can tell if it's better or worse.

Features I'll probably add if I have to keep using the tool:
1) Better support for starting points and bytes to read.
2) Threshold for errors encountered, perferrably managed by a
command-line argument.
3) Coalescing error messages in sequential byte sequences.

When I run the program, it's certainly I/O bound at 30Mb/s to an
external USB drive :).

So the question is, how would you make it more D-ish? (Do we have a
term analogous to "pythonic" for D? :))


Code:

import std.stdio;
import std.file;
import std.conv;
import std.getopt;
import std.algorithm;

enum BLOCK_SIZE = 1024;
union byte_union
{
size_t val;
ubyte[val.sizeof] bytes;
}
struct SOMETHING
{
string file_name;
size_t size_bytes;
File fd;
byte_union[BLOCK_SIZE] bytes;
}


I would use TypeNames and nonTypeNames, so, blockSize, ByteUnion,
Something, sizeBytes, etc.


I haven't used TypeNames or nonTypeNames. Do have some reference
material for me? Searching http://www.d-programming-language.org/ didn't
give me anything that sounds like what you're talking about.


I believe that he was talking about how you named your variables and type
names. Normall in D, user-defined types use pascal case (e.g. Something and
ByteUnion, not SOMETHING and byte_union), and everything else uses camelcase
(e.g. blockSize and fileName, not BLOCK_SIZE and file_name). It's an issue of
style. You can name your variables however you'd like to, but what you're
doing doesn't match what most of the people around here do, which can make it
harder to read the code that you post. He was simply suggesting that you
follow the more typical D naming conventions. It's completely up to you
though.

- Jonathan M Davis
Thanks :) That's what I was asking for. I've got some programming habits 
that need to be broken if I want to increase my D-Factor!


Re: Multi-file byte comparison tool. What would you have done differently?

2011-08-08 Thread Kai Meyer

On 08/08/2011 12:33 AM, Pelle wrote:

On Fri, 05 Aug 2011 18:43:27 +0200, Kai Meyer  wrote:


On 08/05/2011 03:02 AM, Pelle wrote:


Don't declare variables until you need them, just leave bytes_read and
bytes_max here.


Is there a performance consideration? Or is it purely a style or
D-Factor suggestion?


Just style and D-factor :-)

Also, resulting code is shorter, and you can replace a lot of type names
with auto.


I don't understand why you use ByteUnion instead of just a plain array
of bytes.

I thought that comparing one byte at a time would be slower than
comparing 8 bytes at a time (size_t on 64bit) and failing over to the
byte-by-byte comparison only when the size_t value was different.


Maybe, but that's something that should be benchmarked. If a byte array
is just as fast, and the code is simpler, that's a better solution :)



I simply can't imagine how 8,000 byte comparisons would be even close to 
comparable to 1,000 size_t comparisons done one at a time, with the way 
I'm doing the comparison. I'm certain there are much better ways of 
comparing bits, but I'm not ready to make this program that complex :)


We have slices, do we have Strides?

2011-08-08 Thread Kai Meyer
I have a problem I'd really like to use Strides for to simplify my code. 
Currently, I do this:

foreach(n; 0..chunks)
comp_arr[n] = values[(n * step_size) + n]
if(!all_same(comp_arr, comp_arr[0]))

It would eliminate an entire 2 lines of code for each time I want 
strides, to be able to do this:

if(!all_same(bytes[i..$..step_size])

Meaning, start with i, grab all elements at i + block_size * n until 
block_size * n > bytes.length. Right?


-Kai Meyer


Modify thread-local storage from parent thread

2011-08-08 Thread Kai Meyer

I am playing with threading, and I am doing something like this:
file.rawRead(bytes);
auto tmpTask = task!do_something(bytes.idup);
task_pool.put(tmpTask);
Is there a way to avoid the idup (or can somebody explain why idup here 
is not expensive?)


If the logic above is expressed as:
Read bytes into an array
Create a thread (task) to execute a function that takes a copy of 'bytes'
Execute the thread

I wonder if I could:
Create a thread (task)
Read bytes directly into the tasks' thread local storage
Execute the thread



Re: We have slices, do we have Strides?

2011-08-08 Thread Kai Meyer

On 08/08/2011 12:55 PM, Jonathan M Davis wrote:

I have a problem I'd really like to use Strides for to simplify my code.
Currently, I do this:
foreach(n; 0..chunks)
comp_arr[n] = values[(n * step_size) + n]
if(!all_same(comp_arr, comp_arr[0]))

It would eliminate an entire 2 lines of code for each time I want
strides, to be able to do this:
if(!all_same(bytes[i..$..step_size])

Meaning, start with i, grab all elements at i + block_size * n until
block_size * n>  bytes.length. Right?

-Kai Meyer


Would std.range.stride work for you?

- Jonathan M Davis


It would, if there was a way to give it an offset:

int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][]));
assert(equal(stride(a, 3, 1), [ 2, 5, 8, 11 ][]));
assert(equal(stride(a, 3, 2), [ 3, 6, 9 ][]));
assert(equal(stride(a, 3, 3), [ 4, 7, 10 ][]));

Is that possible?


Re: We have slices, do we have Strides?

2011-08-09 Thread Kai Meyer

On 08/08/2011 05:25 PM, Steven Schveighoffer wrote:

On Mon, 08 Aug 2011 18:33:55 -0400, Kai Meyer  wrote:


On 08/08/2011 12:55 PM, Jonathan M Davis wrote:

I have a problem I'd really like to use Strides for to simplify my
code.
Currently, I do this:
foreach(n; 0..chunks)
comp_arr[n] = values[(n * step_size) + n]
if(!all_same(comp_arr, comp_arr[0]))

It would eliminate an entire 2 lines of code for each time I want
strides, to be able to do this:
if(!all_same(bytes[i..$..step_size])

Meaning, start with i, grab all elements at i + block_size * n until
block_size * n> bytes.length. Right?

-Kai Meyer


Would std.range.stride work for you?

- Jonathan M Davis


It would, if there was a way to give it an offset:

int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];


fixed:


assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][]));
assert(equal(stride(a[1..$], 3), [ 2, 5, 8, 11 ][]));
assert(equal(stride(a[2..$], 3), [ 3, 6, 9 ][]));
assert(equal(stride(a[3..$], 3), [ 4, 7, 10 ][]));


-Steve


Awesome :) Thanks Steve!


Re: We have slices, do we have Strides?

2011-08-09 Thread Kai Meyer

On 08/08/2011 05:25 PM, Steven Schveighoffer wrote:

On Mon, 08 Aug 2011 18:33:55 -0400, Kai Meyer  wrote:


On 08/08/2011 12:55 PM, Jonathan M Davis wrote:

I have a problem I'd really like to use Strides for to simplify my
code.
Currently, I do this:
foreach(n; 0..chunks)
comp_arr[n] = values[(n * step_size) + n]
if(!all_same(comp_arr, comp_arr[0]))

It would eliminate an entire 2 lines of code for each time I want
strides, to be able to do this:
if(!all_same(bytes[i..$..step_size])

Meaning, start with i, grab all elements at i + block_size * n until
block_size * n> bytes.length. Right?

-Kai Meyer


Would std.range.stride work for you?

- Jonathan M Davis


It would, if there was a way to give it an offset:

int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];


fixed:


assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][]));
assert(equal(stride(a[1..$], 3), [ 2, 5, 8, 11 ][]));
assert(equal(stride(a[2..$], 3), [ 3, 6, 9 ][]));
assert(equal(stride(a[3..$], 3), [ 4, 7, 10 ][]));


-Steve


Doh, how do I extract the array from the return value of stride?

import std.range;
int do_something(int[] values)
{
return values[0];
}
void main(string[] args)
{
int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
do_something(stride(a,3));
}


I get:
moo.d(9): Error: function moo.do_something (int[] values) is not 
callable using argument types (Result)
moo.d(9): Error: cannot implicitly convert expression (stride(a,3LU)) of 
type Result to int[]


Re: Modify thread-local storage from parent thread

2011-08-09 Thread Kai Meyer

On 08/08/2011 01:38 PM, Steven Schveighoffer wrote:

On Mon, 08 Aug 2011 14:17:28 -0400, Kai Meyer  wrote:


I am playing with threading, and I am doing something like this:
file.rawRead(bytes);
auto tmpTask = task!do_something(bytes.idup);
task_pool.put(tmpTask);
Is there a way to avoid the idup (or can somebody explain why idup
here is not expensive?)


I'd have to see where bytes is created, if it's created in the same
context, just casting to immutable is allowed, as long as you never use
the mutable reference again.


If the logic above is expressed as:
Read bytes into an array
Create a thread (task) to execute a function that takes a copy of 'bytes'
Execute the thread

I wonder if I could:
Create a thread (task)
Read bytes directly into the tasks' thread local storage
Execute the thread


This *might* be possible. However, in many cases, the OS is responsible
for creating the TLS when the thread starts, so you have to wait until
the thread is actually running to access it (not an expert on this, but
I think this is the case for everything but OSX?)

So you would have to create the thread, have it pause while you fill
it's TLS, then resume it.

But I think this is clearly a weird approach to this problem. Finding a
way to reliably pass the data to the sub-thread seems more appropriate.

BTW, I've dealt with having to access other threads' TLS. It's not
pretty, and I don't recommend using it except in specialized situations
(mine was adding a GC hook).

-Steve


Well, bytes is in a loop, so casting to immutable wouldn't do it. The 
idea is to read a block of bytes, and hand them off to a worker thread 
to operate on those set of bytes. Everything is working, I'm just trying 
to avoid having to reallocate that block of bytes for the read, and then 
reallocate them again to pass them off to the worker thread. If I could 
get away with one allocation, I'd be happier.


-Kai Meyer


Re: We have slices, do we have Strides?

2011-08-09 Thread Kai Meyer

On 08/09/2011 09:37 AM, Steven Schveighoffer wrote:

On Tue, 09 Aug 2011 11:29:52 -0400, Kai Meyer  wrote:


On 08/08/2011 05:25 PM, Steven Schveighoffer wrote:

On Mon, 08 Aug 2011 18:33:55 -0400, Kai Meyer  wrote:


On 08/08/2011 12:55 PM, Jonathan M Davis wrote:

I have a problem I'd really like to use Strides for to simplify my
code.
Currently, I do this:
foreach(n; 0..chunks)
comp_arr[n] = values[(n * step_size) + n]
if(!all_same(comp_arr, comp_arr[0]))

It would eliminate an entire 2 lines of code for each time I want
strides, to be able to do this:
if(!all_same(bytes[i..$..step_size])

Meaning, start with i, grab all elements at i + block_size * n until
block_size * n> bytes.length. Right?

-Kai Meyer


Would std.range.stride work for you?

- Jonathan M Davis


It would, if there was a way to give it an offset:

int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];


fixed:


assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][]));
assert(equal(stride(a[1..$], 3), [ 2, 5, 8, 11 ][]));
assert(equal(stride(a[2..$], 3), [ 3, 6, 9 ][]));
assert(equal(stride(a[3..$], 3), [ 4, 7, 10 ][]));


-Steve


Doh, how do I extract the array from the return value of stride?

import std.range;
int do_something(int[] values)
{
return values[0];
}
void main(string[] args)
{
int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
do_something(stride(a,3));
}


I get:
moo.d(9): Error: function moo.do_something (int[] values) is not
callable using argument types (Result)
moo.d(9): Error: cannot implicitly convert expression (stride(a,3LU))
of type Result to int[]


Two options, first, you can change do_something to accept a range
(depending on what the real implementation of do_something is, you might
need to require a random-access range, but that dummy implementation
could accept any input range, just return x.front):

int do_something(R)(R values) if (isInputRange!R && is(ElementType!R :
int))
{
return values.front; // maybe need random access in real code?
}

Second option, convert range to an array. This incurs a memory
allocation to create the array:

import std.array;

...
void main(...)
{
...
do_something(array(stride(a, 3)));
}

doc for std.array.array:
http://www.d-programming-language.org/phobos/std_array.html#array

-Steve


Both of those solutions worked, thanks :)


Re: Modify thread-local storage from parent thread

2011-08-09 Thread Kai Meyer

On 08/09/2011 10:27 AM, Steven Schveighoffer wrote:

On Tue, 09 Aug 2011 11:36:13 -0400, Kai Meyer  wrote:


On 08/08/2011 01:38 PM, Steven Schveighoffer wrote:

On Mon, 08 Aug 2011 14:17:28 -0400, Kai Meyer  wrote:


I am playing with threading, and I am doing something like this:
file.rawRead(bytes);
auto tmpTask = task!do_something(bytes.idup);
task_pool.put(tmpTask);
Is there a way to avoid the idup (or can somebody explain why idup
here is not expensive?)


I'd have to see where bytes is created, if it's created in the same
context, just casting to immutable is allowed, as long as you never use
the mutable reference again.


If the logic above is expressed as:
Read bytes into an array
Create a thread (task) to execute a function that takes a copy of
'bytes'
Execute the thread

I wonder if I could:
Create a thread (task)
Read bytes directly into the tasks' thread local storage
Execute the thread


This *might* be possible. However, in many cases, the OS is responsible
for creating the TLS when the thread starts, so you have to wait until
the thread is actually running to access it (not an expert on this, but
I think this is the case for everything but OSX?)

So you would have to create the thread, have it pause while you fill
it's TLS, then resume it.

But I think this is clearly a weird approach to this problem. Finding a
way to reliably pass the data to the sub-thread seems more appropriate.

BTW, I've dealt with having to access other threads' TLS. It's not
pretty, and I don't recommend using it except in specialized situations
(mine was adding a GC hook).

-Steve


Well, bytes is in a loop, so casting to immutable wouldn't do it. The
idea is to read a block of bytes, and hand them off to a worker thread
to operate on those set of bytes. Everything is working, I'm just
trying to avoid having to reallocate that block of bytes for the read,
and then reallocate them again to pass them off to the worker thread.
If I could get away with one allocation, I'd be happier.


OK, there are other options. First, you could keep a "pool" of buffers,
which are marked as shared. When you want to run a task, get one of
those buffers, fill it, then pass the buffer to the task thread to
process. Make sure the task thread puts the buffer back into the pool
when it's done. I'd recommend casting the buffer to unshared while
inside the task thread to save some cycles. This is probably the option
I'd go with.

Second, you can have the task thread give you it's TLS buffer to read
data into (you need to do some casting to get this around the type
system). Note that in order for it truly to be stored in TLS, the buffer
has to be a fixed-sized array.

-Steve


These are concepts that I'm only familiar with. I think I would like to 
try the "pool" of buffers. I can't say I know how to mark buffers as 
shared, though. Could you modify this for me, to show me an example?


import std.parallelism;
ubyte[8][] pool; // Dynamic array of (array of 8 bytes)
void thread_func()
{
//my_pool[0] = 50;
}
void main(string[] args)
{
uint threads = 2;
pool.length = threads;
TaskPool taskpool = new TaskPool(threads);
foreach(i; 0..threads)
{
auto tmpTask = task!thread_func();
taskpool.put(tmpTask);
}
taskpool.stop();
}



Re: making a really simple dll.

2011-08-18 Thread Kai Meyer

On 08/18/2011 01:32 PM, Trass3r wrote:

Am 18.08.2011, 21:17 Uhr, schrieb Adam D. Ruppe
:

We should make a mixin template DllMain that has a generic main.


We should also have a -shared switch that transparently includes all of
the boilerplate crap:
particularly the .def file, maybe even a default DllMain if none exists.


This would be my vote. -shared will:
1) check if there is a DllMain defined at the end, and if not, sticks a 
generic one in there
2) check if there are any exported functions (via .def or export()), if 
not, export them all


That way, the OP's original simple 1 function d file compiles to a dll.

Same goes for the Linux side. Default constructor and destructors that 
initialize and destroy the D runtime if there aren't any defined at the 
end of the compilation.


-Kai Meyer