Temporarily protect array from garbage collection

2014-04-24 Thread Lars T. Kyllingstad via Digitalmars-d-learn
Is it possible to temporarily prevent the garbage collector from 
collecting a memory block even if there are no references to it?


The use case is as follows:  I want to call a C library function 
which expects to take ownership of a buffer.  It looks something 
like this:


alias FreeFunc = extern(C) void function(void*, void*) 
nothrow;


extern(C) void foo(void* buf, size_t len,
   FreeFunc free, void* ctx) nothrow;

Here, 'buf' is a pointer to the buffer, 'len' is the length of 
the buffer, 'free' is a function to deallocate the buffer when 
the library is done with it, and 'ctx' is a user-supplied context 
pointer.  Upon deallocation, 'free' receives two parameters; the 
pointer to the buffer and the context pointer.  The latter can be 
anything, even null, as it is just passed to 'free' and not used 
for anything else.


Here is the problem:  I want to be able to use a 
garbage-collected dynamic array with this function, but I don't 
want to have to retain a reference to it in my program.  (I don't 
know when the C library will call the free function.)  In other 
words, I want something like this:


extern(C) void myFree(void* ptr, void* ctx)
{
enableGCFor(ptr);
}

auto arr = new int[123];
disableGCFor(arr);
foo(arr.ptr, arr.length, myFree, null);
arr = null;

Is this at all possible?

Thanks,
Lars


Re: Temporarily protect array from garbage collection

2014-04-24 Thread Lars T. Kyllingstad via Digitalmars-d-learn

On Thursday, 24 April 2014 at 20:09:38 UTC, Justin Whear wrote:
You can use GC.addRoot() from core.memory before passing the 
pointer to

the C function, then use GC.removeRoot in your myFree function.


Perfect, thanks!


Struct size

2014-04-19 Thread Lars T. Kyllingstad via Digitalmars-d-learn

Say I have two structs, defined like this:

struct A { /* could contain whatever */ }

struct B { A a; }

My question is, is it now guaranteed that A.sizeof==B.sizeof, 
regardless of how A is defined (member variable types, alignment, 
etc.)?  More to the point, say I have a function foo() which 
looks like this:


extern(C) void foo(A* ptr, size_t len);

Is it now guaranteed that I can safely pass it a pointer to an 
array of Bs?  That is,


auto arr = new B[10];
foo(cast(A*) arr.ptr, arr.length);

Thanks,
Lars


Re: Struct size

2014-04-19 Thread Lars T. Kyllingstad via Digitalmars-d-learn
On Saturday, 19 April 2014 at 12:26:16 UTC, Andrej Mitrovic via 
Digitalmars-d-learn wrote:

On 4/19/14, Lars T. Kyllingstad via Digitalmars-d-learn
digitalmars-d-learn@puremagic.com wrote:

Say I have two structs, defined like this:

 struct A { /* could contain whatever */ }

 struct B { A a; }

My question is, is it now guaranteed that A.sizeof==B.sizeof?


The best thing to do is add a static assert and then you can 
relax:


That's what I've done, but it would be nice to know the code 
won't break due to some combination of platform and/or compiler 
switches I didn't think to test.  Anyway, I've played around a 
bit, and found that a combination of struct and field alignment 
*can* break my assumption:


align(1) struct A
{
char c;
align(1) int i;
}

struct B { A a; }

Now, A.sizeof is 5, while B.sizeof is 8.  I'd have to add 
align(1) to the declaration of B to fix it.


Re: Different NaNs used

2011-06-29 Thread Lars T. Kyllingstad
On Mon, 27 Jun 2011 16:41:14 -0400, bearophile wrote:

 This question is related to this thread:
 http://d.puremagic.com/issues/show_bug.cgi?id=3632
 
 Can you tell me why real.nan and real.init don't contain the same bit
 patterns?
 
 
 import std.math: isIdentical;
 void main() {
 assert(isIdentical(real.nan, real.init)); // this asserts
 }

real.init is a signaling NaN, real.nan is not.  I don't know if this is 
by design, but I suppose it may be:  You can quiet a signaling NaN by 
assigning real.nan to your variable.

  http://en.wikipedia.org/wiki/NaN#Signaling_NaN

-Lars


Re: Advice on threading/fibers/?

2011-06-16 Thread Lars T. Kyllingstad
On Wed, 15 Jun 2011 23:57:25 +, Justin Whear wrote:

 Consider the following:
 
 You have 10 million data points and you need to apply a multipass
 algorithm to them. Each pass is like a cellular automata: it can read
 from the previous pass but it doesn't know the current values. This
 makes the actual processing of each value trivially parallelizable. The
 actual operation for each value is fairly simple and cheap (essentially
 a multidimensional ancestor-child averaging operation).
 
 After each value has been operated on once, the pass is complete and the
 current and old buffers are switched (conceptually, the current
 buffer can only be written to, the old buffer can only be read--using
 __gshared here).
 
 The number of passes is not fixed; in the course of each value
 operation, an error is computed. When the worst individual error falls
 below a certain threshold, the algorithm is finished. Generally this
 will take between one thousand and ten thousand passes.
 
 How would you go about parallelizing this? My thought is to take the
 map/reduce approach within each pass: each thread/fiber takes a slice of
 the dataset, makes its modifications, then returns an error summary.
 These summaries are quickly combined and the algorithm loop decides
 whether to run again. Each pass shouldn't take more than a second or
 two, so I'm not sure whether introducing the overhead of spawning, say,
 10 threads each pass is worthwhile (times 5000 passes). On the other
 hand, I have plenty of CPUs to throw at it (at least 16 cores, each with
 hyperthreading) and am in a situation where as fast as possible is
 important (while individual datasets may not grow, the number of them
 is).
 
 Any thoughts appreciated.

I would recommend you take a look at the new std.parallelism module, 
which was introduced in the most recent DMD release (2.053):

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

-Lars


Re: Pure not acting pure.

2011-06-16 Thread Lars T. Kyllingstad
On Thu, 16 Jun 2011 06:52:45 -0400, Michel Fortin wrote:

 On 2011-06-15 23:29:46 -0400, Charles McAnany mcana...@rose-hulman.edu
 said:
 
 Ah, so does the compiler figure out which ones are strongly and weakly
 pure and then optimize as
 appropriate? Is there a way to indicate that a function is strongly
 pure? Because it would seem odd
 to call a function you thought was pure and wind up with a mutated
 argument.
 
 Just make sure all the parameters are either const or immutable or
 passed by copy and do not contain any pointer or reference. That'll make
 the function strongly pure, and the compiler will be able optimize.

If you want a strongly pure function, the parameters need to be immutable 
or implicitly convertible to immutable.  const references may be mutated 
elsewhere.

-Lars


Re: Pure not acting pure.

2011-06-16 Thread Lars T. Kyllingstad
On Thu, 16 Jun 2011 17:38:27 +, Charles McAnany wrote:

 Ok, I think I get it. That cleared it up. =). So, if you have a
 functioned labelled pure, it's your job to not pass it mutable
 arguments, but the compiler's job to make sure it doesn't mutate
 anything not in the arguments. And that's why a strongly pure function
 can call a weakly pure one - only the first function's internal state
 can be mutated by a weakly pure function. Thanks!

Exactly. :)

-Lars


Re: how to migrate to std.datetime

2011-05-09 Thread Lars T. Kyllingstad
On Mon, 09 May 2011 09:49:04 +0100, Russel Winder wrote:

 On Sun, 2011-05-08 at 23:52 -0700, Jonathan M Davis wrote: [ . . . ]
 I could look at writing an article on moving from std.date to
 std.datetime, I suppose. We already have an article contest going, and
 it would make sense to put such an article on the site.
 
 I suspect many people would be happy if you did do this, but I was
 thinking more copy and paste the material into a wiki page and then let
 everyone who has knowledge/interest help refine it.
 
 I don't really have anywhere online that I can post anything myself
 though, let alone links to whatever newsgroup posts might be useful for
 understanding std.datetime.
 
 If there isn't a D/Phobos wiki then now is the time for Those in
 Authority, to make one so that this sort of material can go up there and
 be crowd edited.

There certainly is:  http://prowiki.org/wiki4d/wiki.cgi

-Lars


Re: What is put() useful for with regards to dynamic arrays?

2011-05-02 Thread Lars T. Kyllingstad
On Sat, 30 Apr 2011 00:09:09 -0400, Andrej Mitrovic wrote:

 import std.range;
 
 void main()
 {
 int[] a = [1, 2, 3];
 
 a.put(6);
 assert(a == [2, 3]);
 
 a.put([1, 2]);
 assert(a.length == 0);
 }
 
 Seems kind of odd.. put is implemented as an append method for some
 custom types, e.g. std.array.appender. But for arrays put just removes
 Item or RangeLength number of elements from the array. What's the use
 case for this?

This should probably be in a FAQ somewhere. :)

http://www.digitalmars.com/d/archives/digitalmars/D/
std.array.put_doesn_t_put_106871.html

-Lars


Re: Reading a line from stdin

2011-03-16 Thread Lars T. Kyllingstad
On Wed, 16 Mar 2011 11:20:43 +0100, spir wrote:

 On 03/16/2011 06:41 AM, Jesse Phillips wrote:
 Ali Çehreli Wrote:

 Right? Is there a better way that I am missing?

 Thank you,
 Ali

 No better way, the stated reason IIRC is that it is easier to remove
 the new line then to append it back on.
 
 May be stated, but it is very wrong! I guess:
 
  s = s ~ '\n';
 versus
  if ((str[$-1] == '\n') || (str[$-1] == '\r')) {
  str = str[0..$-1];
  if ((str[$-1] == '\n') || (str[$-1] == '\r')) {
  str = str[0..$-1];
  }
  }

That comparison seems a bit biased. :)  This one is more fair:

import std.path;
...
s ~= linesep;

versus

import std.string;
...
s = s.chomp;

-Lars


Re: in/out with -release

2011-03-05 Thread Lars T. Kyllingstad
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


Re: Two questions about %a

2011-03-02 Thread Lars T. Kyllingstad
On Wed, 02 Mar 2011 13:35:11 +0100, Magnus Lie Hetland wrote:

 First question: I just noticed that writefln(%a, 1.2) writes
 0x1.3p+0, while writeln(format(%a, 1.2)) (that is, with
 std.string.format) writes 0x9.8p-3 ... wouldn't it be nice
 to be consistent here? (The former is what printf in gcc gives.) Or am I
 missing a difference in functionality?

Hm, that's weird.  I'm pretty sure writefln() is doing the right thing 
here, since that's what printf() does.  I've had a look at the code for 
format(), and it looks to me like it is using some old formatting code 
that is being phased out.  I've created a bug report for this, and will 
look into fixing it shortly:

  http://d.puremagic.com/issues/show_bug.cgi?id=5687


 Second question: Just to make sure, this *is* an exact representation of
 the underlying floating-point number? (I.e., if that'w what I'm after,
 using %a *is* the way to go?)

Yes, that's right.

-Lars


Re: Version very simple?

2011-02-27 Thread Lars T. Kyllingstad
On Sun, 27 Feb 2011 15:52:01 +0100, simendsjo wrote:

 I'm having some problems grokking version.
 
 How would I translate this simple C macro? #if !defined(IDENT) ||
 !defined(IDENT2)
 
 I've tried the following:
 version(!IDENT)
   identifier or integer expected, not !
 
 !version(IDENT)
   Declaration expected, not '!'
 
 version(IDENT || IDENT2)
   found '||' when expecting ')'
 
 version(IDENT) || version(IDENT2)
   Declaration expected, not '||'
 
 
 This is just plain ugly:
 version(IDENT) {
 } else {
version = NOT_IDENT_OR_IDENT2;
 }
 
 version(IDENT2) {
 } else {
version = NOT_IDENT_OR_IDENT2;
 }
 
 version(NOT_IDENT_OR_IDENT2) {
// Finally
 }

Here's one nice solution to your problem:

http://www.digitalmars.com/d/archives/digitalmars/D/
Improving_version_..._119799.html#N119846

Basically, he defines an isVersion() template which is true if the 
current version is enabled, and false if not.

-Lars


Re: %x and floats

2011-02-25 Thread Lars T. Kyllingstad
On Thu, 24 Feb 2011 13:27:39 -0500, Trass3r wrote:

 Why doesn't this work:
 
 import std.stdio;
 void main()
 {
   float a,b=0;
   writefln(%x %x, a, b);
 }
 
 std.format.FormatError: std.format floating

That is because %x is for formatting integers.  If you want a hex 
representation of a floating-point number, use %a.

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

-Lars


What is -nofloat good for?

2011-02-24 Thread Lars T. Kyllingstad
The dmd help text says the following about the -nofloat switch:

  -nofloat do not emit reference to floating point

What does this mean?  What is -nofloat good for?

-Lars


Re: Is std.array.replace supposed to work with char[]?

2011-02-21 Thread Lars T. Kyllingstad
On Sun, 20 Feb 2011 15:23:29 -0500, Steven Schveighoffer wrote:

 On Sun, 20 Feb 2011 14:51:10 -0500, bearophile
 bearophileh...@lycos.com wrote:
 
 Jacob Carlborg:

 Every time I try to use D2 it's just a PITA to use. I've used D1 and
 Tango for
 several years and had no problem with that.

 I use this thread to ask regarding one specific little problem I have
 with strings. I want to generate a random string of AB using the array,
 map, etc, this looks like a possible implementation (in std.random
 there is no choice() function yet):


 import std.stdio, std.random, std.string, std.algorithm, std.range;
 void main() {
 auto m = map!((i){ return AB[uniform(0,2)]; })(iota(10)); string
 s = join(array(m));
 writeln(s);
 }


 It gives this error:
 ...\dmd\src\phobos\std\array.d(62): Error: result[i] isn't mutable
 test.d(5): Error: template instance
 std.array.array!(Map!(__dgliteral1,Iota!(int,uint))) error
 instantiating

 What's the right way to write it in D?

 The same code in Python2.x:

 from random import choice
 s = .join(choice(AB) for _ in xrange(10)) print s
 
 Just a blind guess, I have not tested, but maybe it's because the
 compiler is using const(char) as the return type for your delegate
 literal since you never specify one?

It's probably using immutable(char) since that's the element type of AB.

-Lars


Re: rdmd problems (OS X Leopard, DMD 2.052)

2011-02-21 Thread Lars T. Kyllingstad
On Mon, 21 Feb 2011 12:18:54 +0100, Magnus Lie Hetland wrote:

 On 2011-02-20 19:22:20 +0100, Magnus Lie Hetland said:
 
 On 2011-02-19 22:25:31 +0100, Nick Sabalausky said:
 
 [snip]
 Unfortunately, rdmd doesn't seem to have gotten much attention lately.
 I've had a few patches for it sitting in bugzilla for a number of
 months. (Not that I'm complaning, I realize there's been other
 priorities.)
 
 I see. Kind of surprising, given that rdmd is distributed in the
 official DMD zip file. But, yeah, no complaints. :)
 
 Actually, if you want, you can grab a version of rdmd.d with my
 patches applied here:
 http://www.dsource.org/projects/semitwist/browser/trunk/rdmdAlt.d
 
 Thanks!
 
 Humm. I'm still using the rdmd I had (it seems to work, so as long as I
 have already compiled it... ;)
 
 However: I'm a bit baffled by the --shebang option. What's its purpose,
 really? If I use rdmd without it in a shebang line, it seems to work
 fine. If I *do* use --shebang, the code doesn't seem to be
 compiled/executed at all...
 
 It seems like it interprets args[1] as a single string containing all
 the arguments, splitting it into separate items. That seems well an good
 -- except (in OS X, at least) it doesn't seem to be needed (I get my
 arguments just fine without it, and the shebang-line switches work well)
 ... and it doesn't seem to work (that is, with --shebang, nothing
 happens).
 
 Any thoughts on this?

Say you have a file myscript, that starts with the line

#!/path/to/interpreter --foo --bar

If you run this as

./myscript --hello --world

then the args[] received by the interpreter program looks like this:

args[0] = /path/to/interpreter
args[1] = --foo --bar
args[2] = ./myscript
args[3] = --hello
args[4] = --world

This is the case on every shell I've tried on Linux, at least.  So if you 
have multiple rdmd options, it should in principle need --shebang to know 
that it is being run in a shebang line, so it can expand args[1].

I don't know why it works without --shebang for you, though. :)

-Lars


Re: Checking if something is a template specialization?

2011-02-18 Thread Lars T. Kyllingstad
On Fri, 18 Feb 2011 02:02:51 +, Sean Eskapp wrote:

 If I have
 
 class Bar(T)
 {
 }
 
 void foo(Y)()
 {
...
 }
 
 Is there a way to check inside foo() that Y is in some way an
 instantiation of Bar? Is there a way to find WHICH instantiation it is?


void foo(Y)()
{
static if (is(Y Z == Bar!Z))
{
// Here, Z is now an alias to whichever type Bar is
// instantiated with.
}
else
{
// Z is invalid here.
}
}


Re: datetime fails with undefined reference

2011-02-18 Thread Lars T. Kyllingstad
On Fri, 18 Feb 2011 16:38:19 +, Kai Meyer wrote:

 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?

You have to link in librt.  Pass the -L-lrt option to DMD and it should 
work.

-Lars


Re: Finding out if T is a specialization of another template

2011-02-18 Thread Lars T. Kyllingstad
On Fri, 18 Feb 2011 17:16:02 +, Sean Eskapp wrote:

 I was given this code, to check if Y is a specialization of Bar. How
 does it work?
 
 class Bar(T)
 {
 }
 
 void foo(Y)()
 {
 static if (is(Y Z == Bar!Z))
 {
 // Here, Z is now an alias to whichever type Bar is //
 instantiated with.
 }
 else
 {
 // Z is invalid here.
 }
 }

I'm not sure what you mean by how does it work.  If it's the is() 
expression you're wondering about, it's documented here:

http://www.digitalmars.com/d/2.0/expression.html#IsExpression

-Lars


Re: datetime fails with undefined reference

2011-02-18 Thread Lars T. Kyllingstad
On Fri, 18 Feb 2011 10:23:41 -0800, Jonathan M Davis wrote:

 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.

Well, he could be using a setup similar to me.  I don't use dmd.conf at 
all.  Instead I set the DFLAGS environment variable in the startup script 
of my shell.  I think the new dependency should be noted in the changelog.

-Lars


Re: Finding out if T is a specialization of another template

2011-02-18 Thread Lars T. Kyllingstad
On Fri, 18 Feb 2011 20:37:38 +, Sean Eskapp wrote:

 == Quote from Lars T. Kyllingstad (public@kyllingen.NOSPAMnet)'s article
 On Fri, 18 Feb 2011 17:16:02 +, Sean Eskapp wrote:
  I was given this code, to check if Y is a specialization of Bar. How
  does it work?
 
  class Bar(T)
  {
  }
 
  void foo(Y)()
  {
  static if (is(Y Z == Bar!Z))
  {
  // Here, Z is now an alias to whichever type Bar is //
  instantiated with.
  }
  else
  {
  // Z is invalid here.
  }
  }
 I'm not sure what you mean by how does it work.  If it's the is()
 expression you're wondering about, it's documented here:
 http://www.digitalmars.com/d/2.0/expression.html#IsExpression -Lars
 
 Ah, yes. I'd checked the is documentation, but whenever I tried using
 that is expression outside of an if statement, it complained about my
 usage, so I assumed it had something to do with if statements.

Yeah, is() has a few extra features when it's combined with 'static 
if'. :)

-Lars


Re: Git library for checkouts?

2011-02-15 Thread Lars T. Kyllingstad
On Tue, 15 Feb 2011 21:32:06 +0100, Jacob Carlborg wrote:

 Maybe a little off topic but does anyone know about a git library, I'll
 only need to do checkouts?

Here is a C library, written by the folks behind GitHub:

https://github.com/schacon/libgit

-Lars


Re: MD5 hash on a file and rawRead

2011-02-10 Thread Lars T. Kyllingstad
On Wed, 09 Feb 2011 23:01:47 -0500, Andrej Mitrovic wrote:

 I'm trying to use the std.md5.sum method. It takes as an argument a
 digest to output the hash to, and the second argument is plain data.
 
 So I'm trying to read an entire file at once. I thought about using
 rawRead, but I get a runtime exception:
 auto filename = rC:\file.dat;
 File file;
 try
 {
 file = File(filename, r);
 }
 catch (ErrnoException exc)
 {
 return;
 }
 ubyte[] buffer;
 file.rawRead(buffer);
  
 error: stdio.d:rawRead must take a non-empty buffer
 
 There are no size methods for the File structure (why?). There's a
 getSize function but it's in std.file, and I can't use it because:
 
 auto filename = rC:\file.dat;
 File file;
 try
 {
 file = File(filename, r);
 }
 catch (ErrnoException exc)
 {
 return;
 }
 
 ubyte[] buffer = new ubyte[](getSize(filename)); ubyte[16]
 digest;
 file.rawRead(buffer);
 std.md5.sum(digest, buffer);
 
 Error: cannot implicitly convert expression
 (getSize(cast(const(char[]))this._libFileName)) of type ulong to uint
 
 I can use the buffered version fine:
 auto filename = rC:\file.dat;
 File file;
 try
 {
 file = File(filename, r);
 }
 catch (ErrnoException exc)
 {
 return;
 }
 
 ubyte[16] digest;
 MD5_CTX context;
 context.start();
 
 foreach (ubyte[] buffer; file.byChunk(4096 * 1024)) {
 context.update(buffer);
 }
 
 context.finish(digest);
 writefln(MD5 (%s) = %s, filename, digestToString(digest));
 
 But I'd prefer to write simpler code and use rawRead to read the entire
 file at once. I'm reading really small files, so rawRead should be fine.

To read an entire file at once, you should use std.file.read(), or 
std.file.readText() if it's an UTF encoded text file.


 Also, why do we have file handling in two different modules? I'd expect
 to find all file handling ops in std.file, not scattered around Phobos.
 
 Let me know if I'm doing something obviously stupid. :)

There are actually three modules for file handling, but I think they are 
nicely separated:

  - std.file handles files as isolated units, i.e. it reads,
writes and manipulates entire files.

  - std.path manipulates file/directory names as strings, and
performs no disk I/O.

  - std.stdio is for more advanced file I/O, as it lets you
open files and manipulate them through the File handle.
(This includes reading, writing, seeking, etc.)

Hope this clears things up. :)

-Lars


Re: How to web programming with D2?

2011-02-10 Thread Lars T. Kyllingstad
On Thu, 10 Feb 2011 04:29:21 -0500, canalpay wrote:

 I am trying to write the web framework(but not to write, to gain
 experience.). Maybe the framework can has got a MVC  desing pattern. But
 first, the D2 is not has got for the web library and I am decided write
 to library for web.
 
 I am writed a function for post and get methods. (I am not tried to
 functions. But I think, they are works.) POST:
 https://github.com/canalpay/turna/blob/master/library/post.d GET  : 
 https://github.com/canalpay/turna/blob/master/library/get.d
 
 Environment variables are easy to write for the function. But How to
 write a cookie and session? I looked at the codes of tango. However,
 don't understand.(I'm new to d programming language.)

Adam D. Ruppe does a lot of web development in D, and he has created a 
fairly extensive web-dev library.

  http://arsdnet.net/dcode/

For cookie/session handling, cgi.d is probably the place to look.

-Lars


Re: Dynamic and Static Casting

2011-02-10 Thread Lars T. Kyllingstad
On Thu, 10 Feb 2011 11:54:02 +, Lars T. Kyllingstad wrote:

 On Thu, 10 Feb 2011 16:44:12 +0530, d coder wrote:
 
 Greetings All
 
 I have learnt that D has only one casting operator and that is 'cast'.
 The same operator assumes different functionality depending on the
 context in which it he being used.
 
 Now I have a situation where I have to downcast an object and I am sure
 of the objects type and thereby I am sure that the downcast would only
 be successful. To make the operation faster, in C++ I could have used
 static_cast operator, thus giving the RTTI a skip. Would this be
 possible in D? Can I force a static_cast which downcasting?
 
 Here's one solution.  [...]

Ok, bearophile's solution is better, because it has fewer casts.  I 
forgot you can cast to void*.  So here's an improved version, with some 
template constraints to make sure it's only used for class types:

T staticCast(T, U)(U obj)  if (is(T == class)  is(U == class))
{
return cast(T) cast(void*) obj;
}

-Lars


Re: higher-order funcs for ranges (with usual interface)

2011-02-07 Thread Lars T. Kyllingstad
On Thu, 03 Feb 2011 19:11:04 +0100, spir wrote:

 On 02/03/2011 02:25 PM, Lars T. Kyllingstad wrote:
 On Thu, 03 Feb 2011 13:53:44 +0100, spir wrote:

 On 02/03/2011 01:17 PM, Lars T. Kyllingstad wrote:
 Why the reluctance to use template constraints?  They're so flexible!
 :)

 I cannot stand the is() idiom/syntax ;-) Dunno why. Would happily
 get rid of it in favor of type-classes (built eg as an extension to
 current interfaces). For instance, instead of:

   void func (T) (T t)
   if (is(someConstraint1)  is(someConstraint2))
   {
   ...
   }

 use:

   void func (SomeTypeClass T) (T t)
   {
   ...
   }

 For instance (untested):

   void func (T) (T t)
   if (isInputRange(T)  is(ElementType!T == E))
 --
   void func (InputRange!E T) (T t)

 where InputRange is a (templated) interface / type-class.

 Type-class checks on /type/ /template/ parameters (as opposed to type
 checks on regular value parameters) would be performed structurally
 (as opposed to nominally). D knows how to do this, since that's what
 it needs to perform when checking is() constraints.

 I agree that is() is rather ugly.  Same with __traits.  If you haven't
 already done so, I suggest you vote up this issue:

http://d.puremagic.com/issues/show_bug.cgi?id=3702
 
 Done!
 (I did not get all the details 'cause no time for a deep look, but
 anything impulsed by the motivation of getting rid of is() and __traits
 can hardly be a Bad Thing ;-)
 
 What do you think of type classes, as an alternative to Don's proposal
 in issue #3702.
 See also Type Classes as Objects and Implicits:
 http://ropas.snu.ac.kr/~bruno/papers/TypeClasses.pdf
 
 Anyway, you can hide is()'s ugliness in the most common cases, though,
 by defining new templates.  For instance, I wouldn't mind having the
 following in std.range as an overload of isInputRange:

template isInputRange(R, T)
{
enum isInputRange = isInputRange!R  is(ElementType!R == T);
}

 Then, you'd simply write

void func(R)(R range) if (isInputRange!(R, E)) { ... }

 -Lars
 
 A great improvement, indeed.
 
 While we're at defining a set of constraints in a template, let us make
 it an interface / type-class that the E must (structurally) satisfy, and
 just write:
  void func(InputRange!E R)(R range) { ... }
 
 What do you think?
 
 Note: a template is not always required, I guess:
  void writeElements (Iterable Elements) (Elements elements) {
   foreach (element, elements) {
  write(element,' ');
  }
  }
 (In this case, because write is itself generic.)


How would you deal with the case where the input must satisfy more than 
one concept/constraint?  I mean, for the simple case where you say R 
must be an input range of E, sure, type classes/concepts are cleaner.  
But what about the case where, say, you want R to be an infinite random 
access range that supports slicing?  With template constraints it's 
simple:

void doStuff(R)(R someRange)
if (isRandomAccessRange!R  isInfinite!R  hasSlicing!R)
{
...
}

Now, I'm no expert on concepts at all---my main sources of information 
about them are superficial comments on the D newsgroup and a quick browse 
of the Wikipedia page---but it seems to me that you'd have to define a 
new concept for each such combination of constraints.  Or?

-Lars


Re: default '==' on structs

2011-02-03 Thread Lars T. Kyllingstad
On Wed, 02 Feb 2011 17:35:50 +0100, spir wrote:

 On 02/02/2011 04:20 PM, Lars T. Kyllingstad wrote:
 On Wed, 02 Feb 2011 15:55:53 +0100, spir wrote:

 Hello,

 What are the default semantics for '==' on structs?

 I ask this because I was forced to write opEquals on a struct to get
 expected behaviour. This struct is basically:

 struct Lexeme {
   string tag;
   string slice;
   Ordinal index;
 }

 Equal Lexeme's compare unequal using default '=='. When I add:

   const bool opEquals (ref const(Lexeme) l) {
   return (
  this.tag   == l.tag
this.slice == l.slice
this.index == l.index
   );
   }

 then all works fine. What do I miss?

 I think the compiler does a bitwise comparison in this case, meaning
 that it compares the arrays' pointers instead of their data.  Related
 bug report:

http://d.puremagic.com/issues/show_bug.cgi?id=3433

 -Lars
 
 Thank you, Lars.
 In fact, I do not really understand what you mean. But it helped me
 think further :-)
 Two points:
 
 * The issue reported is about '==' on structs not using member opEquals
 when defined, instead performing bitwise comparison. This is not my
 case: Lexeme members are plain strings and an uint. They should just be
 compared as is. Bitwise comparison should just work fine. Also, this
 issue is marked solved for dmd 2.037 (I use 2.051).

Yeah, but I would say it isn't really fixed.  It seems that the final 
decision was that members which define opEquals() are compared using 
opEquals(), while all other members are compared bitwisely.  But built-in 
dynamic arrays can also be compared in two ways, using '==' (equality) or 
'is' (identity, i.e. bitwise equality).  Struct members which are dynamic 
arrays should, IMO, be compared using '==', but apparently they are not.


 * The following works as expected:
 
 struct Floats {float f1, f2;}
 struct Strings {string s1, s2;}
 struct Lexeme {
  string tag;
  string slice;
  uint index;
 }
 
 unittest {
  assert ( Floats(1.1,2.2)  == Floats(1.1,2.2) ); assert (
  Strings(a,b) == Strings(a,b) ); assert ( Lexeme(a,b,1)
  == Lexeme(a,b,1) );
 }
 
 This shows, if I'm right:
 1. Array (string) members are compared by value, not by ref/pointer. 2.
 Comparing Lexeme's works in this test case.

Nope, it doesn't show that, because you are assigning literals to your 
strings, and DMD is smart enough to detect duplicate literals.

string s1 = foo;
string s2 = foo;
assert (s1.ptr == s2.ptr);

That is actually pretty cool, by the way. :)

Here's an example to demonstrate my point:

import std.stdio;

struct T { string s; }

void main(string[] args)
{
auto s1 = args[1];
auto s2 = args[2];
auto t1 = T(s1);
auto t2 = T(s2);

if (s1 == s2) writeln(Arrays are equal);
else writeln(Arrays are different);

if (t1 == t2) writeln(Structs are equal);
else writeln(Structs are different);
}

If run with the arguments foo bar it prints:

Arrays are different
Structs are different

If run with the arguments foo foo it prints:

Arrays are equal
Structs are different

-Lars


Re: higher-order funcs for ranges (with usual interface)

2011-02-03 Thread Lars T. Kyllingstad
On Thu, 03 Feb 2011 13:05:00 +0100, spir wrote:

 On 02/03/2011 08:41 AM, Lars T. Kyllingstad wrote:
 On Wed, 02 Feb 2011 18:38:02 +0100, spir wrote:
 
 I guess the only solution would be for the compiler to support a kind
 of reange type syntax?

 I'm not sure I understand what you mean here.  Perhaps you're looking
 for something like concepts, which have been discussed for both D and
 C++0x but rejected in both languages:

  http://en.wikipedia.org/wiki/Concept_%28generic_programming%29
 
 Yes, I know about concepts ;-) (and typestates, and such). That's not
 what I mean but I could not find how to express it. What I have in mind
 is a way to simply express range of T just like array of T is
 expressed by T[]. But indeed the issue is there is only one type of
 array of T, while there are an infinity of types of ranges of T.
 Your solution below is a good alternative.
 
 Anyway, if the source and target range are of the same (known) kind,
 something like this should work:

  struct MyRange(T) { ... }

  MyRange!Out map(In, Out)(MyRange!In input, Out delegate(In) f) {
  ...
  }

 If they are of different kinds, but still known, this should work:

  struct MySourceRange(T) { ... }
  struct MyTargetRange(T) { ... }

  MyTargetRange!Out map(In, Out)
  (MySourceRange!In input, Out delegate(In) f)
  {
  ...
  }

 Note that I am only talking about what the compiler should be able to
 figure out through IFTI (implicit function template instantiation), and
 not about actual implementation.
 
 Right, this is more or less what I was looking for. And I think I can
 restrict cases to ranges beeing of the same kind. If necessary, the
 result can then be mapped onto another kind of range (hopefully lazily).
 The only un-workaround-able situation is, I guess, when the source
 range is infinite ;-)

Why the reluctance to use template constraints?  They're so flexible! :)

-Lars


Re: higher-order funcs for ranges (with usual interface)

2011-02-03 Thread Lars T. Kyllingstad
On Thu, 03 Feb 2011 13:53:44 +0100, spir wrote:

 On 02/03/2011 01:17 PM, Lars T. Kyllingstad wrote:
 Why the reluctance to use template constraints?  They're so flexible!
 :)
 
 I cannot stand the is() idiom/syntax ;-) Dunno why. Would happily get
 rid of it in favor of type-classes (built eg as an extension to current
 interfaces). For instance, instead of:
 
  void func (T) (T t)
  if (is(someConstraint1)  is(someConstraint2))
  {
  ...
  }
 
 use:
 
  void func (SomeTypeClass T) (T t)
  {
  ...
  }
 
 For instance (untested):
 
  void func (T) (T t)
  if (isInputRange(T)  is(ElementType!T == E))
 --
  void func (InputRange!E T) (T t)
 
 where InputRange is a (templated) interface / type-class.
 
 Type-class checks on /type/ /template/ parameters (as opposed to type
 checks on regular value parameters) would be performed structurally (as
 opposed to nominally). D knows how to do this, since that's what it
 needs to perform when checking is() constraints.

I agree that is() is rather ugly.  Same with __traits.  If you haven't 
already done so, I suggest you vote up this issue:

  http://d.puremagic.com/issues/show_bug.cgi?id=3702

Anyway, you can hide is()'s ugliness in the most common cases, though, by 
defining new templates.  For instance, I wouldn't mind having the 
following in std.range as an overload of isInputRange:

  template isInputRange(R, T)
  {
  enum isInputRange = isInputRange!R  is(ElementType!R == T);
  }

Then, you'd simply write

  void func(R)(R range) if (isInputRange!(R, E)) { ... }

-Lars


Re: higher-order funcs for ranges (with usual interface)

2011-02-02 Thread Lars T. Kyllingstad
On Wed, 02 Feb 2011 13:26:39 +0100, spir wrote:

 Hello,
 
 This bit of code for arrays:
 
 Out[] map (In,Out) (In[] input, Out delegate (In) f) {
  Out[] output = new Out[](input.length); foreach (i,item ; input)
  output [i] = f(item);
  return output;
 }
 unittest {
  char character (uint code) {return cast(char)code;} uint[] codes =
  [0x61,0x62,0x63];
  // functional style
  writeln(map(codes, character));// abc // OO style
  writeln(codes.map(character)); // abc
 }
 
 How to write this for ranges? [...]

 For ranges, I'm looking for something similar to:
  Range!Out map (In,Out) (Range!In input, Out delegate (In) f) {...}
 Indeed, the compiler should understand that Range!T is a type id just
 like T[].

I don't think it's possible to do it exactly as you describe.  I mean, 
Range in that case can be anything, and you can't always return a range 
of the same kind.  Two possibilities are, you can do it eagerly,

  Out[] map(Range, In, Out)(Range input, Out delegate(In) f)
  if (isInputRange!Range  is(ElementType!Range : In))
  {
  ...
  }

or you can do it lazily by defining your own map range (untested):

  struct Map(Range, In, Out)
  if (isInputRange!Range  is(ElementType!Range : In)
  {
  Range input;
  Out delegate(In) f;

  @property bool empty() { return input.empty; }

  // Inefficient, should cache front...
  @property Out front() { return f(input.front); }
  
  void popFront() { input.popFront(); }
  }

  Map!(Range, Out) map(Range, In, Out)(Range input, Out delegate(In) f)
  if (isInputRange!R  is(ElementType!Range : In)
  {
  return typeof(return)(input, f);
  }

-Lars


Re: higher-order funcs for ranges (with usual interface)

2011-02-02 Thread Lars T. Kyllingstad
On Wed, 02 Feb 2011 13:18:07 +, Lars T. Kyllingstad wrote:

 [...]
 
   struct Map(Range, In, Out)
   if (isInputRange!Range  is(ElementType!Range : In)
   {
   Range input;
   Out delegate(In) f;
 
   @property bool empty() { return input.empty; }
 
   // Inefficient, should cache front... @property Out front() {
   return f(input.front); }
   
   void popFront() { input.popFront(); }
   }
 
   Map!(Range, Out) map(Range, In, Out)(Range input, Out delegate(In) f)
   if (isInputRange!R  is(ElementType!Range : In)
   {
   return typeof(return)(input, f);
   }

Oops, seems i missed a few closing parentheses on the template 
constraints.

-Lars


Re: default '==' on structs

2011-02-02 Thread Lars T. Kyllingstad
On Wed, 02 Feb 2011 15:55:53 +0100, spir wrote:

 Hello,
 
 What are the default semantics for '==' on structs?
 
 I ask this because I was forced to write opEquals on a struct to get
 expected behaviour. This struct is basically:
 
 struct Lexeme {
  string tag;
  string slice;
  Ordinal index;
 }
 
 Equal Lexeme's compare unequal using default '=='. When I add:
 
  const bool opEquals (ref const(Lexeme) l) {
  return (
 this.tag   == l.tag
   this.slice == l.slice
   this.index == l.index
  );
  }
 
 then all works fine. What do I miss?

I think the compiler does a bitwise comparison in this case, meaning that 
it compares the arrays' pointers instead of their data.  Related bug 
report:

  http://d.puremagic.com/issues/show_bug.cgi?id=3433

-Lars


Re: higher-order funcs for ranges (with usual interface)

2011-02-02 Thread Lars T. Kyllingstad
On Wed, 02 Feb 2011 18:38:02 +0100, spir wrote:

 On 02/02/2011 02:18 PM, Lars T. Kyllingstad wrote:
 On Wed, 02 Feb 2011 13:26:39 +0100, spir wrote:

 Hello,

 This bit of code for arrays:

 Out[] map (In,Out) (In[] input, Out delegate (In) f) {
   Out[] output = new Out[](input.length); foreach (i,item ; input)
   output [i] = f(item);
   return output;
 }
 unittest {
   char character (uint code) {return cast(char)code;} uint[] codes
   = [0x61,0x62,0x63];
   // functional style
   writeln(map(codes,character));// abc // OO style
   writeln(codes.map(character)); // abc
 }

 How to write this for ranges? [...]

 For ranges, I'm looking for something similar to:
   Range!Out map (In,Out) (Range!In input, Out delegate (In) f)
   {...}
 Indeed, the compiler should understand that Range!T is a type id just
 like T[].

 I don't think it's possible to do it exactly as you describe.  I mean,
 Range in that case can be anything, and you can't always return a range
 of the same kind.
 
 Right. The output range's ElementType is given by f's return type. As
 you say, the kind of range may change. Even if it's the same, how
 could one express that: range_which-elements-are-of-type-T,
 syntactically and in the param set, just like
 array_which-elements-are-of-type- is written T[]? Currently, we must
 (1) declare the range type as template param, which is a bit redondant
 because the ElementType must also be given, (2) add some 'is' horror
 code:
   if (isInputRange!Range  is(ElementType!Range : In))
 I guess the only solution would be for the compiler to support a kind of
 reange type syntax?

I'm not sure I understand what you mean here.  Perhaps you're looking for 
something like concepts, which have been discussed for both D and C++0x 
but rejected in both languages:

http://en.wikipedia.org/wiki/Concept_%28generic_programming%29


Anyway, if the source and target range are of the same (known) kind, 
something like this should work:

struct MyRange(T) { ... }

MyRange!Out map(In, Out)(MyRange!In input, Out delegate(In) f)
{
...
}

If they are of different kinds, but still known, this should work:

struct MySourceRange(T) { ... }
struct MyTargetRange(T) { ... }

MyTargetRange!Out map(In, Out)
(MySourceRange!In input, Out delegate(In) f)
{
...
}

Note that I am only talking about what the compiler should be able to 
figure out through IFTI (implicit function template instantiation), and 
not about actual implementation.


   Two possibilities are, you can do it eagerly,

Out[] map(Range, In, Out)(Range input, Out delegate(In) f)
if (isInputRange!Range  is(ElementType!Range : In))
{
...
}
 
 OK.
 
 or you can do it lazily by defining your own map range (untested):

struct Map(Range, In, Out)
if (isInputRange!Range  is(ElementType!Range : In)
{
Range input;
Out delegate(In) f;

@property bool empty() { return input.empty; }

// Inefficient, should cache front... @property Out front() {
return f(input.front); }

void popFront() { input.popFront(); }
}
 
 That's similar to what I did.
 
Map!(Range, Out) map(Range, In, Out)(Range input, Out delegate(In)
f)
if (isInputRange!R  is(ElementType!Range : In)
{
return typeof(return)(input, f);
}
 
 What's the point of map, then? My version initially had a 'MapRange'
 defined as static struct template inside map, but then map just
 instanciated it, so I suppressed map alltogether, letting the user
 write:
   auto r2 = MapRange!(R1, In, Out)(input, f);
 which is not more complicated than calling the func, I guess.

map() is just a helper function.   Unlike struct literals/constructors, 
functions can make use of IFTI, which makes for much prettier code:

// The range from my example, without map()
auto result =
Map!(SomeRange!int, int, bool)(someRange, someDelegate);

// The range from my example, with map()
auto result = map(someInputRange, someDelegate);

This has become a quite common idiom in Phobos.  std.range, for instance, 
is littered with helper functions like this:

  Retro, retro()
  Stride, stride()
  Chain, chain()
  ...

The list goes on.

-Lars


Re: std.format example not working

2011-01-29 Thread Lars T. Kyllingstad
On Fri, 28 Jan 2011 23:30:06 -0500, Akakima wrote:

 Firt, i would like to know if you are interested in receiving comments
 an bug reports for DMD V1.

D1 bugs are still fixed, so bug reports are welcome.

  http://d.puremagic.com/issues/

D1 has been declared stable, though, so there is usually no point in 
submitting enhancement requests for it.


 If yes, then the following example does not work:
 
 http://www.digitalmars.com/d/1.0/phobos/std_format.html
 
 import std.c.stdio;
 import std.format;
 void formattedPrint(...)
 {
   void putc(char c)  {fputc(c, stdout);} std.format.doFormat(putc,
   _arguments, _argptr);
 }
 
 
 declaring: void putc(dchar c) fixes the problem.

That's a bug in the documentation, please report. :)


 Also to a D newbee like me, _arguments and _argptr are confusing.
 
 _arginfo or _argtype is more significant. _argptr could be _arglist or
 _argvalue or _arguments
 
 Those names would be a better fit to the explanations given.

That, on the other hand, would be a breaking change, so it won't happen.

-Lars


Re: __gshared static versus static __gshared

2011-01-29 Thread Lars T. Kyllingstad
On Sat, 29 Jan 2011 08:47:21 +, %u wrote:

 Is this a bug?
 
__gshared static i;
 
 makes i be thread-local, while
 
static __gshared i;
 
 makes it be shared.

If that's the case, then it is definitely a bug.  The order of attributes 
shouldn't matter.

-Lars


Re: non-constant error for module AAs

2011-01-25 Thread Lars T. Kyllingstad
On Mon, 24 Jan 2011 10:45:03 -0500, Andrej Mitrovic wrote:

 Is this a bug?
 
 import std.stdio;
 
 string[string] values = [abc:abc, def:def];
 
 void main()
 {
 string[string] values2 = [abc:abc, def:def];
 }
 
 
 test.d(3): Error: non-constant expression [abc:abc,def:def]
 
 What's non-constant about that expression?


My guess would be that using an AA literal is just syntax sugar for 
calling an AA construction function, and that said function isn't 
CTFEable.

When you specify an initial value for a global, that value must be a 
compile-time constant.  If it's not, as in this case, the correct thing 
to do is to use a module constructor:

  string[string] values;
  static this()
  {
  values = [ abc:abc, def:def ];
  }

It is ONLY a good idea to use an enum array if you know you will be doing 
all lookups at compile time.  If the key you're looking for is just known 
at run time, the AA will be constructed anew for each lookup (I think), 
which is hideously expensive.

  enum string[string] values = [ abc:def, ghi:jkl ];

  // This is fine, because it is done at compile time.
  // It's essentially the same as:  auto s = def;
  auto s = values[abc];

  // This is a no-no, because it evaluates to something
  // like:  auto aa = values; auto s = aa[key];
  auto key = abc;
  auto s = values[key];

Here's an example program that demonstrates the difference.  On my 
machine, the enum AA version takes 22x longer than the normal AA 
version.


import std.datetime, std.stdio;


enum string[string] enumAA = [ abc : abc, def : def ];

string[string] normalAA;
static this()
{
normalAA = [ abc : abc, def : def ];
}


void main()
{
enum max = 10_000_000;
StopWatch sw;
string lookup1 = abc;
string lookup2 = def;

sw.start();
foreach (i; 0 .. max)
{
auto a = enumAA[lookup1];
auto b = enumAA[lookup2];
}
sw.stop();
writeln(sw.peek().seconds);

sw.reset();

sw.start();
foreach (i; 0 .. max)
{
auto a = normalAA[lookup1];
auto b = normalAA[lookup2];
}
sw.stop();
writeln(sw.peek().seconds);
}


Re: How to use std.bind?

2011-01-18 Thread Lars T. Kyllingstad
On Mon, 17 Jan 2011 17:03:15 +, Sean Eskapp wrote:

 I used to use boost::bind all the time, but std.bind has me stumped, as
 I keep getting static asserts with a cryptic argument has no
 parameters message. At this point, the code is just:
 
 class Foo
 {
   void bar(int i) { writeln(i); }
 }
 
 void main()
 {
   auto foobar = new Foo;
   bind(foobar.bar, 5)();
 }
 
 I've tried a myriad of different ways, but keep coming up with the same
 error. Using bindAlias gives me an error that std.bind.bindAlias(alias
 FT) is not a function template.
 
 I'm using DMD v2.051 on a Windows platform. Help anybody?

Like BlazingWhitester said, std.bind is scheduled for deprecation.  (It 
will be marked as such starting with the next DMD release.)  It is a 
relic from D1, and I don't think it has worked well with D2 for quite a 
while.

Luckily, you don't need it at all.  You can do the same thing with D2's 
built-in features, such as nested functions and lambdas.

  // Lambda example
  int add2(int i) { return i + 2; }

  void main()
  {
  auto seven = () { return add2(5); };
  assert (seven() == 7);
  }

-Lars


Re: std.container.Array/RefCounted(T) leaking memory?

2011-01-18 Thread Lars T. Kyllingstad
On Tue, 18 Jan 2011 01:16:51 +, %u wrote:

 I find it very hard to believe that struct dtors are never called.
 
 Sorry, that part was my bad -- last time I checked, they didn't get
 called, but maybe my example was too complicated, since they did get
 called for a *simple* example.
 
 However, here's a situation in which no postblit or destructor is called
 whatsoever:
 
 import std.stdio;
 struct S
 {
this(int dummy) { writeln(ctor); }
this(this) { writeln(postblit); }
~this() { writeln(dtor); }
 }
 S test(int depth) { return depth  0 ? test(depth - 1) : S(0); } int
 main(string[] argv) { test(3); }


That would be bug 3516, wouldn't it?

  http://d.puremagic.com/issues/show_bug.cgi?id=3516

-Lars


Re: Memory mapped IO

2011-01-10 Thread Lars T. Kyllingstad
On Sun, 09 Jan 2011 22:44:44 -0800, Dan Olson wrote:

 I'm exploring D for embedded work as a nice alternative to C/C++ for the
 32-bitters and am finding it has a nice set of features.  But, what is
 the best way handle memory mapped IO?  I don't see volatile like in C.
 Is writing asm {} the best way to ensure memory access?
 
 Thanks,
 Dan Olson

Would std.mmfile be what you need?

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

-Lars


Re: auto declarations

2011-01-10 Thread Lars T. Kyllingstad
On Fri, 07 Jan 2011 16:30:24 -0800, Jonathan M Davis wrote:

 On Friday, January 07, 2011 13:32:42 Ellery Newcomer wrote:
 auto a = 1, b = null;
 
 int a = 1, *b = null;
 
 
 [...]
 
 [...]
 
 However, I'm vere suprised that the first one succeeds. I think that it
 should be reported as a bug. All variables declared on the same line are
 supposed to have the same type.

If I remember correctly, TDPL explicitly states that you may use 
automatic type inference to declare variables of different types in one 
line.

-Lars


Re: Memory mapped IO

2011-01-10 Thread Lars T. Kyllingstad
On Mon, 10 Jan 2011 08:38:15 -0800, Dan Olson wrote:

 Lars T. Kyllingstad pub...@kyllingen.nospamnet writes:
 
 On Sun, 09 Jan 2011 22:44:44 -0800, Dan Olson wrote:

 I'm exploring D for embedded work as a nice alternative to C/C++ for
 the 32-bitters and am finding it has a nice set of features.  But,
 what is the best way handle memory mapped IO?  I don't see volatile
 like in C. Is writing asm {} the best way to ensure memory access?
 
 Thanks,
 Dan Olson

 Would std.mmfile be what you need?

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

 -Lars
 
 Ok, thanks.  So I see that is a wrapper for mmap.  So that would be good
 for user space code running on top of posix or win32.  But...

Ah, I should have read your post more closely.  I just saw memory mapped 
IO and latched onto that. :)


 I'm more interested in the general embedded case with a small OS or no
 OS (just ISRs and main loop).  I'm betting without volatile, asm {} is
 the next best thing for tickling a controllers peripheral registers?
 Yes/No?
 
 I searched the news groups and saw there used to be a volatile.  But it
 looks like it was done away with because of how it was misused (like C
 volatile) for thread sharing.  But this is different.  This is just
 telling the compiler not to optimize away an access.

AFAIK, that's right.  The compiler does not optimise across asm {} blocks.

-Lars


Re: Why does the example on page 8 of TDPL work without importing std.algorithm for splitter?

2011-01-04 Thread Lars T. Kyllingstad
On Mon, 03 Jan 2011 17:18:34 -0600, Ellery Newcomer wrote:

 If you're importing some other phobos module, I would guess an instance
 of this bug: http://d.puremagic.com/issues/show_bug.cgi?id=314
 
 On 01/03/2011 10:56 AM, Bryce Watkins wrote:
 However when I use splitter in my code it works without having imported
 std.algorithm.

That's right.  std.string does a public selective import of startsWith() 
and endsWith() from std.algorithm, and bug 314 causes the whole module to 
be imported publically.

314 is a huge, gaping hole in the module system.  AFAIK, it's a high-
priority bug, but also one that is very difficult to fix for some reason.

-Lars


Re: string comparison

2010-12-20 Thread Lars T. Kyllingstad
On Sun, 19 Dec 2010 07:01:30 +, doubleagent wrote:

 Andrei's quick dictionary illustration [in his book, 'The D Programming
 Language'] doesn't seem to work.  Code attached.

That's strange.  I ran the example you posted using DMD 2.050 myself, and 
it works for me.  Are you 100% sure that you are running this version, 
and that it is not using an outdated Phobos version (from an older 
installation, for instance)?

One suggestion:  Try replacing the next-to-last line with this:

  dictionary[word.idup] = newId;

The 'word' array is mutable and reused by byLine() on each iteration.  By 
doing the above you use an immutable copy of it as the key instead.


 On my computer, with d2-0.5.0, I got the following output while testing.
 
 andrei
 0 andrei
  andrei
 1 andrei
 
 
 Also, why doesn't 'splitter' show up on the site's documentation of
 std.string?  And what advantage does 'splitter(strip(line))' offer over
 'split(line)'?

splitter is defined in std.algorithm.  The fact that it becomes visible 
when you import std.string is due to bug 314:

  http://d.puremagic.com/issues/show_bug.cgi?id=314

(std.string is supposed to publically import just a few symbols from 
std.algorithm, but because of this bug the whole module gets imported 
publically.)

The advantage with splitter is that it is lazy and therefore more 
efficient.  split() is eager and allocates memory to hold the string 
fragments.

-Lars


Re: string comparison

2010-12-20 Thread Lars T. Kyllingstad
On Mon, 20 Dec 2010 18:44:12 +, doubleagent wrote:

 Are you 100% sure that you are running this version
 
 I have to be.  There are no other versions of phobos on this box and
 'which dmd' points to the correct binary.
 
  dictionary[word.idup] = newId;
 
 That fixes it.
 
 The 'word' array is mutable and reused by byLine() on each iteration. 
 By doing the above you use an immutable copy of it as the key instead.
 
 I REALLY don't understand this explanation.  Why does the mutability of
 'word' matter when the associative array 'dictionary' assigns keys by
 value...it's got to assign them by value, right?  Otherwise we would
 only get one entry in 'dictionary' and the key would be constantly
 changing.

This could be related to bug 2954, for which a fix will be released in 
the next version of DMD.

  http://d.puremagic.com/issues/show_bug.cgi?id=2954

-Lars


Re: random access-range without lower-power range kinds?

2010-12-14 Thread Lars T. Kyllingstad
On Tue, 14 Dec 2010 09:09:33 +0100, spir wrote:

 Hello,
 
 It seems impossible to define a random-access range (opIndex + length)
 alone. In fact, I cannot have it used by the language. Am I missing
 something? Random-access looks enough to provide fonctionality for both
 input and bidirectional ranges without any additional method. Lowering
 for forward iteration means I guess ;-)
   for (uint i=0 ; i  coll.length ; i++) {
   element = coll[i];
   doSomethingWith(element);
   }
 What is the reason for requiring methods of lower-power range types to
 be defined? (This makes 5 methods!)
 
 Denis
 -- -- -- -- -- -- --
 vit esse estrany ☣
 
 spir.wikidot.com


To avoid the boilerplate, you could write a mixin that defines the 
iteration primitives for you.

  mixin template IterationFuncs()
  {
  int index;
  bool empty() { return index == length; }
  auto front() { return opIndex(index); }
  void popFront() { ++index; }
  // ... etc.
  }

Then you'd just have to define opIndex() and length(), and the mixin does 
the rest for you.

  struct MyRange(T)
  {
  T opIndex(int i) { ... }
  @property int length() { ... }
  mixin IterationFuncs!();
  }

(I haven't tested the code above, so it probably has bugs, but you get 
the point.)

-Lars


Re: Passing functions to functionals

2010-12-01 Thread Lars T. Kyllingstad
On Tue, 30 Nov 2010 18:49:56 +0300, Dmitry Olshansky wrote:

 On 30.11.2010 14:59, Lars T. Kyllingstad wrote:
 In my library I have a lot of functionals (functions that take other
 functions as parameters).  Here is an example that shows the style I
 use to define them:

  // Example: Evaluate the function/delegate/functor f at x. auto
  eval(F, X)(F f, X x) { return f(x); }

  // Test
  void main()
  {
  int add2(int i) { return i + 2; }
  assert (eval(add2, 1) == 3);
  }

 In other words, the function is passed as a run-time parameter.  I've
 seen this (or similar) style used in Phobos, but there, I've also noted
 that functions are sometimes passed as template alias parameters:

  // Same as above, using template alias parameter. auto eval(alias
  f, X)(X x) { return f(x); }

  // Test
  void main()
  {
  int add2(int i) { return i + 2; }
  assert (eval!add2(1) == 3);
  }

 I'd be grateful if people would share their knowledge of the pros and
 cons of each method.  For instance, are there any situations where
 template alias parameters don't work?


 Thanks,

 -Lars
 alias parameters must be know/computable at compile time, quick example
 on what you can't do:
 
 import std.stdio;
 
 auto eval(F, X)(F f, X x) { return f(x); } auto eval2(alias f,X)(X x){
 return f(x); }
 
 auto summator(int k){
  int f(int val){
  return k + val;
  }
  return f;
 }
 
 
   // Test
 void main()
 {
   int add2(int i) { return i + 2; }
  int traceAdd2(int i){
  writeln(i, -- ,i+2);
  return i+2;
  }
  int delegate(int) getAdd2(){
  writeln(Getting add2);
  return add2;
  }
   assert(eval(add2, 1) == 3);
   assert(eval2!add2(1) == 3);
  assert(eval(summator(2),1) == 3);
  //Next one fails with
  //Error: closures are not yet supported in CTFE //Error: cannot
  evaluate summator(2) at compile time
  //assert(eval2!(summator(2))(1) == 3);
 
  assert(eval(traceAdd2,1) == 3);
  assert(eval2!traceAdd2(1) == 3); //side effect in call is no
  problem
 
  assert(eval(getAdd2,1) == 3);
  //Next one fails with
  //Error: cannot evaluate writeln(Getting add2) at compile time
  //Error: cannot evaluate getAdd2() at compile time
  //assert(eval2!(getAdd2())(1) == 3);
 }

That's a very good point, and pretty much settles it for me.  I'll stay 
away from alias parameters, then.  Thanks!

-Lars


Passing functions to functionals

2010-11-30 Thread Lars T. Kyllingstad
In my library I have a lot of functionals (functions that take other 
functions as parameters).  Here is an example that shows the style I use 
to define them:

// Example: Evaluate the function/delegate/functor f at x.
auto eval(F, X)(F f, X x) { return f(x); }

// Test
void main()
{
int add2(int i) { return i + 2; }
assert (eval(add2, 1) == 3);
}

In other words, the function is passed as a run-time parameter.  I've 
seen this (or similar) style used in Phobos, but there, I've also noted 
that functions are sometimes passed as template alias parameters:

// Same as above, using template alias parameter.
auto eval(alias f, X)(X x) { return f(x); }

// Test
void main()
{
int add2(int i) { return i + 2; }
assert (eval!add2(1) == 3);
}

I'd be grateful if people would share their knowledge of the pros and 
cons of each method.  For instance, are there any situations where 
template alias parameters don't work?


Thanks,

-Lars


Why is 'scope' so weak?

2010-11-23 Thread Lars T. Kyllingstad
If I've understood things correctly, by marking a delegate parameter with 
'scope' you tell the compiler not to create a true closure for the 
delegate.  Effectively you're saying I promise not to escape this 
delegate, so you don't need to copy its context to the heap.

In brief, my question is:  Why doesn't the compiler enforce this 
promise?  In particular, why is 'scope' not a type constructor?

(Note that this is mostly a question out of curiosity, and not really a 
proposal for a new feature.  I imagine it has been discussed in the past 
and rejected for some reason.)

Considering that the compiler enforces proper use of pure, nothrow, 
const, and all those other things, it doesn't seem much harder to do the 
same with scope.

As an example, I really can't see a reason why obviously wrong code like 
this should be allowed:

void delegate() globalDg;

void foo(scope void delegate() dg)
{
globalDg = dg;
}

Here's a slightly less obvious example, which also compiles successfully:

void foo(void delegate() dg);  // Who knows what this does?

void bar(scope void delegate() dg)
{
foo(dg);
}

-Lars


Re: delegate vs function

2010-11-23 Thread Lars T. Kyllingstad
On Tue, 23 Nov 2010 13:15:46 +0100, spir wrote:

 Hello,
 
 alias void function (int) F;
 alias void delegate (int) D;
 
 void fnFunc (F f, int i) {f(i);}
 void dgFunc (D d, int i) {d(i);}
 
 void writeOut (int i) {writeln(i);}
 
 void test () {
 void writeIn (int i) {writeln(i);}
 fnFunc(writeOut, 1);
 dgFunc(writeIn, 1);
 //~ fnFunc(writeIn, 1);// error (expected a func, got a
 delegate...) //~ dgFunc(writeOut, 1);   // error (... and
 conversely) }
 
 If a function is defined at the module's toplevel and then passed (via a
 pointer) to a higher-order func that expects a function, al works fine.
 But if it is defined inside a function, then the pointer is
 automatically typed as delegate, even if the function does not use any
 variable in scope, and I get an error.

Mark the function as 'static', like this:

  static void writeIn(int i) { ... }

Then the compiler even ensures that it doesn't use any symbols from the 
enclosing scope.


 Conversely, if the higher order
 func is defined to expect a delegate, then it fails if I pass a func
 defined at the top-level. How to solve this?

Use std.functional.toDelegate(), like this:

  dgFunc(toDelegate(writeOut), 1);

(For some reason the documentation for toDelegate() seems to be missing 
from the D web site, but I don't know why.  I'll look into it.)

-Lars


Re: delegate vs function

2010-11-23 Thread Lars T. Kyllingstad
On Tue, 23 Nov 2010 12:25:18 +, Lars T. Kyllingstad wrote:

 (For some reason the documentation for toDelegate() seems to be missing
 from the D web site, but I don't know why.  I'll look into it.)

Ah, found it:
http://d.puremagic.com/issues/show_bug.cgi?id=2581

-Lars


Re: Why is 'scope' so weak?

2010-11-23 Thread Lars T. Kyllingstad
On Tue, 23 Nov 2010 13:46:19 +0100, Lutger Blijdestijn wrote:

 Lars T. Kyllingstad wrote:
 
 If I've understood things correctly, by marking a delegate parameter
 with 'scope' you tell the compiler not to create a true closure for the
 delegate.  Effectively you're saying I promise not to escape this
 delegate, so you don't need to copy its context to the heap.
 
 In brief, my question is:  Why doesn't the compiler enforce this
 promise?  In particular, why is 'scope' not a type constructor?
 
 (Note that this is mostly a question out of curiosity, and not really a
 proposal for a new feature.  I imagine it has been discussed in the
 past and rejected for some reason.)
 
 Considering that the compiler enforces proper use of pure, nothrow,
 const, and all those other things, it doesn't seem much harder to do
 the same with scope.
 
 As an example, I really can't see a reason why obviously wrong code
 like this should be allowed:
 
 void delegate() globalDg;
 
 void foo(scope void delegate() dg)
 {
 globalDg = dg;
 }
 
 Most likely it is not yet implemented? It's hard to find something on
 this topic, I couldn't find anything in the spec or tdpl. I did found
 this one post by Andrei about your question:
 
 http://permalink.gmane.org/gmane.comp.lang.d.concurrency/617

Thanks.  He only says that ...too many qualifiers make the language 
quite baroque.  Hopefully there is a better reason than that. ;)

-Lars


Re: Why is 'scope' so weak?

2010-11-23 Thread Lars T. Kyllingstad
On Tue, 23 Nov 2010 10:17:08 +, Lars T. Kyllingstad wrote:

 If I've understood things correctly, by marking a delegate parameter
 with 'scope' you tell the compiler not to create a true closure for the
 delegate.  [...]

I just realised I posted this to the wrong group.  I'll repost to 
digitalmars.D, so please post answers there as well.

-Lars


CTFE of yl2x() and other intrinsics

2010-11-15 Thread Lars T. Kyllingstad
I thought that the compiler could evaluate all intrinsics at compile 
time, but this doesn't seem to be the case for std.math.yl2x().  Is my 
assumption wrong, or is this a bug that should be reported?

-Lars


Re: CTFE of yl2x() and other intrinsics

2010-11-15 Thread Lars T. Kyllingstad
On Mon, 15 Nov 2010 13:03:03 +, div0 wrote:

 On 15/11/2010 12:12, div0 wrote:
 On 15/11/2010 11:00, Lars T. Kyllingstad wrote:
 I thought that the compiler could evaluate all intrinsics at compile
 time, but this doesn't seem to be the case for std.math.yl2x(). Is my
 assumption wrong, or is this a bug that should be reported?

 -Lars

 Looks like it's not implemented because yl2x isn't in DMC. Dam and I
 thought it would be an easy one!

 Still I'll have a play with inline asm and see if it'll work.


 Sweet, I got it working! I'll submit a patch to bugzilla in a bit.

Cool! :)

-Lars


Re: 2 bool optional params

2010-11-10 Thread Lars T. Kyllingstad
On Wed, 10 Nov 2010 08:55:26 +0100, spir wrote:

 Hello,
 
 Is there a way for a func to hold 2 optional params of the same type?
   void f(int p, bool b1=false, bool b2=false) {
   writefln(p=%s b1=%s b2=%s, p,b1,b2);
}
 Or is there a workaroud?

I'm not sure I understand what you're asking for here.  Your example 
works for me.

-Lars


Re: custom exception type

2010-10-22 Thread Lars T. Kyllingstad
On Fri, 22 Oct 2010 13:00:43 +0200, spir wrote:

 Hello,
 
 Where can one find descriptions of Throwable, Error,  Exception? (I
 mean, how do you even know they exist?) I could finally guess the
 constructor must have a string parameter used for error output.

Well, they should be in the documentation for the 'object' module, but I 
see that they aren't.  Until that is fixed, you can check out the 
source.  Throwable starts at line 1210 here:

  http://www.dsource.org/projects/druntime/browser/trunk/src/object_.d

Exception and Error immediately follow it, but they don't really add 
anything to Throwable.


 Also, is it possible to implicitely reuse the superclass's constructor?
 I had to write:
 
 class E : Exception {
 this (string msg) {
 super(msg) ;
 }
 }
 
 E.this performs nothing new. But without it, I get a compiler error:
 trial.d(7): Error: constructor trial.E.this no match for implicit
 super() call in constructor
 Isn't the constructor inherited like other attributes?

No.  With the exception of a no-argument constructor, which Throwable 
doesn't have, you have to call it explicitly with super(...).


 Finally, is it possible to customize the error message construction,
 using eg tostring? A big issue is that, currently, an exception's
 message is computed at construction time, even if the exception will
 never be thrown, or more ccommonly never be output -- because it is
 caught by a 'catch' clause. In some cases, constructing the message can
 be costly; some programming schemes may throw huge numbers of
 exceptions, all caught (or nearly all). Example: in a parsing library,
 pattern match methods throw an instance of MatchFailure when matching
 fails. When there is a pattern choice, there may be numerous failures
 for each success. MatchFailure is just a clean way of signaling this
 fact (*): each failure exception is caught at a higher level to allow
 trying the alternative patterns. Since error messages can be rather
 complicated, constructing them uselessly would multiply parsing time by
 a rather big factor (in my case, ~ X 30!). I guess tostring is the right
 feature for this: it would return the exception's textual form, ie the
 message. (For information, this is how Python works.) I tried to use it,
 but it seems to be simply ignored. What is the func/method that
 constructs the text of an exception, eg what is implicitely called by
 writeln(e);?

That would be toString(), not tostring().

-Lars


Re: dmd 2.049 bug with take and SList?

2010-10-14 Thread Lars T. Kyllingstad
On Wed, 13 Oct 2010 18:06:15 +, Lars T. Kyllingstad wrote:

 On Wed, 13 Oct 2010 16:46:09 +, Nick Treleaven wrote:
 
 Hi,
 I'm new to D2 ranges but have been following D for some time. I'm
 posting here because I want to check if I'm doing anything wrong before
 filing a bug.
 
 The code below is a test case I made after hitting the problem in real
 code. Basically the pyramid recursive function should print out: [1, 2,
 3]
 [1, 2]
 [1]
 
 This works fine when calling with an int[] range, but calling with
 SList!int seems to make the compiler hang, eating up memory.
 
 Should I file a bug?
 
 
 import std.stdio;
 import std.range;
 import std.container;
 
 void pyramid(Range)(Range items)
 {
  if (items.empty)
  return;
  writeln(items);
  auto len = walkLength(items);
  auto r = take(items, len - 1);
  pyramid(r);
 }
 
 void main()
 {
  /* array version is fine */
  int[] arr = [1, 2, 3];
  pyramid(arr[]);
  
  SList!int list = [1, 2, 3];
  pyramid(list[]);/* infinite loop with dmd 2.049 */
 }
 
 
 You are creating an infinite recursion of templates.  For an array the
 return type of take() is the same array type.  For other ranges, the
 return type of take() is Take!Range.  So when you instantiate pyramid!
 Range, it instantiates pyramid!(Take!Range), and then
 pyramid!(Take!(Take! Range)), and so on ad infinitum.
 
 A solution could be to make take!(Take!Range)() just return another
 Take! Range.  I can look into that, but you should file a bug report on
 it so it's not forgotten.
 
 -Lars

http://d.puremagic.com/issues/show_bug.cgi?id=5052


Re: dmd 2.049 bug with take and SList?

2010-10-14 Thread Lars T. Kyllingstad
On Thu, 14 Oct 2010 06:54:17 +, Lars T. Kyllingstad wrote:

 On Wed, 13 Oct 2010 18:06:15 +, Lars T. Kyllingstad wrote:
 
 On Wed, 13 Oct 2010 16:46:09 +, Nick Treleaven wrote:
 
 Hi,
 I'm new to D2 ranges but have been following D for some time. I'm
 posting here because I want to check if I'm doing anything wrong
 before filing a bug.
 
 The code below is a test case I made after hitting the problem in real
 code. Basically the pyramid recursive function should print out: [1,
 2, 3]
 [1, 2]
 [1]
 
 This works fine when calling with an int[] range, but calling with
 SList!int seems to make the compiler hang, eating up memory.
 
 Should I file a bug?
 
 
 import std.stdio;
 import std.range;
 import std.container;
 
 void pyramid(Range)(Range items)
 {
 if (items.empty)
 return;
 writeln(items);
 auto len = walkLength(items);
 auto r = take(items, len - 1);
 pyramid(r);
 }
 
 void main()
 {
 /* array version is fine */
 int[] arr = [1, 2, 3];
 pyramid(arr[]);
 
 SList!int list = [1, 2, 3];
 pyramid(list[]);/* infinite loop with dmd 2.049 */
 }
 
 
 You are creating an infinite recursion of templates.  For an array the
 return type of take() is the same array type.  For other ranges, the
 return type of take() is Take!Range.  So when you instantiate pyramid!
 Range, it instantiates pyramid!(Take!Range), and then
 pyramid!(Take!(Take! Range)), and so on ad infinitum.
 
 A solution could be to make take!(Take!Range)() just return another
 Take! Range.  I can look into that, but you should file a bug report on
 it so it's not forgotten.
 
 -Lars
 
 http://d.puremagic.com/issues/show_bug.cgi?id=5052

Fixed.
http://www.dsource.org/projects/phobos/changeset/2102


Re: writing

2010-10-14 Thread Lars T. Kyllingstad
On Thu, 14 Oct 2010 09:58:36 +0200, spir wrote:

 Hello,
 
 write and writeln just write; writef and writefln first format: seems
 clear. But the latter do not work properly with D strings, and the
 former do not work without format. Is there a practical way to just
 write anything to the terminal (without caring of its type)?
 
 Is there some rationale about this?
 Would it be possible to automatically add \0 to D strings passed to
 write/writeln (can a programmer define a custom func doing this before
 delegating to builtin funcs, or is it necessarily a job for the
 compiler?)? And/or what about having writef/writefln use %s as default
 format (when the first arg is not a string)?


I don't understand what you mean.  This works just fine:

  import std.stdio;

  void main()
  {
  string s = Hello world!;
  writeln(s);
  }

If I'm misunderstanding you, please explain, or perhaps give a code 
example.

-Lars


Re: toString(char*)?

2010-10-11 Thread Lars T. Kyllingstad
On Mon, 11 Oct 2010 21:46:26 +0200, Lutger wrote:

 Where can I find the function to convert from c-style string to a normal
 D string? It used to be toString in std.string, but that one is
 deprecated.
 
 Thanks.

import std.conv;

const char* cString;
string dString = to!string(cString)

-Lars


Re: toString(char*)?

2010-10-11 Thread Lars T. Kyllingstad
On Mon, 11 Oct 2010 22:00:37 +0200, Lutger wrote:

 Lars T. Kyllingstad wrote:
 
 On Mon, 11 Oct 2010 21:46:26 +0200, Lutger wrote:
 
 Where can I find the function to convert from c-style string to a
 normal D string? It used to be toString in std.string, but that one is
 deprecated.
 
 Thanks.
 
 import std.conv;
 
 const char* cString;
 string dString = to!string(cString)
 
 -Lars
 
 Oh wow, I didn't knew that would work. Awesome.

I don't think it works the other way, though, you still have to use 
std.string.toStringz().

-Lars


Re: lvalue method

2010-10-08 Thread Lars T. Kyllingstad
On Fri, 08 Oct 2010 09:33:22 +0200, Benjamin Thaut wrote:

 Hi, I'm writing a vec4 math struct and I have a method of which the
 return value has to be a lvalue so I wonder which is the correct way to
 do this:

 vec4 Normalize() const { ... } //won't work, not a lvalue
 
 ref vec4 Normalize() const {
vec4 temp;
...
return temp;
 } //will this lead to a segfault or not?

The compiler shouldn't even accept this.  When I try a similar thing, DMD 
says Error: escaping reference to local variable temp.


 ref vec4 Normalize() const {
vec4* temp = new vec4;
...
return *temp;
 } //ugly, don't want to allocate anything on the heap

This would work, since the variable is no longer on the stack and thus 
survives the return of the function.


 auto ref vec4 Normalize() const {
vec4 temp;
...
return temp;
 } //will this lead to a segfault?

Well, that should compile, but it doesn't work the way you want.  'auto 
ref' means that the function returns by ref if the return expression is 
an lvalue *and it would not be a reference to a local or a parameter*.  
So for this example, your function would return by value, not by ref.

 
 Or do I need to do it totaly in some other way?

Yes, you do. :)  You are trying to create a variable on the stack, and 
return it by reference.  The problem is that when the function returns, 
its stack frame (the memory occupied by the function's local variables) 
is released.  At that point the variable doesn't exist anymore, and any 
reference to it would be invalid.

-Lars


Re: Stop function parameters from being copied.

2010-10-07 Thread Lars T. Kyllingstad
On Thu, 07 Oct 2010 14:43:25 +, Benjamin Thaut wrote:

 If I want to tell the compiler that a certain function argument should
 not be copied (say a large struct, or a array) which is the right way to
 do?
 
 arrays:
 1. function foo(in float[] bar) { ... } 2. function foo(ref
 const(float[]) bar) { ... } 3. something else


Just to complement what Steven and Simen have already said, I always find 
it useful to think of arrays as structs.  For instance, int[] is 
equivalent to

struct IntArray
{
size_t length;
int* ptr;
}

where ptr contains the memory location of the array data.  (In fact, the 
above is not only a conceptual equivalence.  The struct above is exactly, 
bit for bit, how a D array is implemented.)

Fixed-size arrays (aka. static arrays), on the other hand, are value 
types, so there the equivalence goes something like

// int[3]
struct IntArray3
{
int element0;
int element1;
int element2;
}

Therefore, if you want to pass large fixed-size arrays to a function, 
you'd better use 'ref' like you would with large structs.

-Lars


Re: Destruction Sequence: module and classes defined within

2010-10-06 Thread Lars T. Kyllingstad
On Tue, 05 Oct 2010 23:25:36 +0200, vano wrote:

 The code below:
  module used;
 
  import std.stdio;
 
  class ClassA {
  this()  { writeln(A ctor); }
  ~this() { writeln(A dtor); }
  }
 
  static this()  { writeln(used.sctor); } static ~this() {
  writeln(used.sdtor); }
 
  void main() {
  auto a = new ClassA();
  }
 produces the following output (DMD v2.049):
  used.sctor
  A ctor
  used.sdtor
  A dtor
 
 The question is: should the module be allowed to be unloaded before all
 module-level objects/structures are destructed/unloaded?


I'm no expert on this, but I think it has to be that way.  Consider this:

  class Foo { ... }
  Foo foo;

  static this()
  {
  foo = new Foo;
  }

  static ~this()
  {
  foo.doStuff();
  }

So you see, if foo had already been destroyed and garbage collected, my 
program would have crashed when the module static destructor was run.  
Thus, I guess, running the garbage collector for the final time has to be 
one of the last things done on program shutdown, after running all module 
destructors.

-Lars


Initialisation of static immutable arrays

2010-10-06 Thread Lars T. Kyllingstad
I have a program that uses an immutable array, the contents of which are 
known at compile time.  Thus, ideally, I want it to be placed in 
the .rodata segment of the program.

Firstly, I seem to remember reading that using an array literal in D will 
always result in a heap allocation.  Is this correct?

Secondly, if the above is not true, how can I verify that the array in 
the following piece of code isn't allocated and/or copied anew every time 
the program runs, or even worse, every time foo() is called?

  void foo()
  {
  static immutable int[3] = [1, 2, 3];
  }

I know, RTFAsm, but some help with that would be appreciated. ;)

Thirdly, intuition tells me that when the array is immutable, the 
'static' shouldn't have an effect.  But experiments (i.e. printing the 
adress of the array) indicate that it does.  Is there some reason for 
this, or is it just a shortcoming of the compiler?

-Lars


Re: Initialisation of static immutable arrays

2010-10-06 Thread Lars T. Kyllingstad
On Wed, 06 Oct 2010 10:16:45 +, Lars T. Kyllingstad wrote:

   static immutable int[3] = [1, 2, 3];

..should of course be

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

-Lars


Re: Initialisation of static immutable arrays

2010-10-06 Thread Lars T. Kyllingstad
On Wed, 06 Oct 2010 07:39:48 -0400, Steven Schveighoffer wrote:

 On Wed, 06 Oct 2010 06:16:45 -0400, Lars T. Kyllingstad
 pub...@kyllingen.nospamnet wrote:
 
 [...]
 
 Secondly, if the above is not true, how can I verify that the array in
 the following piece of code isn't allocated and/or copied anew every
 time the program runs, or even worse, every time foo() is called?

   void foo()
   {
   static immutable int[3] = [1, 2, 3];
   }
 
 Actually, static probably will prevent it from being created every time
 foo is called.  I don't think there's a way to prevent it from being
 created every time the program is run.

Does anyone know a way to verify this?  (If it is in fact created every 
time the function runs, I'll change it to a module-level array 
initialised in a 'static this()' instead.)


 I know, RTFAsm, but some help with that would be appreciated. ;)

 Thirdly, intuition tells me that when the array is immutable, the
 'static' shouldn't have an effect.  But experiments (i.e. printing the
 adress of the array) indicate that it does.  Is there some reason for
 this, or is it just a shortcoming of the compiler?
 
 Of course.  If you realize that the expression [1,2,3] is not immutable,
 then it makes sense.
 
 Another example to help you think about it:
 
 void foo(int x)
 {
 immutable int[3] = [1,2,x];
 }
 
 This must be run on every call of foo, because x can vary.

I don't think that is a very good reason.  The compiler could detect the 
special (and, might I add, common) case where an array literal whose 
contents are known at compile time is assigned to an immutable variable, 
and treat it as immutable even though [1,2,3] is formally of type int[].


 BTW, I'm all for making array literals immutable.  You can always make
 runtime-allocated arrays via a library function.

I completely agree.

-Lars


Re: Associative arrays give compile error

2010-10-05 Thread Lars T. Kyllingstad
On Tue, 05 Oct 2010 12:50:44 +0100, Bob Cowdery wrote:

 On 05/10/2010 12:40, Bob Cowdery wrote:
  On 05/10/2010 12:13, Denis Koroskin wrote:
 On Tue, 05 Oct 2010 15:08:39 +0400, Bob Cowdery
 b...@bobcowdery.plus.com wrote:

  On 05/10/2010 12:04, Denis Koroskin wrote:
 On Tue, 05 Oct 2010 14:57:22 +0400, Bob Cowdery
 b...@bobcowdery.plus.com wrote:

  On 05/10/2010 11:45, Denis Koroskin wrote:
 On Tue, 05 Oct 2010 14:23:47 +0400, Bob Cowdery
 b...@bobcowdery.plus.com wrote:

  I can't seem to get any sense out of associative arrays. Even
  the
 simplest definition won't compile so I must be doing something
 daft.

 int[string] aa = [hello:42];

 Error: non-constant expression [hello:42]

 What exactly is not constant about this. The example is straight
 out the
 book. Using D 2.0.

 bob
 What exactly compiler version are you using (run dmd with no
 args)? Works perfectly fine here (dmd2.049).
 It says 2.049. How odd. I've got a fair amount of code and
 everything else compiles fine.
 Can you please post complete code snippet that fails to compile?

 Here is the code I used to test:

 module aa;

 import std.stdio;

 void main()
 {
 int[string] aa = [hello:42];
 writeln(aa[hello]);
 }

 # dmd -run aa.d
 Ah! It's some other code below it that is not giving an error but
 causing the error above. So the compiler is getting confused. What I
 was actually trying to do was create an associative array with a
 string as a key and a Tuple as the value. Now

 auto aa = [
 some string: (100.0, 6100.0)
 ]

 compiles but is clearly wrong and gives rise to other errors.  Does
 anyone know the correct way to define this and then access the tuple.
 import std.stdio;
 import std.typecons;

 void main()
 {
 auto aa = [hello: tuple(100.0, 6100.0)]; auto result =
 aa[hello];
 
 writeln(result.field[0],  , result._1); // primary and
 alternative way
 }
 Thanks. I've established that works for me and also that the actual
 array I'm using also works in the test program but it won't compile in
 the real program. I've commented everything else out of the file and
 just left...

 import std.typecons;

 auto A_RX_FILT = [
 6K0: tuple(100.0, 6100.0),
 2K4: tuple(300.0, 2700.0),
 2K1: tuple(300.0, 2400.0),
 1K0: tuple(300.0, 1300.0),
 500: tuple(500.0, 1000.0),
 250: tuple(600.0, 850.0),
 100: tuple(700.0, 800.0)
 ];

 I get an error on every line:
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(100,6100) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(300,2700) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(300,2400) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(300,1300) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(500,1000) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(600,850) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(700,800) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(100,6100) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(300,2700) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(300,2400) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(300,1300) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(500,1000) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(600,850) at
 compile time|
 Definitions\dspDefs.d|51|Error: cannot evaluate tuple(700,800) at
 compile time|
 ||=== Build finished: 14 errors, 0 warnings ===|

 This is a bit worrying now. I moved the array into the file that uses
 it but I still get the same errors. Any ideas?


 Oh dear, this is getting worse and worse. I've still got problems with a
 simple definition. If I take out the one with the tuple and leave in
 this one:
 
 enum E_MODE
 {
   LSB,//  0
   USB,//  1
   DSB,//  2
   CWL,//  3
   CWU,//  4
   FMN,//  5
   AM,//  6
   DIGU,//  7
   SPEC,//  8
   DIGL,//  9
   SAM,// 10
   DRM// 11
 }
 // Associative array for translation
 auto A_MODE = [
 LSB: E_MODE.LSB,
 USB: E_MODE.USB,
 DSB: E_MODE.DSB,
 CWL: E_MODE.CWL,
 CWU: E_MODE.CWU,
 FMN: E_MODE.FMN,
 AM: E_MODE.AM,
 DIGU: E_MODE.DIGU,
 SPEC: E_MODE.SPEC,
 DIGL: E_MODE.DIGL,
 SAM: E_MODE.SAM,
 DRM: E_MODE.DRM
 ];
 
 I get:
 Definitions\dspDefs.d|25|Error: non-constant expression
 [LSB:cast(E_MODE)0,USB:cast(E_MODE)1,DSB:cast(E_MODE)2,CWL:cast
(E_MODE)3,CWU:cast(E_MODE)4,FMN:cast(E_MODE)5,AM:cast(E_MODE)
6,DIGU:cast(E_MODE)7,SPEC:cast(E_MODE)8,DIGL:cast(E_MODE)
9,SAM:cast(E_MODE)10,DRM:cast(E_MODE)11]|
 ||=== Build finished: 1 errors, 0 warnings ===|
 
 Something is seriously broken here.

No, nothing is 

Re: Segmentation fault on closing file in destructor

2010-09-27 Thread Lars T. Kyllingstad
On Sun, 26 Sep 2010 20:55:33 +0200, Tom Kazimiers wrote:
 If I would use std.stdio.File, what would be different?

Well, for one thing you won't have to write your code all over again when 
std.stream is deprecated, which will happen soon.  std.stdio.File is 
really what you should use for file I/O in new code.

That said, there's a chance it does exactly what you want.  You don't 
have to open a file on construction, there's an open() function which 
opens a file and assigns it to the File handle.  Nor do you have to worry 
about closing the file in the destructor, as it is automatically closed 
the moment the last reference to it goes out of scope.

Here are a few examples of how to use it:

  File file;// File's a struct, so no need to use 'new'

  // Read a text file line by line
  file.open(foo.txt);
  foreach (line; file.byLine())  writeln(line);

  // Read a binary file in 4MB chunks
  file.open(foo.dat);
  foreach (ubyte[] chunk; file.byChunk(4*1024))
  doStuffWith(chunk);

  // Read up to 100 ints from a file
  file.open(myInts);
  auto buffer = new int[100];
  auto data = file.rawRead(buffer);
  
-Lars


Re: Where is module dstats.all for dflplot?

2010-09-20 Thread Lars T. Kyllingstad
On Sat, 18 Sep 2010 07:15:35 -0400, Sam Hu wrote:

 Greetings!
 
 I want to have a try on dflplot.But I don't find module dstats.all which
 is used by dflplot.d,could anybody let me where it is?
 
 Thank you.


Hi!

David Simcha (the dflplot author) has changed the name of the library to 
Plot2Kill, so if you're still using dflplot, it's an old version.  Check 
out the Plot2Kill project for the latest version:

  http://www.dsource.org/projects/plot2kill

As far as I know, dstats is not required to use Plot2Kill, it's only used 
for the demo/test application.  Anyway, if you need it, you can find it 
here:

  http://www.dsource.org/projects/dstats


-Lars


Re: How to avoid the console from apearing.

2010-08-19 Thread Lars T. Kyllingstad
On Wed, 18 Aug 2010 13:50:34 -0400, Nick Sabalausky wrote:

 Steven Schveighoffer schvei...@yahoo.com wrote in message
 news:op.vhl46mdneav...@localhost.localdomain...

 Changes are afoot to std.process, we recently got a blocker fixed (not
 yet in svn, but someone submitted a correct patch)


 Issue #?

3979


Re: rdmd only works with files in current directory on Windows?

2010-08-15 Thread Lars T. Kyllingstad
On Sat, 14 Aug 2010 14:58:05 +0200, simendsjo wrote:

 c:\temp\src\test.d
 
 c:\temprdmd src\test
 The system cannot find the path specified.
 
 c:\temprdmd src/test
 std.file.FileException: (...)\.rdmd\rdmd-src/test.d-(...): The system
 cannot find the path specified.
 
 Using rdmd 20090902, dmd 2.048 and 64 bit win7

It doesn't work on Linux either, you have to be in the same directory as 
the source file.  But I'm not sure it was ever supposed to work, i.e. 
Andrei didn't account for that use when he wrote it.  If you really want 
this to work, you could submit an enhancement request to bugzilla.

-Lars


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 17:35:56 -0700, Jonathan M Davis wrote:

 On Monday, August 09, 2010 17:09:03 simendsjo wrote:
 On 10.08.2010 02:09, Jonathan M Davis wrote:
  On Monday, August 09, 2010 16:59:07 bearophile wrote:
  simendsjo:
  Ahem.. :) Yes, I did miss your answer! How I got fooled by the
  preview pane and never noticed the scrollbar.
  
  No problem, it happens, don't worry.
  
  I cannot see how your other bug report relates to this though.
  
  My other bug report is about this line in your code:
if (delimiter == null)
  
  I don't like it :-)
  
  Bye,
  bearophile
  
  Why, because it should be
  
  if(delimiter is null)
  
  
  or just
  
  if(!delimiter)
  
  
  - Jonathan M Davis
 
 Hehe.. You're a bit beyond my D level right now. At least I now know
 null == false and you can do reference is null :)
 
 IIRC, you're not really supposed to do delim == null but rather us
 delim is null or shorten to to just !delim. Why, I don't recall off
 the top of my head, but it might be because delim == null would be
 calling Object.opEquals(), and there's no need for that function call
 (though fortunately delim == null translates to Object.opEquals(delim,
 null) rather than delim.opEquals(null) which avoids issues where the lhs
 is null and causes it to go boom).
 
 In either case, for null checks, I'd suggest either just using the
 reference by itself or to explictly use is null if you want the extra
 clarity.

No, using 'is' won't work.  Check this out:

  int[] a;
  assert (a == null);
  assert (a is null);

  a = new int[10];
  a.length = 0;
  assert (a == null);
  assert (a !is null);

The thing is, '==' tests whether two arrays are equal, that is, that they 
are equally long and that their elements are equal.  Any empty array is 
equal to null -- in fact, in this context 'null' is just a way of 
denoting an empty array that doesn't point to any particular memory block 
(i.e. hasn't been initialised yet).

  // This is what '==' does
  bool mimicEquals(int[] a, int[] b)
  {
  if (a.length != b.length) return false;
  foreach (i; 0 .. a.length) if (a[i] != b[i]) return false;
  return true;
  }

'is', on the other hand, tests whether two arrays are identical, i.e. 
that they have the same length and *refer to the same piece of memory*.

  // This is (sort of) what 'is' does
  bool mimicIs(int[] a, int[] b)
  {
 return (a.ptr == b.ptra.length == b.length);
  }

-Lars


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Tue, 10 Aug 2010 01:48:17 -0700, Jonathan M Davis wrote:

 On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote:
 No, using 'is' won't work.  Check this out:
 
   int[] a;
   assert (a == null);
   assert (a is null);
 
   a = new int[10];
   a.length = 0;
   assert (a == null);
   assert (a !is null);
 
 The thing is, '==' tests whether two arrays are equal, that is, that
 they are equally long and that their elements are equal.  Any empty
 array is equal to null -- in fact, in this context 'null' is just a way
 of denoting an empty array that doesn't point to any particular memory
 block (i.e. hasn't been initialised yet).
 
   // This is what '==' does
   bool mimicEquals(int[] a, int[] b)
   {
   if (a.length != b.length) return false; foreach (i; 0 ..
   a.length) if (a[i] != b[i]) return false; return true;
   }
 
 'is', on the other hand, tests whether two arrays are identical, i.e.
 that they have the same length and *refer to the same piece of memory*.
 
   // This is (sort of) what 'is' does
   bool mimicIs(int[] a, int[] b)
   {
  return (a.ptr == b.ptra.length == b.length);
   }
 
 -Lars
 
 Actually, it looks to me that that's an argument for using is for
 checking for null rather than ==, since == isn't really going to tell
 you. The fact that == doesn't care about whether an array is null makes
 it not work for checking for whether an array is null.

I guess it depends on what behaviour you're after.  In the present case, 
if you want chomp(a, null) and chomp(a, ) to do the same thing, then 
you should use '=='.  If you want chomp(a, ) to simply do nothing, use 
'is'.  I just figured that the former was the desired behaviour here.  If 
it isn't, I agree with you. :)


 1. As I understand it, using is instead of == is for all references, not
 just arrays and their bizarre pseudo-null state. Using is with a class
 will avoid calling opEquals() and does exactly what you want when
 checking whether a class reference is null.

Fun fact: Actually, 'is' works for any type.

  assert (1 is 1);

As I've understood it, 'a is b' is true if the variables a and b contain 
the exact same bits.  If a and b are value types, this must mean they 
have the same value, and if they are references (including arrays), it 
means they refer to the same data.


 2. For arrays, if you want to check whether it really is null, then you
 _must_ use is, because == obviously isn't going to tell you. It'll just
 lump empty arrays in with null ones. For instance, if you want to check
 that an array has never been initialized or that it has been set to null
 and never set to something else, then you need to use is.
 
 3. On the other hand, if what you really care about is checking whether
 an array has any elements and you don't care about whether it's null or
 not, then the empty function/property would be the better way to go.
 It's quite explicit, and it's more generic, doing things the way that
 ranges are done.

I totally agree with you.  Lately, I have started using empty (as well 
as the other range primitives) for arrays myself.  I just disagreed that 
'is' would produce what I perceived to be the right behaviour for the 
function in question.  But that perception may well be wrong. ;)


 Personally, I think that the way that null is handled with arrays and
 associative arrays is a poor design choice (if they're null, they should
 be null until you assign to them with new rather than this whole null
 but not null nonsense), but we're stuck with it I guess.

There, I don't agree with you.  Arrays are a sort of pseudo-reference 
type, so I don't mind 'null' being a sort of pseudo-null in that 
context.  Actually, I find it to be quite elegant.  It's a matter of 
taste, I guess.

-Lars


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Tue, 10 Aug 2010 07:50:34 -0400, bearophile wrote:

 Lars T. Kyllingstad:
 There, I don't agree with you.  Arrays are a sort of pseudo-reference
 type, so I don't mind 'null' being a sort of pseudo-null in that
 context.  Actually, I find it to be quite elegant.  It's a matter of
 taste, I guess.
 
 I suggest you to write down the things you don't like and the design you
 desire here.

??

I like how it is designed now, that was my point.

-Lars


Re: Problem with std.array(std.regex.splitter())

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 07:31:21 -0400, bearophile wrote:

 Jonathan M Davis:
 Well, the requirement for save() being part of a forward range is
 fairly recent, and a bunch of ranges which are supposed to be forward
 ranges don't have them even though they're supposed to. The change was
 made fairly close to the release of 2.047, I believe, and it was missed
 for many ranges. It's mostly if not entirely fixed in svn. Actually, if
 I try and compile Bearophile's code on my machine (which has a fairly
 recent version of phobos), it compiles just fine.
 
 I have tried the latest beta and indeed it works, thank you. Where can I
 find information about the purposes and meaning of save()? TDPL?


It should be in the documentation of std.range.isForwardRange(), but 
Andrei seems to have forgotten it.  He did describe it in his 'On 
Iteration' article, though:

http://www.informit.com/articles/article.aspx?p=1407357

Check out page 7, section 'Forward Ranges'.  (I think the whole article 
is worth reading, if you haven't already -- it really helped me 
understand ranges.)

-Lars


Re: Casting away const

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 10:35:02 -0400, Steven Schveighoffer wrote:

 On Mon, 09 Aug 2010 10:27:09 -0400, Don nos...@nospam.com wrote:
 
 Steven Schveighoffer wrote:
 On Mon, 09 Aug 2010 09:57:47 -0400, bearophile
 bearophileh...@lycos.com wrote:

 Steven Schveighoffer:
 I thought it was you're on your own, not undefined behavior.  The
 former
 implies there is some right way to do this if you know more about
 the
 data than the compiler, the latter implies that there is no right
 way to
 cast away const.  Am I wrong?

 In my opinion if this thing is well designed then you go in undefined
 behaviour only when you change the contents of something after you
 have removed its const nature with a cast. Just casting const away
 and then reading the data can't be undefined behaviour, otherwise
 casting const away is useless and can be totally disallowed.
  Casting away const just to read the data is useless.  You can read
 const data without a cast.

 No you can't. You can't pass it to a C function.
 
 Sure you can.
 
 extern(C) int strlen(const(char) *arg);
 
 
  But my understanding is that casting away const to write should be
 doable if you know what you're doing.  If this is undefined behavior,
 then that's fine, I'm just unclear on what undefined behavior
 actually means.  I thought undefined behavior means that you cannot
 count on the behavior to work in the future.
  An example of where casting away const to write should be allowed is
 for a hypothetical mutable member:
  class C
 {
private Mutable!(int) cache = -1;
int expensiveFunction() const { return cache == -1 ? cache =
 _expensiveFunctionImpl() : cache; }
private int _expensiveFunctionImpl() const {...}
 }
  If this is undefined, then something like this cannot be relied on,
 even when performance is critical.
  -Steve

 I really can't see how the compiler could make that work, without
 destroying most of the benefits of const. For example, if that code is
 legal, it disallows most const-related optimisation.
 
 Why not?  What possible optimization can the compiler do here?  Mutable
 has an assign operation that is labeled as const, it should be callable
 by the compiler.
 
 I haven't really seen what const optimizations can be, so maybe an
 example (even if unimplemented) is helpful.

The compiler does an optimization on const/immutable struct members 
which I reported as a bug:

  http://d.puremagic.com/issues/show_bug.cgi?id=3449

-Lars


Re: std.string.chomp error

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 18:58:36 +0200, simendsjo wrote:

 The documentation says
 /***
   * Returns s[] sans trailing delimiter[], if any. * If delimiter[] is
   null, removes trailing CR, LF, or CRLF, if any. */
 
 To adhere to the documentation, chomp must be changed from:
 
 C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (endsWith(s, delimiter))
  {
  return s[0 .. $ - delimiter.length];
  }
  return s;
 }
 
 to:
 
 C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (delimiter == null)
return chomp(s);
  else if (endsWith(s, delimiter))
return s[0 .. $ - delimiter.length];
  else
return s;
 }


Either that, or the documentation for it needs to be changed.  Anyway, it 
would be great if you'd report this.

http://d.puremagic.com/issues/

Thanks!

-Lars


Re: Wanting an immutable associative array in a class

2010-07-30 Thread Lars T. Kyllingstad
On Thu, 29 Jul 2010 22:55:35 -0400, bearophile wrote:

 RedZone:
 But it would be nice if I could have the array reference itself be
 immutable and not just the array's contents.  Is there any way I could
 do this?
 
 Let's say your code is as your second example:
 
 class Foo {
 private:
 immutable int[string] bar;
 
 public:
 this() {
 bar = [AB:1, CD:2, EF:3];
 }
 }
 
 void main() {
 auto f = new Foo;
 }
 
 
 How can you change the array reference outside the class constructor?


But that was not his second example. :)  His second example used the type

  immutable(int)[char[]]

while you used the correct one,

  immutable(int[char[]])

RedZone:  Even though the overall type is immutable, you can still set it 
in a constructor, like bearophile showed.

May I also suggest a small improvement?  Doing it like this means that 
the array will be constructed anew every time you create an instance of 
the class.  If it's meant to be immutable, and you know all the elements 
of the array at compile time, that's just wasteful.  In that case, it's 
probably better to make it a static member variable, and set its value in 
a static constructor.  That way it will only get constructed once, at 
program startup.

  class Foo
  {
  private:
  static immutable int[string] bar;

  static this()  // Only run when program loads
  {
  bar = [AB: 1, CD: 2, EF: 3];
  }

  public:
  ...
  }

-Lars


Re: exern (C) linkage problem

2010-07-20 Thread Lars T. Kyllingstad
On Mon, 19 Jul 2010 18:01:25 -0400, bearophile wrote:

 typedef char* Cstring;
 extern(C) Cstring strcmp(Cstring s1, Cstring s2); ...
 
 You can use just a struct too:
 
 import std.string: toStringz;
 
 struct Cstring {
 const(char)* ptr;
 }
 
 extern(C) Cstring strcmp(Cstring s1, Cstring s2);
 
 Cstring toCString(T)(T[] s) {
 return Cstring(toStringz(s));
 }
 void main() {
 auto s1 = abba;
 auto s2 = red;
 // auto r = strcmp(toCString(s1), s2); // compile error auto r =
 strcmp(toCString(s1), toCString(s2)); // OK
 }
 
 Bye,
 bearophile

Good point.  Actually, I think there should be a CString type in Phobos, 
but I think it should wrap a ubyte*, not a char*.  The reason for this is 
that D's char is supposed to be a UTF-8 code unit, whereas C's char can 
be anything.

-Lars


Re: exern (C) linkage problem

2010-07-20 Thread Lars T. Kyllingstad
On Tue, 20 Jul 2010 05:10:47 -0400, bearophile wrote:

 In that code, for further safety, I'd like to make it not possible
 (without a cast) code like this (here toStringz doesn't get called):
 strcmp(Cstring(s1.ptr), Cstring(s2.ptr));
 
 So I think this code is a bit better:
 
 import std.string: toStringz;
 
 struct Cstring {
 const(char)* ptr; // const(ubyte)* ?
 static Cstring opCall(string s) {
 Cstring cs;
 cs.ptr = toStringz(s);
 return cs;
 }
 }
 
 extern(C) Cstring strcmp(Cstring s1, Cstring s2);
 
 void main() {
 auto s1 = abba;
 auto s2 = red;
 auto r2 = strcmp(Cstring(s1), Cstring(s2));
 }
 
 Lars T. Kyllingstad:
 
 but I think it should wrap a ubyte*, not a char*.  The reason for this
 is that D's char is supposed to be a UTF-8 code unit, whereas C's char
 can be anything.
 
 Right. But toStringz() returns a const(char)*, so do you want to change
 toStringz() first?

Yes.  I think we should stop using char* when interfacing with C code 
altogether.  The right thing to do, if you can call it that, would be 
to use char* only if you KNOW the C function expects text input encoded 
as UTF-8 (or just plain ASCII), and ubyte* for other encodings and non-
textual data.  But this rule requires knowledge of what each function 
does with its input and must hence be applied on a case-by-case basis, 
which makes automated translation of C headers to D difficult.

So I say make it simple, don't assume that your C functions handle UTF-8, 
and use ubyte* everywhere.  (Actually, it's not that simple, either.  I 
just remembered that C's char is sometimes signed, sometimes unsigned...)

Maybe this should be discussed on the main NG.  It's been bothering me 
for a while.  I think I'll start a topic on it later.

-Lars


Re: Why are string literals zero-terminated?

2010-07-20 Thread Lars T. Kyllingstad
On Tue, 20 Jul 2010 13:26:56 +, Lars T. Kyllingstad wrote:

 On Tue, 20 Jul 2010 14:59:18 +0200, awishformore wrote:
 
 Following this discussion on announce, I was wondering why string
 literals are zero-terminated. Or to re-formulate, why only string
 literals are zero-terminated. Why that inconsistency? What's the
 rationale behind it? Does anyone know?
 
 So you can pass them to C functions.

Note that even though string literals are zero terminated, the actual 
string (the array, that is) doesn't contain the zero character.  It's 
located at the memory position immediately following the string.

  string s = hello;
  assert (s[$-1] != '\0');  // Last character of s is 'o', not '\0'
  assert (s.ptr[s.length] == '\0');

Why is it only so for literals?  That is because the compiler can only 
guarantee the zero-termination of string literals.  The memory following 
a string in general could contain anything.

  string s = getStringFromSomewhere();
  // I have no idea where s is coming from, so I don't
  // know whether it is zero-terminated or not.  Better
  // make sure.
  someCFunction(toStringz(s));

-Lars


Re: exern (C) linkage problem

2010-07-19 Thread Lars T. Kyllingstad
On Sun, 18 Jul 2010 13:08:57 -0700, Charles Hixson wrote:

 I'm trying to link a C routine to a D program, passing string
 parameters, but I keep getting segmentation errors. As you can see,
 these are simple test routines, so the names don't reflect current
 status, but merely where I intend to arrive...but I've hit severe
 roadblocks.
 (FWIW, I've tried including -fpic in the gcc command, and it didn't
 appear to make any difference.)
 
 Makefile:
 biblio: biblio.d sqlitebase.o
   dmd biblio.d sqlitebase.o -ofbiblio
 
 sqlitebase.o: sqlitebase.c sqlitebase.h
   gcc -c sqlitebase.c
 
 biblio.d:
 import   std.stdio;
 
 //extern (C)   void   dbdefine (char[] str); extern (C)   void  
 dbdefine (char[] inStr, ref char[255] outStr);
 
 void   main()
 {  char[255]   retVal;
 char[]   msg   =   cast(char[])Hello from C\0; dbdefine   (msg,
 retVal);
 writeln (Hello, World);
 }
 
 sqlitebase.h:
 
 //void   dbdefine (char str[]);
 void   dbdefine (char inStr[], char outStr[255]);
 
 sqlitebase.c:
 
 #include   sqlitebase.h
 
 //void   dbdefine (char str[])
 void   dbdefine (char inStr[], char outStr[255]) {   //int   i   =   0;
 //while (str[i] != 0)   i++;
 //printStr   (i, str);
 //^^--segmentation fault--^^
 //   printf (%s/n, str);
 //^^--warning: incompatible implicit declaration of built-in
 function ‘printf’--^^
 //int   i   =   str[0];
 //putchar(i);
 //^^--segmentation fault--^^
 int   i   =   -1;
 while (++i  255)
 {   if (inStr[i] == 0)   break;
outStr[i]   =   inStr[i];
 }
 
 }


Since bearophile already answered with a solution to your problem, I'll 
just chime in with a few small tips (of which you may already be aware):

1. D string *literals* are already zero-terminated, so you don't need to 
add the \0 character explicitly.  Also, they cast implicitly to const
(char)*, so if your function doesn't change inStr, it's perfectly fine to 
do

  extern(C) void dbdefine (const char* inStr);
  dbdefine(Hello from C);

2. For D strings in general the \0 must be added, but this is very easy 
to forget.  Therefore, when passing strings to C functions I always use 
the std.string.toStringz() function.  It takes a D string, adds a \0 if 
necessary, and returns a pointer to the first character.

  string s = getAStringFromSomewhere();
  dbdefine(toStringz(s));

-Lars


Re: Anyone know why this CTFE isn't working?

2010-07-16 Thread Lars T. Kyllingstad
On Fri, 16 Jul 2010 11:46:48 +0200, Rory McGuire wrote:

 import std.stdio;
 
 struct State {
   string s; string getString() { return s; } static State opCall(string
   s) {
   State ret;
   ret.s = s;
   return ret;
   }
 }
 
 void main() {
   auto s = State(adf);
   pragma(msg, s.getString());
 }
 
 dmd Output: (line 14 is the pragma statement)
 
 struct.d(14): Error: variable s cannot be read at compile time
 struct.d(14): Error: cannot evaluate s.getString() at compile time
 s.getString()

It's not working because s isn't a compile-time quantity.  Try:

  enum s = State(adf);

-Lars


Re: Multi dimensional array question.

2010-07-15 Thread Lars T. Kyllingstad
On Wed, 14 Jul 2010 16:57:13 -0400, Heywood Floyd wrote:

 Lars T. Kyllingstad Wrote:
 
 
 But then arrays would be different from all other types!  If you have
 an array of 3 Ts, that is written T[3], regardless of what T is.  Now
 consider these two cases:
 
A. T is an int.  Then T[3] becomes int[3].
 
B. T is an int[string].  Then T[3] becomes int[string][3].
 
 In case A, the first element of the array is accessed like this:
 
int[3] a;
int firstA = a[0];
 
 Since a is an array of int, firstA is of course an int.
 
 But then, since b is an array of int[string], we have
 
int[string][3] b;
int[string] firstB = b[0];
 
 If we again want to access element foo of the associative array which
 is firstB, we write firstB[foo].  And so we have the following three
 ways to get to that element, which *must* be equivalent because that's
 how the language is defined:
 
// Using firstB as an intermediate step int[string] firstB = b[0];
int x = firstB[foo];
 
// Drop the intermediate variable firstB int x = (b[0])[foo];
 
// Drop the redundant parentheses
int x = b[0][foo];
 
 So you see, it can't be any other way than the way it is. :)
 
 -Lars
 
 Thank you for the elaborate answer!
 
 When you put it like that, it does make sense. But I'm sorry. I refuse.
 The reason I refuse is those examples are void of any higher semantic
 meaning. Once we add a semantic meaning, it simply becomes backwards:
 
 int[MAX_WIDTH][MAX_HEIGHT] map2d;
 map2d[x][y] = 9; // Wrong!
 
 At least in my head, this is cognitive dissonance. To me, the language
 acts as if it's low-level semantics outweighs my high-level semantics
 and I should correct my thinking for that. I refuse! Seems to me it
 could just as well work as:
 
 int[string][3] b;
 int[3] firstB = b[foo];
 int i = firstB[0];
 int j = (b[foo])[0];
 int k = b[foo][0];
 
 But I feel like I'm the only one feeling this, so I'll just let it go
 and hope my dear C-style arrays stay in :)
 
 BR
 /HF
 
 PS. Never thought I'd find a reason to love C.. DS.


I do agree that, if possible, the language should match how most people 
think.  But in this case, it is impossible, because of templates.  How 
would the following example work with T = int[3], if arrays worked the 
way you want?

  struct MyArray(T)
  {
  T[] a;
  }

C doesn't have this issue, because it doesn't have templates.  And I'll 
have my templates over C-style array declarations any time, thank you. :)

-Lars


object.reserve() and array size

2010-07-14 Thread Lars T. Kyllingstad
Is object.reserve() only useful for large arrays, or should I always use 
it if I intend to append to an array?

Let's say I want to read some data, and I expect there to be ~100 bytes 
of data.  Is there any point in using reserve() first, or will there 
always be that much memory available to an array?

  byte[] buffer;
  buffer.reserve(100);
  foreach(byte b; dataSource) buffer ~= b;

-Lars



Re: object.reserve() and array size

2010-07-14 Thread Lars T. Kyllingstad
On Wed, 14 Jul 2010 10:35:19 -0400, Steven Schveighoffer wrote:

 On Wed, 14 Jul 2010 06:01:10 -0400, Lars T. Kyllingstad
 pub...@kyllingen.nospamnet wrote:
 
 Is object.reserve() only useful for large arrays, or should I always
 use it if I intend to append to an array?

 Let's say I want to read some data, and I expect there to be ~100 bytes
 of data.  Is there any point in using reserve() first, or will there
 always be that much memory available to an array?

   byte[] buffer;
   buffer.reserve(100);
   foreach(byte b; dataSource) buffer ~= b;
 
 Yes, you should always reserve if you know how much data is coming.  If
 you do not here is what happens:
 
 Upon adding the first byte, a block of 16 bytes is allocated Upon adding
 the 16th byte (there is one byte for padding), a *new* block of 32 bytes
 is allocated, and the 15 previous bytes are copied to the 32-byte block.
  The original 16 byte block is left allocated because there could be
 other aliases to the data.
 Upon adding the 32nd byte, a block of 64 bytes is allocated, rinse and
 repeat.
 Upon adding the 64th byte, a block of 128 bytes is allocated, same deal.
 
 Then the block will hold 100 bytes.
 
 If you reserve 100 bytes, then a block of 128 bytes is allocated, and
 your data all goes in there.
 
 OT, I assume you realize that reading data in this way is horribly
 inefficient :)  You should read a block at once if possible.


Yeah, that was just an artificial example. :)  The actual use case was 
building a string from substrings.

Thanks!

-Lars


Re: Multi dimensional array question.

2010-07-13 Thread Lars T. Kyllingstad
On Mon, 12 Jul 2010 17:23:16 -0400, Heywood Floyd wrote:

 bearophile Wrote:
 
 Heywood Floyd:
  This had me crazy. I ended up putting the brackets on the variable,
  like
int marr[3][5];
  then it worked like
marr[2][4] = 9;
 
 That's present only for compatibility with C syntax, this means that
 you can use it to perform a quicker port of C code to D, but you are
 supposed to later convert it to D-style array definitions. See also:
 http://www.digitalmars.com/webnews/newsgroups.php?
art_group=digitalmars.Darticle_id=113185
 
 Bye,
 bearophile
 
 Aha, good to know! Thanks!
 (So this might go away in the future? Or require a -cstyle compile
 flag?)
 
 ***
 
 I have a feeling this backwards-array stuff is gonna be one of the
 things my brain will repel for as long as it can.
 
 To me, it seems equal to saying you declare a function like:
 
 
   void foo(string name, int age){
  //... }
  
  
 And then call it by doing
 
foo(90,Benny)
 
 and this makes sense because the arguments are actually pushed on the
 stack in reverse at runtime, so they arrive in the correct order in the
 function. And this is especially important with tuples. or something.
 
 Ok, I understand this has some deep purpose that I still don't
 understand, I'm just, yeah. *tear* (Although this is way out of my
 league: For instance, if a T is an int[3][4], then why can't T[string]
 be a int[string][3][4], and be accessed with arr[a][2][3]? Seems just
 like a matter of taste?)


But then arrays would be different from all other types!  If you have an 
array of 3 Ts, that is written T[3], regardless of what T is.  Now 
consider these two cases:

   A. T is an int.  Then T[3] becomes int[3].

   B. T is an int[string].  Then T[3] becomes int[string][3].

In case A, the first element of the array is accessed like this:

   int[3] a;
   int firstA = a[0];

Since a is an array of int, firstA is of course an int.

But then, since b is an array of int[string], we have

   int[string][3] b;
   int[string] firstB = b[0];

If we again want to access element foo of the associative array which 
is firstB, we write firstB[foo].  And so we have the following three 
ways to get to that element, which *must* be equivalent because that's 
how the language is defined:

   // Using firstB as an intermediate step
   int[string] firstB = b[0];
   int x = firstB[foo];

   // Drop the intermediate variable firstB
   int x = (b[0])[foo];

   // Drop the redundant parentheses
   int x = b[0][foo];

So you see, it can't be any other way than the way it is. :)

-Lars


Re: Recommended way to do RAII cleanly

2010-07-12 Thread Lars T. Kyllingstad
On Sun, 11 Jul 2010 23:25:32 -0700, Jonathan M Davis wrote:

 Okay. There are cases where you want a constructor to do something when
 the class/struct is created, and you want the destructor to do something
 when the class/struct goes out of scope. A classic example would be an
 autolock for a mutex. Another would be the hourglass in MFC - it's
 displayed when the object is created and disappears when the object is
 destroyed (so all you have to do is declare the object it at the
 beggining of the function and it automatically is displayed and then
 disappears). This is classic RAII.
 
 Obviously, because classes are reference types with infinite lifetime
 while structs are value types with their lifetime restricted to their
 scope, structs would be the better choice for RAII. I have noticed a bit
 of a snag however: structs can't have default constructors.
 
 After reading TDPL, I completely understand that structs can't have
 default constructors due to how the init property works. However, the
 classic case where you want to simply declare an object and have it do
 what it does through RAII then falls apart. Ideally, you'd have
 something like this
 
 struct S
 {
 this()
 {
 /* do something */
 }
 
 ~this()
 {
/* undo what you did before or do whatever clean up is required
for it */
 }
 }
 
 void main()
 {
 auto s = S();
/* whatever the rest of main() does */
 }
 
 
 Thanks to the lack of default constructor, you can't do that. Therefore,
 I see 2 options:
 
 1.  Create a nonsensical constructor that takes an argument of _some_
 kind which is totally ignored.
 
 2. Create a factory function to create the struct, and it does whatever
 would have been in the default constructor.
 
 
 Out of those two options, the second seems the best, but it seems to me
 that there have got to be more options than that. So, the question is
 what would be the best option (be it one of those or another that I
 haven't though of) to do RAII in the general case? What would be best
 practice for D when dealing with structs intended for RAII without any
 arguments to their constructor when you can't have a default
 constructor?


I'd say option 2 is your best bet.  I don't know any other way to fake 
default construction.

That said, the recommended best practice for D is, if possible, to use 
scope guards:

  void doStuffWith(string resourceName)
  {
  auto resource = acquire(resourceName);
  scope(exit) release(resource);

  ... // Do stuff with resource here
  }

-Lars


Re: core.sys.posix.grp missing

2010-06-21 Thread Lars T. Kyllingstad
On Mon, 21 Jun 2010 14:07:19 -0400, Chick Corea wrote:

 Using dmd v2.0.47, the following code:
 
 import core.sys.posix.pwd;
 import core.sys.posix.grp;
 
 yields the following error message:
 
 Error: module grp is in file 'core/sys/posix/grp.d' which cannot
 be read
 
 Checking the src/druntime/import directories, I find that a POSIX pwd
 module is present:
 
 src/druntime/import/core/sys/posix/pwd.d
 src/druntime/import/core/sys/posix/pwd.di
 
 But a POSIX grp module is absent.  Neither is there any code related to
 POSIX grp functions in any of the modules.  When I found the pwd.d file,
 I forgot to check
 for a grp.d file, guessing that if one was present then so was the
 other.
 
 So - am I missing something ?  Or do I need to write one myself ?
 
 CHICKZ


Unfortunately, there are still some POSIX headers missing from druntime.  
It would be great if you file a bug on this, so it isn't forgotten:

  http://d.puremagic.com/issues/

If you end up writing it yourself, I'm sure Sean will be happy if you 
attach it to the bug report. :)

-Lars


Re: setMaxMailboxSize

2010-06-18 Thread Lars T. Kyllingstad
On Thu, 17 Jun 2010 21:31:10 +, Byron Heads wrote:

 is setMaxMailboxSize not implemented yet or is it bugged?

It seems it got implemented today. :)

  http://www.dsource.org/projects/phobos/changeset/1662

You can use the SVN version of Phobos, or wait for the next release.

-Lars


Re: Proper way to access posix functions

2010-06-17 Thread Lars T. Kyllingstad
On Thu, 17 Jun 2010 20:09:29 +, Byron Heads wrote:

 Whats the proper way to get access to some of the Posix functions?
 
 ie. fork setsid...
 
 import core.sys.posix.unistd;  //? Is it proper to import from core.sys

Yes, that is correct. :)

-Lars


Re: D Programming Language

2010-06-08 Thread Lars T. Kyllingstad
On Tue, 08 Jun 2010 11:23:23 +0100, Patrick Byrne wrote:

 Amazon (UK) tells me that publication of this book is delayed. Is it
 still coming soon, please?

I also ordered it from Amazon UK, and got the same message.  But the book 
is, as far as I know, finished and printed.  So I suppose it's mostly a 
matter of transportation time. :)

-Lars


Re: Tuple to tuple conversion

2010-06-08 Thread Lars T. Kyllingstad
On Tue, 08 Jun 2010 12:39:43 +0200, Simen kjaeraas wrote:

 Simen kjaeraas simen.kja...@gmail.com wrote:
 
 Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote:

 FWIW, I've run across the same error, while writing code that had
 nothing
 to do with tuples.  And I've seen others complaining about it too.  It
 seems to be a rather elusive bug in Phobos.

 This has now been tracked down to the importing of std.typecons in two
 included files.

 Test case:

 //
 module a;
 import std.typecons;
 alias Tuple!( float ) foo;

 //
 module b;
 import std.typecons;
 
 Forgot to mention, this only happens with -unittest.
 http://d.puremagic.com/issues/show_bug.cgi?id=4294

That's consistent with my experiences too.  It seems to be triggered by a 
Phobos unittest.

Still, I can't reproduce it with your test case.  Which DMD version are 
you using?

-Lars


Re: Tuple to tuple conversion

2010-06-08 Thread Lars T. Kyllingstad
On Tue, 08 Jun 2010 12:56:04 +0200, Simen kjaeraas wrote:

 Lars T. Kyllingstad pub...@kyllingen.nospamnet wrote:
 That's consistent with my experiences too.  It seems to be triggered by
 a Phobos unittest.

 Still, I can't reproduce it with your test case.  Which DMD version are
 you using?
 
 2.045. Actually, I can't reproduce it now either. Ah, found the problem.
 dmd a b -unittest works. dmd b a -unittest does not.

Ok, now I can reproduce it too, with 2.046.  This just makes it even more 
clear that it is a DMD bug, not a Phobos one.  I've been running into a 
lot of these order-of-compilation bugs lately. :(

-Lars


Re: D Programming Language

2010-06-08 Thread Lars T. Kyllingstad
On Tue, 08 Jun 2010 13:00:51 +0100, Robert Clipsham wrote:

 On 08/06/10 11:23, Patrick Byrne wrote:
 Amazon (UK) tells me that publication of this book is delayed. Is it
 still coming soon, please?

 --
 Patrick Byrne
 
 I ordered it from amazon.com, it was half the priceof the UK version ;)


I don't know when you ordered it, but that has changed now, at least.  At 
amazon.co.uk it costs £18.50, while at amazon.com it sells for $42.70 -- 
roughly £29.  Also, for Europeans, the delivery cost is lower if you 
order from UK.

-Lars


What does 'scope' mean for non-class types?

2010-05-29 Thread Lars T. Kyllingstad
In D2, what is the effect (if any) of 'scope' in the following situations?

  scope int a;

  struct B { ... }
  scope B b;

  scope int[] c;

  // According to the spec, 'in' is shorthand for 'const scope'.
  void foo(in char[] d) { ... }


Thanks,
-Lars


Re: Loop optimization

2010-05-14 Thread Lars T. Kyllingstad
On Fri, 14 May 2010 02:38:40 +, kai wrote:

 Hello,
 
 I was evaluating using D for some numerical stuff. However I was
 surprised to find that looping  array indexing was not very speedy
 compared to alternatives (gcc et al). I was using the DMD2 compiler on
 mac and windows, with -O -release. Here is a boiled down test case:
 
   void main (string[] args)
   {
   double [] foo = new double [cast(int)1e6]; for (int 
i=0;i1e3;i++)
   {
   for (int j=0;j1e6-1;j++)
   {
   foo[j]=foo[j]+foo[j+1];
   }
   }
   }
 
 Any ideas? Am I somehow not hitting a vital compiler optimization?
 Thanks for your help.

Two suggestions:


1. Have you tried the -noboundscheck compiler switch?  Unlike C, D checks
that you do not try to read/write beyond the end of an array, but you can
turn those checks off with said switch.


2. Can you use vector operations?  If the example you gave is
representative of your specific problem, then you can't because you are
adding overlapping parts of the array.  But if you are doing operations on
separate arrays, then array operations will be *much* faster.

http://www.digitalmars.com/d/2.0/arrays.html#array-operations

As an example, compare the run time of the following code with the example
you gave:

void main ()
{
double[] foo = new double [cast(int)1e6];
double[] slice1 = foo[0 .. 999_998];
double[] slice2 = foo[1 .. 999_999];

for (int i=0;i1e3;i++)
{
// BAD, BAD, BAD.  DON'T DO THIS even though
// it's pretty awesome:
slice1[] += slice2[];
}
}

Note that this is very bad code, since slice1 and slice2 are overlapping
arrays, and there is no guarantee as to which order the array elements are
computed -- it may even occur in parallel.  It was just an example of the
speed gains you may expect from designing your code with array operations
in mind.

-Lars


  1   2   >