Re: Why doesn't this have a length?

2012-03-13 Thread Magnus Lie Hetland

On 2012-03-13 14:24:37 +, H. S. Teoh said:


Indeed. Would've thought const AA keys would be reasonable. (In
Python they're *required*... :)

[...]

I'm of the opinion that AA keys should be *implicitly* immutable.


Seconded, whole-heartedly.

--
Magnus Lie Hetland
http://hetland.org



Re: Sorting char arrays

2012-03-13 Thread Magnus Lie Hetland

On 2012-03-12 17:33:35 +, Ali Çehreli said:

You can use isNarrowString to either disallow or provide special 
implementation for narrow strings (char[] and wchar[]):


Ah -- useful, thanks!

--
Magnus Lie Hetland
http://hetland.org



Re: Sorting char arrays

2012-03-13 Thread Magnus Lie Hetland

On 2012-03-12 17:24:56 +, Jonathan M Davis said:


The problem is that sort requires a random access range, and narrow string
(string and wstring) aren't, because they're variable length encoded. I'm not
sure that strings _can_ be efficiently sorted, because of that, but maybe
there's a sorting algorthm that could do it reasonably efficiently,


I'd certainly think that'd be posible. (Might, in fact, be a nice 
problem for the students in my algorithms class ;)


I guess I'm just tripped up by the fact that char[] is treated as an 
"almost-string", and hence is "infected" by the variable-length 
encoding of string (i.e., const char[]).


This all makes sense, for sure -- at least as a practical tradeoff or 
the like. (After all, UTF-8 is a super-elegant solution to a very 
difficult problem.) It's just so easy to assume that T[] is a 
random-access range. It seems so *obvious*. And it is true for any type 
T except the variable-length chars... :)


In my case, I was just using char literals (and strings) as an easy way 
of encoding test cases for a template class, and the sorting (+ uniq) 
was just a way of removing duplicates. (Could've used a hash, of 
course.) So I was really just treating it as a ubyte[]. Slightly 
Evil[tm], I guess.



and we could
special case sort for narrow strings to use that one, but it's a while since I
messed with sorting algorithms, so I don't remember all of their
characteristics off of the top of my head. Certainly, with how sort is currenly
implemented, it can't handle any range which isn't a random access range.


No, I get that. I was just assuming that any T[] could be treated as a 
random access range if I really wanted to ;)


--
Magnus Lie Hetland
http://hetland.org



Re: Why doesn't this have a length?

2012-03-13 Thread Magnus Lie Hetland

On 2012-03-13 02:27:46 +, Simen Kjærås said:


Weird.


Indeed. Would've thought const AA keys would be reasonable. (In Python 
they're *required*... :)



You get a different error message from what I get.
My reduced code:

[snip]

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


I guess this issue then covers both (despite the different error 
messages)? I'll just leave this alone (i.e., not submit any additional 
tickets), then (and cast away the constness for now; seems to help).


--
Magnus Lie Hetland
http://hetland.org



Why doesn't this have a length?

2012-03-12 Thread Magnus Lie Hetland
In a template class (with State and Input as template parameters), I 
have the following (private) member:


State[][Tuple!(const(State), const(Input))] transitions;

It works well enough, but for some reason I can't access its length 
attribute...? (If I define other simpler, similar private attributes, 
such as uint[uint], I can access their length in the same location 
where transition.length fails.)


I get an error message that seems to indicate that DMD is looking for a 
global identifier. I've tried instantiating with different types, e.g., 
uint.


Am I doing something illegal?-)

--
Magnus Lie Hetland
http://hetland.org



Re: Sorting char arrays

2012-03-12 Thread Magnus Lie Hetland

On 2012-03-12 13:56:15 +, bearophile said:


It's not a bug, char is meant to be a UTF-8.


Right.


Two workarounds:


Thanks. I'm doing the sorting in a template, so this won't work -- but 
I guess I just can't use char as a type parameter to my template 
either, then :)


--
Magnus Lie Hetland
http://hetland.org



Re: Sorting char arrays

2012-03-12 Thread Magnus Lie Hetland

On 2012-03-12 13:09:18 +, Dmitry Olshansky said:


Mm it should perform sort on UTF-8 buffer?


Humm -- dunno ;) The UTF-8-semantics of single characters sort of 
slipped my mind :)



Tricky thing but worths an enhancement request.


I'm just thinking an array of anything that can be compared should 
probably be sort-able. But comparing individual UTF-8-bytes can be 
weird, indeed. So, yeah. I guess the weirdness follows from the fact 
that individual characters are considered UTF-8 :)



If it's ASCII then try:
sort(a.representation)

representation is in std.string IRC.


The thing is, I'm using sort() in a template, and I just happen to use 
char as the template parameter in a unit test. And since I have no 
special UTF-8 values in there, my own sort() works just fine. (Although 
maybe it shouldn't? ;)


--
Magnus Lie Hetland
http://hetland.org



Re: Tempfiles in unittests

2012-03-12 Thread Magnus Lie Hetland

On 2012-03-11 21:14:59 +, Jonathan M Davis said:

So, as far as Phobos' unit tests are  concerned, there's not really any 
need for what you're trying to do.


Sure. Just would have thought that maybe some unit-testing D user out 
there had written a function that wrote something to a file ;-)


But no problem -- not many lines to add to  my own code.

--
Magnus Lie Hetland
http://hetland.org



Sorting char arrays

2012-03-12 Thread Magnus Lie Hetland

The following fails, which I guess is a bug?

import std.algorithm;
void main() {
char[] a = ['a', 'b', 'c'];
sort(a);
}

I thought maybe I'd report it -- sort of surprises me that it hasn't 
been reported before, but I couldn't find it (although I found some 
similar reports) in the Bugzilla. (No biggie for me, though; the Phobos 
sort seems to fail with all kinds of things, so I have my own anyway... 
;)


--
Magnus Lie Hetland
http://hetland.org



Re: Tempfiles in unittests

2012-03-11 Thread Magnus Lie Hetland

On 2012-03-10 17:10:52 +, Jonathan M Davis said:


Otherwise, this wouldn't have been a problem :)


Then you'll probably have to write a wrapper function which just uses byLine
and join to grab the string line by line and then put it back together again.


Indeed. Not a problem.

Just surprised me that there wasn't a standard way of writing 
file-related unit tests :)


--
Magnus Lie Hetland
http://hetland.org



Re: Tempfiles in unittests

2012-03-10 Thread Magnus Lie Hetland

On 2012-03-09 18:42:01 +, Jonathan M Davis said:


File has a name property. You can do something like

auto file = File.tmpfile();
auto filename = file.name;
auto str = readText(filename);


Yeah -- again, sorry my original post was so verbose, but part of the 
"problem spec" was that my tempfiles don't seem to have names (i.e., 
they are unnamed tempfiles, and file.name is null; platform-dependent, 
I think).


Otherwise, this wouldn't have been a problem :)

--
Magnus Lie Hetland
http://hetland.org



Re: Tempfiles in unittests

2012-03-09 Thread Magnus Lie Hetland

On 2012-03-09 15:08:42 +, bearophile said:


Magnus Lie Hetland:

It seems that File has no method for reading the entire file contents 
into a string, so I'd have to read and concatenate lines or chunks or 
something?


There are std.file.read() and std.file.readText().


Yeah, I found those. I guess my post was a bit verbose, but the main 
point was that I have a File object, but no file name (because I'm 
using std.stdio.tmpfile() in a unit test), so std.file.read() and 
std.file.readText() are useless to me... :)



But I agree that std.stdio.File should have a readAll() method
:-) If you think this is a good idea, add it to Bugzilla.


Sure.

For now, though: What's The Way[TM] to write unit tests for code that 
writes to files? Use tmpfile and read/concatenate the file contents 
myself? Something else that's more practical? (I would have thought 
this kind of test would be common?-)


--
Magnus Lie Hetland
http://hetland.org



Tempfiles in unittests

2012-03-09 Thread Magnus Lie Hetland
I'm testing a class that writes various things to a file, and I'd like 
to test that behavior, and I'm wondering what the standard solution 
here is.


In Python, I'd just use a StringIO class, for example. It seems sort of 
impractical to make std.outbuffer to work as a File (even if the 
file-like parameter is a template parameter, the outbuffer methods 
don't work like the File methods, as far as I can see), so I've 
concluded that using std.stdio.tmpfile is the way to go.


However, when I'm done with the tempfile, I'd like to have its contents 
as a string. It seems that File has no method for reading the entire 
file contents into a string, so I'd have to read and concatenate lines 
or chunks or something? Now, if the File returned by tmpfile had a 
name, I could use std.file.readText(). But no such luck (as far as I 
can see, tmpfile().name is null).


So I'm just wondering -- what's "the way" to do this sort of testing? 
And if it is along the lines of what I'm doing, is there some 
function/method for reading the contents of a File as a string?


(I guess this goes for much file-related functionality; much of it 
seems to be very related to file-names and actual files, rather than 
"file-like" objects, i.e., those with the appropriate methods...)


--
Magnus Lie Hetland
http://hetland.org



Re: Getting the mutable version of a type

2012-03-02 Thread Magnus Lie Hetland

On 2012-03-02 11:23:20 +, Ali Çehreli said:


On 03/02/2012 02:18 AM, Magnus Lie Hetland wrote:

I'm writing a template for generating data of some possibly immutable
type -- e.g., a string. What I'm wondering is, is there some way of
accessing the mutable version of an immutable type?


Yes, std.traits.Unqual:

   http://dlang.org/phobos/std_traits.html#Unqual


Aah -- awesome. Thanks!

--
Magnus Lie Hetland
http://hetland.org



Getting the mutable version of a type

2012-03-02 Thread Magnus Lie Hetland
I'm writing a template for generating data of some possibly immutable 
type -- e.g., a string. What I'm wondering is, is there some way of 
accessing the mutable version of an immutable type?


I mean, I could do something like (for strings and related immutable arrays)...

void func(T)(ref immutable(T)[] arg) {
   T[] res;
   ...
   arg = cast(immutable(T)[]) res;
}

But it would be useful to be able to write the same template for both 
mutable and immutable types, and just use something like


void func(T)(ref T arg) {
   mutable(T) res;
   ...
   arg = cast(T) res;
}

Is there something like that? (E.g., a template in Phobos or 
something.) I guess I could do a match with an is() expression to 
extract the type, perhaps.



--
Magnus Lie Hetland
http://hetland.org



Re: Should uniform(-real.max, real.max) be inf?

2012-03-02 Thread Magnus Lie Hetland

On 2012-03-01 16:34:23 +, Ali Çehreli said:

Since there are also sub-normal values between 0 and T.min_normal, it 
may make sense to use the range [T.min_normal, 1) and scale the result 
from there. But I haven't tested whether the distinct values in that 
range are equally distributed.


I get similar results now that I did when I started with the range from 
-1 to 1, but I'm guessing it's my brain that's a little slow. I was 
perplexed that (for float) almost all the numbers had an exponent of 
38, while only a few had 37, and none had anything else (in my limited 
tests).


Bt that's just the problem with (at least my) "common sense" and 
exponentials/logarithms. There are, of course, ten times as many 
numbers with an exponent of 38 as there are with an exponent of 37 (and 
so on, down the line; c.f., the incompressibility lemma etc.).


For testing, I might want some small numbers, too -- perhaps I should 
just generate the mantissa and exponent separately (maybe even throwing 
in some NaNs and Infs etc.) :)


Thanks for your help, though.

--
Magnus Lie Hetland
http://hetland.org



Re: Should uniform(-real.max, real.max) be inf?

2012-03-02 Thread Magnus Lie Hetland

On 2012-03-01 16:34:23 +, Ali Çehreli said:


I recommend reading this page:

   http://dlang.org/d-floating-point.html



Thanks.

Especially the ASCII graph there is very interesting. The number of 
distinct values between T.min_normal and 1 are equal to the distinct 
values between 1 and T.max

.


Ah -- right.

Since there are also sub-normal values between 0 and T.min_normal, it 
may make sense to use the range [T.min_normal, 1) and scale the result 
from there.


Hm. Seems reasonable.

But I haven't tested whether the distinct values in that range are 
equally distributed.


At the moment, I'm just using this for test-case generation, so 
anything close to a reasonable approximation is fine :)


However: Perhaps it would be useful with a uniform!real() or the like 
in Phobos? Or is that (because of the vagaries of FP) a weird thing to 
do, inviting misunderstandings and odd behavior? Perhaps it's been left 
out for a reason? (Sounds sort of likely ;-)


--
Magnus Lie Hetland
http://hetland.org



Re: Should uniform(-real.max, real.max) be inf?

2012-03-01 Thread Magnus Lie Hetland

On 2012-03-01 10:52:49 +, Magnus Lie Hetland said:


I could just use

  uniform(cast(T) -1, cast(T) 1)*T.max

I guess (for some floating-point type T). Seems to work fine, at least.


Aaactually, not so much. The output here seems to get about the same 
exponent as T.max. Which isn't all that surprising, I guess. (Then 
again, most floating-point numbers *are* pretty large ;-)


So ... any suggestions?

--
Magnus Lie Hetland
http://hetland.org



Should uniform(-real.max, real.max) be inf?

2012-03-01 Thread Magnus Lie Hetland
What's the preferred way of generating a random floating-point number 
in the range of a given floating-point type? We have uniform!T() for 
integral types, but nothing similar for floats? And uniform(-real.max, 
real.max) (possibly tweaking the limits) seems to only return inf, 
which isn't terribly helpful.


What's the standard thing to do here? I could just use

 uniform(cast(T) -1, cast(T) 1)*T.max

I guess (for some floating-point type T). Seems to work fine, at least.

Am I missing the obvious way to do it?

--
Magnus Lie Hetland
http://hetland.org



Re: More general Cartesian product

2012-02-29 Thread Magnus Lie Hetland

On 2012-02-29 14:24:36 +, Philippe Sigaud said:


[snip]

Thanks for the response.

In the meantime, I also hacked together a simple version of what I 
needed (see below), but I'll look into the references you provided as 
well :)


void forall(alias func, size_t lvl=0, T...)(T args) {
   static if (lvl == args.length) {
   func(args);
   }
   else {
   foreach (e; args[lvl]) {
   forall!(func, lvl+1)
  (args[0..lvl], e, args[lvl+1..$]);
   }
   }
}

--
Magnus Lie Hetland
http://hetland.org



More general Cartesian product

2012-02-29 Thread Magnus Lie Hetland

Hi!

I have a need for a Cartesian product of multiple ranges. I see there's 
been a discussion here (Dec 2011) as well as a request posted (#7128). 
It seems to me that the request deals with a multidimensional product 
-- which is what I need -- while the implementation by Timon Gehr deals 
only with the two-dimensional case.


I guess I could apply it in a nested fashion, but there's still the 
issue of flattening the result.


My application is a template along the lines of

 void forall(alias func, T...)(T args) {
   ...
 }

which would call func with every combination of parameters taken from 
the ranges in args. So that, for example, forall!foo([1, 2], ["a", 
"b"]) would yield four calls, from foo(1, "a") to foo(2, "b").


But the thing is that I'd like an arbitrary number of arguments. Sure, 
I could set an upper limit and hard-code the cases -- but there must be 
a prettier way? I've made some stabs at a recursive version, DMD 
complaining all the while. Any pointers?


(Now, I would eventually like to do more complex versions, using only a 
*subset* of the Cartesian product (for, e.g., all-pairs testing or 
combinatorial testing).)


--
Magnus Lie Hetland
http://hetland.org



Re: DbC bug?

2012-02-27 Thread Magnus Lie Hetland

On 2012-02-23 15:59:18 +, H. S. Teoh said:


Looks like a compiler bug. You should never be able to access invalid
values.


Indeed. After spending quite a while whittling down my code, I've 
posted the following snippet as issue #7599:


module main;
import std.conv;

class Class {

   void method(uint arg)
   in {
   // assert(arg + 1); // Uncomment to prevent bug
   }
   out {
   assert(arg == 0, "BUG: arg == " ~ to!string(arg));
   }
   body {}

}

void main(string[] args) {
   (new Class).method(0);
}

--
Magnus Lie Hetland
http://hetland.org



DbC bug?

2012-02-23 Thread Magnus Lie Hetland
I think I've stumbled across a DbC bug. In an out-block, I have the 
assertion `assert(id < objs.length);`. Now, if I don't have an 
in-block, this fails. However, if I add an in-block (with basically any 
code that isn't optimized away, or so it seems), the assertion 
succeeds. (Before this was an assertion, the failure was a range 
violation from objs[id]; the behavior is equivalent for that.)


And this happens even though both id and objs are const...(!)

And: If I place the same assertion just before the return statement 
(which just returns the result, without any computation), the assertion 
before return succeeds, but the one immediately inside the out block 
fails.


Unless, of course, there is an in block, which magically fixes 
everything (without really doing anything).


It seems that the id variable (a parameter of the method) is actually 
undefined in the out-block, and that this is the reason for the error. 
(The program is run with the same random seeds, but the id variable, 
which *should* be in 0..1000, ends up with varying values such as 
1609528144, 1653547856 or 1816621904.


I'm guessing this is a bug in the DbC functionality, somehow? Is it a 
known bug? (Couldn't find anything relevant -- but then again, I wasn't 
sure exactly what to search for...)


My code runs lots of experiments, and this only happens after the 
method has been used a *lot* (i.e., this doesn't happen all the time -- 
though it *does* happen every time the program is run) -- which means 
producing a minimal example would require some effort... :-}




Re: GG bug? (OS X Lion, DMD 2.054)

2011-08-04 Thread Magnus Lie Hetland

On 2011-08-04 13:01:19 +, Jacob Carlborg said:

Since it's just the runtime that's been changed in this case, perhaps 
you just can compile the runtime and replace that with what's in the 
release.


I guess so. I've just starting compiling/linking stuff together -- I'll 
see how it goes. (It can be useful to have the most recent version; 
ideally, it should have fewer bugs ;) If that fails, I could try just 
the runtime, as you suggest.


--
Magnus Lie Hetland
http://hetland.org



Re: GG bug? (OS X Lion, DMD 2.054)

2011-08-04 Thread Magnus Lie Hetland

On 2011-08-04 12:27:54 +, Alex Rønne Petersen said:


Hi,

You can see my blog for Linux: 
http://xtzgzorex.wordpress.com/2011/07/31/d-building-dmd-and-phobos-on-linux/


For 


others trying to do the same (i.e., compile this stuff in OS X Lion), 
one change is needed in posix.mak:


Change ...

   SDK=/Developer/SDKs/MacOSX10.5.sdk
   #SDK=/Developer/SDKs/MacOSX10.6.sdk

... into ...

   SDK=/Developer/SDKs/MacOSX10.5.sdk
   #SDK=/Developer/SDKs/MacOSX10.6.sdk
   SDK=/Developer/SDKs/MacOSX10.7.sdk

(or equivalent).

--
Magnus Lie Hetland
http://hetland.org



Re: GG bug? (OS X Lion, DMD 2.054)

2011-08-04 Thread Magnus Lie Hetland

On 2011-08-04 12:27:54 +, Alex Rønne Petersen said:


Hi,

You can see my blog for Linux: 
http://xtzgzorex.wordpress.com/2011/07/31/d-building-dmd-and-phobos-on-linux/


Thanks!

--




Magnus Lie Hetland
http://hetland.org



Re: GG bug? (OS X Lion, DMD 2.054)

2011-08-04 Thread Magnus Lie Hetland

On 2011-08-03 14:57:57 +, David Nadlinger said:

This seems to be exactly same problem I reported to the NG some days 
ago. It is caused by ASLR being enabled for 32bit applications on Lion 
too, and kennytm is to be credited for tracking this down to a fixed 
stack bottom in the druntime code: 
https://github.com/D-Programming-Language/druntime/pull/43. The fix has 
already been merged into master, please use that for OS X development 
until the next DMD release.


Sorry for being a n00b here, but ... what's the intended way of using 
the Git version? It seems to be split into five different repos...? Do 
I have to assemble a full distro myself, or am I just missing something 
obvious? (I'm assuming the latter, really ;)


--
Magnus Lie Hetland
http://hetland.org



Re: GG bug? (OS X Lion, DMD 2.054)

2011-08-03 Thread Magnus Lie Hetland
Note that an explicit call to GC.collect isn't necessary. Whenever 
collection occurs, the collectors seems rather indiscriminate, 
collecting things it shouldn't, resulting in bus errors. When I disable 
the GC, my code runs just fine. (My production code, that is. There are 
still mysterious, probably Lion-related, bugs in my test suite...)


--
Magnus Lie Hetland
http://hetland.org



GG bug? (OS X Lion, DMD 2.054)

2011-08-03 Thread Magnus Lie Hetland
I upgraded from OS X Snow Leopard to Lion recently (on a 32-bit iMac), 
and when I tried to run my D code afterward, I suddenly ran into all 
kinds of interesting problems (lots of failed assertions in my tests, 
and bus errors in my actual runs...). Still cleaning stuff up, but I've 
isolated at least one thing that seems to be a bug, and that wasn't 
there before I upgraded.


Now, I upgraded from DMD 2.052 to 2.054 before doing any extensive 
debugging, so I'm not 100% sure this specific problem was there in 
2.052 as well, but I *think* so (i.e., making the switch to Lion the 
triggering factor).


Anyway, here's some code:

import std.exception, core.memory;

class Foo {
   bool bar;
}

void main() {
   auto f = new Foo;
   f.bar = true;
   //GC.collect();
   enforce(f.bar);
}

Works well, unless you uncomment the GC call, in which case a bus error 
occurs (at least for me). Seems the collector is a bit over-eager...?


--
Magnus Lie Hetland
http://hetland.org



Re: Polymorphism problem w/local functions?

2011-07-20 Thread Magnus Lie Hetland

On 2011-07-18 18:10:47 +0200, Jonathan M Davis said:


Well, technically-speaking, that's not really polymorphism, since the choice
of function is decided at compile time (polymorphism would be dealing with
overridden functions than overloaded ones),


Right ... thought static overloading was considered a form of 
polymorphism as well. Aanyway... :D



but I suppose that that's not really here nor there.


Right :)


In any case, no you can't overload nested functions. You've never been able
to, and you still can't do it. I don't know _why_ such a restriction exists,
but it does. Feel free to open up an enhancement request for it. I don't know
that it'll do much good, but maybe you'll luck out. Not knowing why the
restriction exists in the first place, I don't know what the chances are of
that restriction being removed. For all I know, it's an Walter's TODO list.


I see. Not really critical.

As I've been thinking about the problem I was working on, I guess 
dynamic (i.e., "real") polymorphism is what I need anyway; I guess the 
(only?) way to do that would be to have a method on the objects in 
question. (Right...? There are no other dynamic dispatch mechanisms 
that I'm forgetting, other than type-based switch statements?)


Thanks,

- M

--
Magnus Lie Hetland
http://hetland.org



Polymorphism problem w/local functions?

2011-07-18 Thread Magnus Lie Hetland

Is it intended that local functions can't be polymorphic?

Example:

void foo(int x) {}
void foo(string x) {}

void bar() {
   void foo(int x) {}
   void foo(string x) {}
}

void main() {
}

The error (at line 6) is "declaration foo is already defined".

The code compiles if you comment out at least one of the local 
functions (but not if you, for example, comment out the global ones, of 
course).


Is this a bug, or am I just missing the reasoning behind it? Any 
workarounds? (I'm still at 2.052, so maybe this works in the new 
version?)


--
Magnus Lie Hetland
http://hetland.org



Re: "Before and after" in contracts?

2011-04-13 Thread Magnus Lie Hetland

On 2011-04-11 18:42:18 +0200, bearophile said:

Your need is perfectly natural it's named "old" values or prestate in 
contract programming, and currently it's probably the biggest hole in 
the D contract programming. It was discussed three or four times, like:

[snip]

Interesting.


I don't know if Walter is willing someday to fill this hole of the D DbC.


It seems the prestate thing hasn't been done because it's a bit 
ambitious? I mean, the automatic part (which would be totally 
*kick-ass*, of course).


For me, I'd be happy if I could simply declare and initialize the 
variables myself somehow before the body is executed, and then check 
them in the out-block.


In my opinion is good to bugger now and then the main D newsgroup about 
this, to help Walter&Andrei understand that there are some programmers 
that care for this feature of DbC.


Is there a feature request on this that I could add my vote to? If not, 
perhaps it's worth creating one?


If not, I guess I could just post a "bump" to the D group :-}

--
Magnus Lie Hetland
http://hetland.org



Else clauses for loops

2011-04-13 Thread Magnus Lie Hetland

Hi!

A feature I use surprisingly often in Python is the else clause on 
loops. Is there something similar in D? Basically, the idea is that 
your loop is "looking for something" (or some condition), and that 
you'll break out of it if you find what you're looking for. If no break 
occurs, the else clause is executed.


It makes for quite clean code in many cases, IMO. The alternative can 
be a flag variable, I guess, or a goto-statement (to right after the 
"else" bit) instead of a break. Or put it in a function, and use a 
return instead of a break ... or use scope() somehow, perhaps.


I see that the feature has been requested a few years ago [1], so there 
might not be that much demand for this sort of thing. Is there perhaps 
a D idiom here already?


[1] http://d.puremagic.com/issues/show_bug.cgi?id=2304

--
Magnus Lie Hetland
http://hetland.org



Re: "Before and after" in contracts?

2011-04-11 Thread Magnus Lie Hetland

On 2011-04-11 16:32:36 +0200, Kai Meyer said:

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


Yeah, that's what I've got right now. Just seems odd to need to use 
attributes for this sort of thing. Also, it's rather brittle -- for 
example, if the function (directly or indirectly) calls itself. Then 
two (or more) pairs of in/out blocks will manipulate the same 
attribute... Seems like a variable that would be local to one specific 
in/out instantiation (or stack frame) would be preferable.


I guess I could just use a local variable (guarded by version()) and 
then have an assert() near the end of the function. Probably a better 
solution...


--
Magnus Lie Hetland
http://hetland.org



"Before and after" in contracts?

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


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


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


--
Magnus Lie Hetland
http://hetland.org



Can I use a delegate as a template parameter? (Issue 2962?)

2011-03-30 Thread Magnus Lie Hetland

A while ago, I wrote something like this:

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

void B(T)(uint x=2) {
   uint foo() {
   return x;
   }
   C!foo();
}

It worked well, so I didn't think any more about it. Then suddenly, I 
started getting the following error:


./path/to/foo.d(12): Error: function path.to.foo.B!(real).B compiler 
error, parameter 'x', bugzilla 2962?

Assertion failed: (0), function toObjFile, file glue.c, line 729.

This only happens when I compile with -inline, and error disappears if 
I make certain really minor changes to which modules are imported where 
(currently 17 basically empty modules are involved in the minimal case 
I've been able to produce), so the compiler behavior seems like a bug.


As Don says in a comment to 2962, "This is really tough, it's an 
order-of-evaluation issue.

When generating the code for a template, which has a local variable as an alias
parameter, the alias parameter MUST be created before the code for 
template is."


The error message also seems different from that of issue 2962 (which 
DMD dutifully points me toward :), so I'm uncertain about whether it's 
the same issue. What does it look like to you guys?


Also, aside from the erratic DMD behavior, I'm guessing my code might 
be invalid, and shouldn't have worked in the first place. After all, x 
is a run-time argument, and is part of foo, which functions as a 
compile-time argument. I mean, the set-up *could* work (and, in fact, 
generally seems to do so), but it might be a bit problematic?


This way of doing it seems like the most practical for my current use, 
though... (I.e., I'd like foo to be inline-able, and have access to x.)


--
Magnus Lie Hetland
http://hetland.org



Re: How do you use BinaryHeap with Array (or just make a growable heap)?

2011-03-28 Thread Magnus Lie Hetland

On 2011-03-28 20:24:55 +0200, Jonathan M Davis said:


Well, Array definitely shouldn't be a random access range. The range for it
(which you'd typically get by slicing it) would be random access, but the
container itself isn't a range of any kind. Containers aren't ranges (barring
the oddities of dynamic arrays). I've never used BinaryHeap, but glancing at
it, my guess would be that the correct solution (if you want to use Array with
it) is to create an Array and then pass its range to heapify:

Array!uint a;
//... put stuff in a.
auto heap = heapify(a[]);

I'm not sure if that's growable or not though.


Hm. I can't even get the slicing to work:

/path/to/phobos/std/container.d(2436): Error: function 
std.container.Array!(uint).Array.Range.opSlice (uint a, uint b) is not 
callable using argument types ()


Glancing at BinaryHeap, it'll work with arrays though, so you don't 
need to use Array.


Hm. The docs say "If Store is a range, the BinaryHeap cannot grow 
beyond the size of that range. If Store is a container that supports 
insertBack, the BinaryHeap may grow by adding elements to the 
container."


So it seems that a container (such as Array, which has insertBack) 
should be usable, according to the docs. And an array/slice would not 
be growable. (At least, it isn't growable in practice.) See also:


 
http://www.digitalmars.com/d/archives/digitalmars/D/std.algorithm.BinaryHeap_88811.html


What 

I'm looking for is a completely standard priority queue, where I can 
add and remove objects, and not have to know the maximum size 
beforehand.


I'd also like to have tuple entries, but it seems that BinaryHeap has 
trouble with that as well...


I don't know what the ideal container to use with a BinaryHeap is 
though. Also, in my experience, Array is pretty buggy at this point, so 
I'm not sure how far you'll get with it.


Yeah, it seems to be. At the moment, I've just reimplemented BinaryHeap 
myself (with a subset of the Phobos API), so that it can handle arrays 
of tuples (which I couldn't get std.container.BinaryHeap to accept). I 
then wrapped it in a PriorityQueue class, which takes care of resizing 
the array (and having BinaryHeap switch to the possibly reallocated new 
one).


Not an ideal solution, but at least it works.

--
Magnus Lie Hetland
http://hetland.org



How do you use BinaryHeap with Array (or just make a growable heap)?

2011-03-28 Thread Magnus Lie Hetland
I need a (growable) binary heap, and I'm trying to avoid writing one 
myself (which isn't too hard, of course :) ... but for some reason I 
can't figure out how to use Phobos to do it.


I've seen stated (e.g., by Andrei and in the docs) that the standard 
way is combining BinaryHeap with an Array. Which is fine with me. 
Except I can't make it work. E.g., I try:


 Array!uint A;
 auto Q = heapify(A);

The error is

/path/to/phobos/std/container.d(2658): Error: template instance 
BinaryHeap!(Array!(uint)) does not match template declaration 
BinaryHeap(Store,alias less = "a < b") if (isRandomAccessRange!(Store) 
|| isRandomAccessRange!(typeof(Store.init[])))
/path/to/phobos/std/container.d(2658): Error: BinaryHeap!(Array!(uint)) 
is used as a type


When I check it out, it seems that isRandomAccessRange!(Array!uint) 
returns false (and it doesn't, AFAIK, have an init), which means that 
the error makes sense.


Does this mean...

1. That Array isn't, and shouldn't be, a random access range?
2. That Array can't, and shouldn't be (despite official statements to 
the contrary) be used with BinaryHeap?


(I suspect the answer to both is "you're doing it wrong" ;)

And, of course, my main question:

3. How do you (canonically) make a growable heap using Phobos?

--
Magnus Lie Hetland
http://hetland.org



Re: Bug in tuple comparison?

2011-03-24 Thread Magnus Lie Hetland

On 2011-03-24 18:25:30 +0100, bearophile said:


Magnus Lie Hetland:


I guess this is getting old by now ... but I've come across yet another bug :->


The out(result) turns the result into a const,


Riiight! Yes, I've seen that it's const, and (naughtily) cast away the 
constness (without modifying anything) in some cases. It didn't occur 
to me that that was the problem here. :) (In my original program, I 
didn't notice that I had gotten one of the values from outside the 
out-block, while the other was from the result. I guess I was "primed" 
to think that that wasn't the problem ;)


So the issue, then, I take it, is that you *can* compare a non-const 
tuple to a const-tuple, but you *cannot* compare a const-tuple to a 
non-const tuple (as per casting rules)?


Makes sense. Would have been nice with a slightly more obvious error 
message, but I guess that's always a problem with templates in any form 
;)


Aanyway -- glad the bug was just in my code/brain :D Thanks for the help,

- M

--
Magnus Lie Hetland
http://hetland.org



Bug in tuple comparison?

2011-03-24 Thread Magnus Lie Hetland

I guess this is getting old by now ... but I've come across yet another bug :->

This one is a bit obscure, and deals with comparing tuples in 
contracts. It seems that some type information about the result is lost 
when entering an out-block, or something. At least, DMD (2.052, OS X) 
is unable to infer types properly, and is therefore unable to compare 
tuples in some cases. Sample program follows. (Similar behavior occurs 
for other comparison operators as well.)


import std.typecons;
T[] func(T)(T[] arg)
out(result) {
   auto a = result[0];
   auto b = arg[0];
   auto c = result[0];
   // assert(c < a); // Doesn't work
   // assert(a < c); // Doesn't work
   // assert(c < b); // Doesn't work
   assert(b < c); // Works
}
body {
   return arg;
}
void main() {
   alias Tuple!(real, uint) Entry;
   func(new Entry[100]);
}

The error (when uncommenting one of the lines that don't work, e.g., 
line 7) is:


tuplecmpbug.d(7): Error: template 
std.typecons.Tuple!(real,uint).Tuple.opCmp(R) if (isTuple!(R)) does not 
match any function template declaration
tuplecmpbug.d(7): Error: template 
std.typecons.Tuple!(real,uint).Tuple.opCmp(R) if (isTuple!(R)) cannot 
deduce template function from argument types 
!()(const(Tuple!(real,uint)))


I take it this is a bug (or am I just missing something)? Is it a known 
bug? (Sorry if it's in the tracker; it can be hard to find equivalents 
there...)


--
Magnus Lie Hetland
http://hetland.org



Re: Bug w/tuple of custom types?

2011-03-23 Thread Magnus Lie Hetland

On 2011-03-21 18:40:07 +0100, Steven Schveighoffer said:

If you looked and couldn't find it, it doesn't hurt to add it.  Worst 
case -- it gets marked as a duplicate.


OK. Perhaps I should just start doing that, rather than asking here 
about every bug I find. (I seem to come across new ones every day ;-)


Note that typedef is eventually going to be deprecated.  I'd suggest 
using alias unless you have a need to force uints not to be castable to 
oid_t.


Ah. That sort of makes the bug a bit less relevant :->

Actually, the typedef *was* to prevent that casting, because I 
inadvertently used an uint that was of a semantically different kind, 
and got a hard-to-spot bug -- so I thought I'd try to prevent that by 
using the type system.


Any way to do that without (to be deprecated) typedef?

--
Magnus Lie Hetland
http://hetland.org



Re: Deducing types for function templates

2011-03-21 Thread Magnus Lie Hetland

On 2011-03-15 21:13:36 +0100, Michel Fortin said:


Oh, it's much older than that:

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


I'm not sure it's the same thing, but I realize it's hard to say given 
Magnus in his original post didn't mention how he attempts to 
instantiate the template.


Hm. I've gone back to it now, and, sadly (as opposed to for the other 
bugs I've encountered :) I didn't isolate and save the related code -- 
so now I'm unable to reproduce the const problem. (Who knows ... maybe 
I was just trying to pass it on as an un-const parameter or something? 
Might very well have been a bug on my part.)


Here's some sample code for the other part of my question, though 
(which might not have been as unclear in the first place?).


class Foo(T) {
   T foo;
}

template baz_t(T) {
   alias real function(T, T) baz_t;
}

Foo!T foo(T)(T[] bar, baz_t!T baz) {
   return new Foo!T;
}

real frozz(uint x, uint y) {
   return 4.2;
}

void main() {
   uint[] x = [1, 2, 3];
   auto f = foo(x, &frozz);
}

The error is:

inferencebug.d(19): Error: template inferencebug.foo(T) does not match 
any function template declaration
inferencebug.d(19): Error: template inferencebug.foo(T) cannot deduce 
template function from argument types !()(uint[],real function(uint x, 
uint y))


--
Magnus Lie Hetland
http://hetland.org



Bug w/tuple of custom types?

2011-03-21 Thread Magnus Lie Hetland

Sample program:

import std.typecons;

typedef uint oid_t;

void main() {
   Tuple!(uint,uint) key;
   // Tuple!(oid_t,oid_t) key; // Doesn't work
}

If I use the last tuple instead of the first, I get the following 
compiler error with DMD 2.052 in OS X:


/path/to/src/phobos/std/format.d(1579): Error: function 
std.format.formatValue!(Appender!(string),oid_t,immutable(char)).formatValue 
is deprecated
/path/to/src/phobos/std/format.d(306): Error: template instance 
std.format.formatGeneric!(Appender!(string),oid_t,immutable(char)) 
error instantiating
/path/to/src/phobos/std/typecons.d(507):instantiated from here: 
formattedWrite!(Appender!(string),immutable(char),oid_t)


It seems that std.typecons is using a deprecated formatting API, which 
is triggered by my use of a custom type? And ... I guess this would be 
a bug? (I looked in the tracker, and couldn't find it there already.)


--
Magnus Lie Hetland
http://hetland.org



Deducing types for function templates

2011-03-15 Thread Magnus Lie Hetland

I've got a function template along these lines:

 Foo!T foo(T)(T[] bar, real function(T,T) baz) { ... }

The main reason I'm using this is that it seems necessary to use a 
function, rather than a type (such as Foo), if you want the compiler to 
deduce the compile-time parameters. (Right?)


Now ... this works just fine. However, if I try to add "const" before 
"T[]", DMD no longer groks it. Is that how it shold be? Seems awkward 
to me... (Or maybe I'm just doing it wrong?)


And a followup question: Writing out the type of baz like this (in 
several places) is also a bit awkward. I'd like to have a template so I 
could just do


 Foo!T foo(T)(T[] bar, baz_t!T baz) { ... }

However, I haven't been able to define such a template without running 
into the same problem (i.e., that DMD no longer can deduce what T 
should be from my arguments).


Any pointers?

--
Magnus Lie Hetland
http://hetland.org



Re: "Semi-const" methods?

2011-03-14 Thread Magnus Lie Hetland

On 2011-03-14 00:17:18 +0100, Jonathan M Davis said:


So, if you don't actually manage to _really_
be logically const, or if you do this with an immutable object (which would
likely result in a segfault), you _are_ going to have incorrect code. On the
whole, I'd advise just not using const when you need logical const, but if
you're _very_ careful, you can get away with it. But thanks to 
immutable, it can

be _very_ dangerous to cast away constness in a const function unless you're
_very_ careful.

You really should check out this question on stackoverflow and the answers that
go with it: http://stackoverflow.com/questions/4219600/logical-const-in-d


Thanks for the insights + tip :)

--
Magnus Lie Hetland
http://hetland.org



Re: "Semi-const" methods?

2011-03-14 Thread Magnus Lie Hetland

On 2011-03-14 11:51:09 +0100, Mafi said:


I found away which doesn't use casts or bugs.
Just use delegates/closures.


Nice :D

--
Magnus Lie Hetland
http://hetland.org



Re: "Semi-const" methods?

2011-03-13 Thread Magnus Lie Hetland

On 2011-03-13 23:32:34 +0100, Magnus Lie Hetland said:

(Still open to schooling on the design part of this, though. Perhaps 
declaring a method as const is no good when it's not *really* const? 
For now, I'm just doing it to check that I don't inadvertently change 
things I don't want to change.)


Actually, I have a local (recursive) traversal function in the method I 
was talking about. Ended up not declaring the method as const, but 
declaring the argument of the traversal function as const. No 
misleading const declarations "outside", and I get the automatic checks 
that I want.


--
Magnus Lie Hetland
http://hetland.org



Re: "Semi-const" methods?

2011-03-13 Thread Magnus Lie Hetland

On 2011-03-13 23:27:14 +0100, Magnus Lie Hetland said:

Any other ideas on how to handle this sort of "mostly const" or "const 
where it counts" stuff? Perhaps my design intentions here are off to 
begin with?-)


OK -- a *little* quick on the trigger there. My solution: Declare the 
method const, and assign the non-essential cache stuff to local 
variables, casting away the constness.


(Still open to schooling on the design part of this, though. Perhaps 
declaring a method as const is no good when it's not *really* const? 
For now, I'm just doing it to check that I don't inadvertently change 
things I don't want to change.)


--
Magnus Lie Hetland
http://hetland.org



"Semi-const" methods?

2011-03-13 Thread Magnus Lie Hetland
I have a data structure that's generally static (const, or even 
immutable), but it has some utility storage, which caches certain 
results during use. This caching etc. doesn't really affect the 
semantics of the main object, and are reset between operations, so I 
think it still would be useful to declare (and statically check) that 
certain methods don't modify any of the *rest* of the structure (i.e., 
the "main parts").


I *could* declare the methods const, and pass in a second object (a 
non-const parameter) for the caching etc. Or I cast the relevant parts 
to const (assigning them to local variables) early on in the relevant 
methods (dropping the const modifier on the method itself -- sort of a 
bummer).


Any other ideas on how to handle this sort of "mostly const" or "const 
where it counts" stuff? Perhaps my design intentions here are off to 
begin with?-)


--
Magnus Lie Hetland
http://hetland.org



Re: "foo.bar !in baz" not allowed?

2011-03-13 Thread Magnus Lie Hetland

On 2011-03-13 21:27:27 +0100, spir said:


On 03/13/2011 07:58 PM, Magnus Lie Hetland wrote:

For some reason, it seems like expressions of the form "foo.bar !in baz" aren't
allowed. I suspect this is a grammar/parser problem -- the bang is interpreted
as a template argument operator, rather than a negation operator,

[snip]

Would be nice to copy the error, wouldn't it?
template argument expected following !


Ah. I thought my explanation (see above) made that clear.


Anyway, this is definitely a bug in my opinion.


Turns out it's an old one. Sorry about that:

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

--
Magnus Lie Hetland
http://hetland.org



"foo.bar !in baz" not allowed?

2011-03-13 Thread Magnus Lie Hetland
For some reason, it seems like expressions of the form "foo.bar !in 
baz" aren't allowed. I suspect this is a grammar/parser problem -- the 
bang is interpreted as a template argument operator, rather than a 
negation operator, and there's really no need to make that 
interpretation when it is immediately followed by "in". This suspicion 
is strengthened by the fact that "bar !in baz" is fine, as is 
"(foo.bar) !in baz".


Should I file this as a bug?

Small sample program:

struct Foo {
   uint bar;
}

struct Baz {
   bool opIn_r(uint e) {
   return false;
   }
}

void main() {
   Baz baz;
   Foo foo;
   auto res = (foo.bar) !in baz;
   res = !(foo.bar in baz);
   // res = foo.bar !in baz; // Not OK...
   uint frozz;
   res = frozz !in baz;
}

--
Magnus Lie Hetland
http://hetland.org



Re: Iterating over 0..T.max

2011-03-10 Thread Magnus Lie Hetland

On 2011-03-09 21:24:57 +0100, Kai Meyer said:

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


Derp. I didn't mean bool -- I was talking about byte. (Which should 
make quite a bit more sense, given that I'm talking about a limit of 
256... :D)


And, for the record, I'm using DMD 2.052 (OS X).

Just replace bool with byte in your program, and it should compile. 
Sorry for the brain fart ;)


--
Magnus Lie Hetland
http://hetland.org



Iterating over 0..T.max

2011-03-09 Thread Magnus Lie Hetland

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

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

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


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


--
Magnus Lie Hetland
http://hetland.org



Re: Growable BinaryHeap: use w/Array?

2011-03-07 Thread Magnus Lie Hetland

On 2011-03-06 14:58:10 +0100, Magnus Lie Hetland said:

[corrected the example below, replacing int with string]

that works just fine. However, if I try

alias Tuple!(real,string) Entry;
Array!Entry Q;

then I get the following errors:

container.d(1549): Error: this for _data needs to be type Array not 
type Payload
container.d(1550): Error: this for _data needs to be type Array not 
type Payload
container.d(1551): Error: this for _data needs to be type Array not 
type Payload


Actually, now, running the same program, I get a *different* error message:

container.d(1502): Error: template instance template 
'hasElaborateDestructor' is not defined
container.d(1502): Error: hasElaborateDestructor!(Tuple!(real,string)) 
is not an expression


As far as I know, I haven't changed anything in the ecosystem, and the 
code is the same (which seems a bit magical...).


Anyway: this doesn't seem right ... should I file a bug?

--
Magnus Lie Hetland
http://hetland.org



Re: Growable BinaryHeap: use w/Array?

2011-03-06 Thread Magnus Lie Hetland

On 2011-03-06 15:00:29 +0100, David Nadlinger said:


On 3/6/11 2:58 PM, Magnus Lie Hetland wrote:

alias Tuple!(real,int) Entry;
Array!Entry Q;
[...]
alias Tuple!(real,int) Entry;
Array!Entry Q;


Is it just me, or is there really no difference between the two snippets? ;)


$(WITTY_REPLY) ;-)

The one that fails should have string (or some other reference type, 
perhaps) rather than int. Copy/paste fail :D


--
Magnus Lie Hetland
http://hetland.org



Re: Growable BinaryHeap: use w/Array?

2011-03-06 Thread Magnus Lie Hetland

On 2011-03-06 14:37:19 +0100, Magnus Lie Hetland said:

Just wondering: If I want a growable binary heap (I'd be open to other 
priority queue structures, for that matter ;), is the standard way in D 
(w/Phobos) to combine std.container.BinaryHeap with std.container.Array?


Another thing ... when I use priority queues, I'm usually not 
interested in just having a set of priorities -- the payload data is 
what it's all about. So I thought I'd just use an Array of Tuples, 
managed by BinaryHeap (possibly with a custom comparison, to avoid 
comparing the payloads). But perhaps that's not a good idea?


When I try

   alias Tuple!(real,int) Entry;
   Array!Entry Q;

that works just fine. However, if I try

   alias Tuple!(real,int) Entry;
   Array!Entry Q;

then I get the following errors:

container.d(1549): Error: this for _data needs to be type Array not 
type Payload
container.d(1550): Error: this for _data needs to be type Array not 
type Payload
container.d(1551): Error: this for _data needs to be type Array not 
type Payload


It seems the lines that are being referred to are

   GC.removeRange(_data._payload.ptr);
   free(_data._payload.ptr);
   _data._payload = newPayload;

though I may be wrong about that.

Is this a bug in Array? Am I using it wrong? And what would be the 
recommended "best practice" for a priority queue with payload data in D 
(using Phobos)? (I could just write one myself, but that seems sort of 
wasteful ;)


--
Magnus Lie Hetland
http://hetland.org



std.gc doc page

2011-03-06 Thread Magnus Lie Hetland
It seems std.gc is no longer available -- or, rather, that it is now 
core.memory? Is there a reason why this page exists, and has a link in 
the sidebar?


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

(Yes, the documentation is for core.memory, but the page name/link name 
is std.gc. Also, there's no core.memory link in the sidebar...)


--
Magnus Lie Hetland
http://hetland.org



Growable BinaryHeap: use w/Array?

2011-03-06 Thread Magnus Lie Hetland
Just wondering: If I want a growable binary heap (I'd be open to other 
priority queue structures, for that matter ;), is the standard way in D 
(w/Phobos) to combine std.container.BinaryHeap with 
std.container.Array? Any reason why BinaryHeap can't deal with ordinary 
dynamic array appending, or appender instances, for that matter? Or, to 
put the questions a bit differently: Is there a reason why std.array 
doesn't have an insertBack method (that BinaryHeap can use) either 
defined for dynamic arrays or for std.array.Appender?


Just trying to figure out what's what here :)

--
Magnus Lie Hetland
http://hetland.org



Re: Overriding iteration

2011-03-04 Thread Magnus Lie Hetland

On 2011-03-04 19:06:34 +0100, Jonathan M Davis said:


On Friday, March 04, 2011 09:13:34 spir wrote:

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

[snip]

opApply should work but it is supposed to be slower.
Defining range primitives directly on the object/container cannot work as
of now, unfortunately, because of a pair of bugs (conflicts in formatValue
template definitions between struct/class on one hand and ranges on the
other).


You don't _want_ range primitives directly on the container. That would mean
that everything in your container goes away when you process it.


That was the point of my original question, yes :) In TDPL, where 
Andrei discusses overloading foreach, he has two main examples -- one 
using opApply, and one using such a self-destructive container. I think 
(as I said in my post) that what saves that list is that it's a struct, 
so it's copied by the initial assignment of the foreach statement.


You _want_ to have a separate type which is a slice of our container 
and has the range primitives.


Exactly. That was what I was asking for.



Now, it could very well be that

foreach(v; container)

should be calling opSlice on the container, allowing you to feed the container
to foreach directly instead of having to slice it yourself

foreach(v; container[])

but that's just syntactic sugar.


Sure. And judging from the other responses (and from TDPL), the fact 
that this doesn't currently work is just a bug.


You don't want to actually treat your container like a range. Ranges 
should be slices of containers, not containers themselves.


Well, it would still be nice to have things be consistent -- and in 
order for the opSlice approach to be consistent with the opApply 
approach (so a client needn't know how iteration is implemented for a 
given container), it seems reasonable to me to have foreach directly 
run on a slice of your container (i.e., implicitly calling []). But as 
this seems to be the way it is (save for the current bug), I guess it's 
sort of a moot point.


I certainly agree with your point, though. In Python, too, iterators 
(i.e., ranges) and iterables (i.e., containers) are separate concepts. 
You can iterate over an iterable, and the loop then automatically 
extracts an iterator. As this is The Way to Go, it makes sense to me 
that it's automatic/implicit.


--
Magnus Lie Hetland
http://hetland.org



Re: Overriding iteration

2011-03-04 Thread Magnus Lie Hetland

On 2011-03-04 17:46:39 +0100, Simen kjaeraas said:


Simen kjaeraas  wrote:

[snip]

Found it:
http://d.puremagic.com/issues/show_bug.cgi?id=5605


Oo -- nice :) (That it should work, that is; not that it doesn't ;)

--
Magnus Lie Hetland
http://hetland.org



Re: Overriding "in" operator

2011-03-04 Thread Magnus Lie Hetland

On 2011-03-04 18:08:08 +0100, spir said:


Didn't even know 'in' can be defined with opBinary...
I use opIn_r ('r' for right side, since the container stand on the 
right of the expression) everywhere, and it works fine.


Huh. Cool. Works like a charm. Seems cleaner like the opBinaryRight 
solution, really. I just didn't know of it :)


--
Magnus Lie Hetland
http://hetland.org



Re: Overriding "in" operator

2011-03-04 Thread Magnus Lie Hetland

On 2011-03-04 17:06:29 +0100, Mafi said:

If you try to use it in the manner of `something in 
classWhichDefinesThisOpBinary` then it doesn't work because operator 
overloading normally overloads on the left operand (ie something). Use 
opBinaryRight(string op)(...) if(...) to get it working.


Aaah. That makes sense. And works.

*But*: I copied my code from Phobos :D If you search for "in", with the 
quotes, in std/container.d, you'll find two occurrences. The actual 
live use (in RedBlackTree) is opBinaryRight (which makes sense), but in 
the dummy class, TotalContainer, which is described as "an 
unimplemented container that illustrates a host of primitives that a 
container may define", uses just opBinary. The doc-comment says that 
"$(D k in container) returns true if the given key is in the container".


So ... a "bug", I guess? (One that isn't really executed -- but 
still...) Worth reporting?


Anwyay: Thanks for the clarification :)

--
Magnus Lie Hetland
http://hetland.org



Overriding iteration

2011-03-04 Thread Magnus Lie Hetland
From what I understand, when you override iteration, you can either 
implement the basic range primitives, permitting foreach to 
destructively iterate over your object, or you can implement a custom 
method that's called, and that must perform the iteration. The 
destructiveness of the first option can, of course, be mitigated if you 
use a struct rather than a class, and make sure that anything that 
would be destroyed by popFront() is copied.


What I'm wondering is whether there is a way to do what Python does -- 
to construct/return an iterator (or, in this case, a range) that is 
used during the iteration, rather than the object itself?


I'm thinking about when you iterate directly over the object here. As 
far as I can see, the solution used in the std.container is to use 
opSlice() for this functionality. In other words, in order to iterate 
over container foo, you need to use foreach(e; foo[])? Is there no way 
to get this functionality directly (i.e., for foreach(e; foo))?


--
Magnus Lie Hetland
http://hetland.org



Overriding "in" operator

2011-03-04 Thread Magnus Lie Hetland
I'm writing a collection with functionality for membership checking. I 
thought it would be nice to use the "in" operator. In the docs for 
std.collections I surmise that this is the standard way to go. From the 
source code, I see there's no special opIn, but that it can be done 
with the more general...


   bool opBinary(string op)(T k) if (op == "in") {
   ...
   }

Here T is, of course, a compile-time argument of the surrounding struct 
or class.


So ... this is used in the the Phobos source in the DMD 2.052 distro 
(if I'm not mistaken), but I can't get dmd 2.052 to accept it? I keep 
getting the error message "Error: rvalue of in expression must be an 
associative array, not Foo!(uint)".


I guess either that this is a recent feature -- I didn't see it 
mentioned in Andrei's book -- and that my Phobos source is too recent 
for my dmd ... or that I'm doing something wrong elsewhere in my code, 
preventing the operator overloading to take force. 
Suggestions/solutions?-)


--
Magnus Lie Hetland
http://hetland.org



Re: Two questions about "%a"

2011-03-04 Thread Magnus Lie Hetland

On 2011-03-04 03:16:50 +0100, Nick Sabalausky said:

I'm no floating-point expert, but I would think that the only way to 
get an exact representation would be to output the raw data in hex (or 
binary, or octal, etc):


writef("0x%X", cast(ulong)1.2);


That's also an option, certainly. Then I could just write it as a 
decimal integer, I guess.


But the point of hex-literals for floats is precicely that they can 
represent floats exactly (even though it may not *look* like it, as in 
this case, because lots of digits are required to approximate the 
decimal value 1.2). So using those shold be safe -- and perhaps more 
easily read on other platforms, for example (byte order), or into 
floats with other precisions or the like.


Thanks for the suggestion, though :)

--
Magnus Lie Hetland
http://hetland.org



Re: @property ref foo() { ...} won't work...?

2011-03-02 Thread Magnus Lie Hetland

On 2011-03-01 13:20:18 +0100, Steven Schveighoffer said:

On Tue, 01 Mar 2011 07:19:21 -0500, Lars T. Kyllingstad 
 wrote:



On Tue, 01 Mar 2011 12:25:30 +0100, Magnus Lie Hetland wrote:


2. How can I make r.front = foo work, when I only have r.front(),
returning a ref (which seems like it is used in actual code)?


I think this is a bug, but I'm not entirely sure.


It is most definitely a bug.  Please file.


Done.


-Steve


--
Magnus Lie Hetland
http://hetland.org



Two questions about "%a"

2011-03-02 Thread Magnus Lie Hetland
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?


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?)


--
Magnus Lie Hetland
http://hetland.org



@property ref foo() { ...} won't work...?

2011-03-01 Thread Magnus Lie Hetland
In Andrei's book, as well as in the Phobos source, there are property 
getters that return refs, as in...


 @property ref T front() {
 return _payload[0];
 }

... and code that uses this with simple assignments, such as:

 r.front = foo;

For some reason, I can't get this to work in my code :-/ DMD seems to 
insist that I add a setter as well (i.e., @property T front(T val) { 
return _payload[0] = val; }).


On the other hand, I *do* get

 r.front() = foo;

to work. That works well even without @property, of course; and r.front 
fails even without @property.


Then, again, if I write both the getter (front()) and the setter 
(front(T)), that works even without @property (which, then, seems 
rather redundant?).


So ... I guess I have two questions:

1. What's the point of @property (when it seems I get the same 
functionality without it)?
2. How can I make r.front = foo work, when I only have r.front(), 
returning a ref (which seems like it is used in actual code)?


--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-28 Thread Magnus Lie Hetland

On 2011-02-27 02:33:46 +0100, Jonathan M Davis said:




[snip lots of useful stuff]

Thanks for your patience, and more useful clarifications. I think I get 
it now (but I may very well be wrong ;)


- M

--
Magnus Lie Hetland
http://hetland.org



Re: Is std.cover deprecated or gone?

2011-02-26 Thread Magnus Lie Hetland

On 2011-02-26 16:30:10 +0100, Magnus Lie Hetland said:


It's documented here...

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

... but I can't find it in the Phobos source. (Also, I can't import it 
-- which is perhaps the most pressing issue :)


It's just that I'm using rdmd (for convenience), but then I don't know 
where any coverage reports end up (unless I examine the path to the 
generated executable), so I thought I'd specify where I wanted them...


Seems the specific problem isn't really a problem -- rdmd with -conv 
places the files in the right directory anyway :)


--
Magnus Lie Hetland
http://hetland.org



Is std.cover deprecated or gone?

2011-02-26 Thread Magnus Lie Hetland

It's documented here...

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

... but I can't find it in the Phobos source. (Also, I can't import it 
-- which is perhaps the most pressing issue :)


It's just that I'm using rdmd (for convenience), but then I don't know 
where any coverage reports end up (unless I examine the path to the 
generated executable), so I thought I'd specify where I wanted them...


--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-26 Thread Magnus Lie Hetland

On 2011-02-26 15:20:19 +0100, David Nadlinger said:


On 2/26/11 1:15 PM, Jonathan M Davis wrote:

[...]  And from a perfectly practical standpoint, as soon as your code ends
up in a library, assertions are generally useless anyway,[...]


I don't quite think asserts are useless in libraries. If you need to 
care about performance in a library, you hit cases quite frequently 
where sanity-checking the input would be too expensive to be done in 
release mode, and thus you can't specify behavior on invalid input as 
part of your API using exceptions. Nevertheless, it is still useful to 
people using your library to get notified when they are messing 
something up as early as possible in debug mode, which is precisely 
what asserts are made for, at least in my opinion.


But that would only work if they had access to the source, or a version 
not compiled in release mode, right?


Hmm.

This is also related to what Jonathan said about programming by 
contract -- and only using in-clauses (for example) when you also 
control the calling code. I guess what you're saying could be an 
argument in the other direction: that even though they certainly 
shouldn't be considered part of the public API (beyond documenting what 
would be input causing undefined behavior), they *could* be useful in a 
library that a client could use in debug mode, because it gives them 
some extra tests for their own code, "for free". They can test that 
their own code is using your code correctly.


That sounds quite in line with programming by contract to me ... but 
then, again, I'm a reall n00b on the subject :)


--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-26 Thread Magnus Lie Hetland

On 2011-02-26 13:15:58 +0100, Jonathan M Davis said:


On Saturday 26 February 2011 03:24:15 Magnus Lie Hetland wrote:

OK. I had the impression that using assert() in contracts was standard,
also for API functions. I thought contracts fulfilled a similar sort of
function to assert(), in that they're removed in release code -- as
opposed to enforce(), for example...? I'm guessing that if I released a
binary version of a library, I wouldn't leave the contracts in? Or
perhaps I would (but, as you say, with exceptions)? Depends on the
situation, perhaps?

What kind of exceptions would be most relevant to indicate a contract
failure (if the contracts are made part of the API)?


Well, the biggest problem with using assertions to verify input to a 
function is

that if you distribute your code as a library, odds are it will be in release
mode, and then there won't be any assertions in it.


[snip lots of stuff]

After reading your response, I first made lots of comments, but it's 
all a bit redundant. My summary is:


- You're (at times) talking about preconditions as a general concept, 
and that for public APIs, they should be enforced using exceptions.
- I've only been talking about the *language feature* of preconditions, 
i.e., in-clauses.
- We're both clear on that preconditions and asserts disappear in 
release mode, and that the two belong together, as part of your test 
scaffolding (and not as part of your public API).


Sound about right?

[snip]

Regardless of that, however, assertions should only be used when testing the
internal logic of your program. If code from other libraries or any other code
which you wouldn't be looking to test calls your function, then don't use an
assertion to verify pre-conditions. If you're using assertions, you're testing
that the caller is correct. You're verifying that the caller is not violating
your contract, but you're _not_ guaranteeing that the function will 
fail if they

violate the contract (since assertions can go away).


A very clarifying way of putting it, indeed.

As for my "testing the test code" intention, I guess (as I said) I 
actually *did* want to test the test. Not, perhaps, that it was correct 
(as discussed, it should be really simple), but to see it fail at least 
once -- a basic principle of test-driven programming. But I'll find 
other ways of doing that -- for example deliberately making the 
precondition slightly wrong at first :)


The test for the contract  is therefore _not_ part of the API. With 
Exceptions it _is_.


Right.

So, what it really comes down to is whether you looking to test the 
code which calls your function and are therefore willing to have that 
code give you bad input and let your function process it anyway (when 
assertions aren't compiled in) and you therefore use assertions, _or_ 
you're looking to guarantee that your function does _not_ continue if 
the contract is violated, and you want to _always_ error out - in which 
case you use Exceptions.


Yep. All in all, a very useful clarification for me.

As a side note: Why isn't there a release-version of the contract 
mechanisms? I would've thought that contracts would be even more useful 
between different programmers, than just between you and yourself...?-)


That is, wouldn't the same kind of mechanism be useful for *exactly* 
the kind of exception-based input checking that you're describing as 
the alternative to contracts+asserts?


I mean, the reason to remove preconditions and asserts is primarily 
performance and not semantics (although it certainly affects semantics, 
as you've pointed out)? We have enforce() as the alternative to 
assert(); why no alternative to in/out and invariants?


[snip]

And if you're using unit tests to test those, you're testing test code.


Sure. I've already accepted this :)

[snip]
Still, if you start testing test code, at what point does it make sense 
to stop?


Hm. Maybe I should write a test that tests itself?-)

More seriously: your points are well taken.

I still have a vague feeling that in-clauses are a bit different from 
out-closes, invariants and plain unit tests when it comes to the "fail 
first" approach to test-driven programming. A precondition won't fail 
because your code isn't yet functional -- it will only fail if you've 
actively written *wrong* code. But I guess that's just how it is :)



Complicated tests of _any_ kind are a bit dangerous.

[snip]

Hm. True.

Thanks for lots of useful input!

(Still curious about the hypothetical "public API contract" 
functionality, though, and why it's non-existent.)


--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-26 Thread Magnus Lie Hetland

On 2011-02-26 01:20:49 +0100, Jonathan M Davis said:


So, using such assertions makes good sense when you control
both the caller and the callee and it's something that should never happen.


Yeah, in my case that's what's going on. I'll only be using the 
contracts during testing anyway, and remove them with -release in the 
code that's actually to be used. (The code is part of some benchmarking 
experiments, so I'd rather not have any kind of checking like that when 
running those.)



However, if you don't necessarily control the caller or if it's something that
_could_ happen at runtime (even if it shouldn't), then an exception makes a lot
more sense.


OK. I had the impression that using assert() in contracts was standard, 
also for API functions. I thought contracts fulfilled a similar sort of 
function to assert(), in that they're removed in release code -- as 
opposed to enforce(), for example...? I'm guessing that if I released a 
binary version of a library, I wouldn't leave the contracts in? Or 
perhaps I would (but, as you say, with exceptions)? Depends on the 
situation, perhaps?


What kind of exceptions would be most relevant to indicate a contract 
failure (if the contracts are made part of the API)?



I tend to view exceptions as part of the API and think that they should be
tested. Assertions, on the other hand, aren't really part of the API, 
since they

go away in release mode, and I therefore view them as test code. They're
verifying that your logic is correct.


Exactly. The same, of course, applies to contracts -- which is why I'm 
a bit confused by your suggestion to use exceptions in them.


Or perhaps I'm misreading you completely, and you're only suggesting 
that I use code paths that throw exceptions in the function body 
itself, e.g., with enforce(foo, exception) (which would make sense to 
me)?



So, on some level, it is indeed a stylistic thing, but where you choose to use
exceptions and where you choose to use assertions can have a big effect on code
that uses your code.


Sure thing. It just seems to me that contracts and assertions go well 
together, and have the same function, of testing your program logic?


I guess the driving force of my original query was the old "first, see 
your test fail" idea of test-driven programming. If I just slap a 
precondition on some code, it won't fail because things aren't 
implemented properly yet (as a normal unit test would) -- I'd actively 
have to implement a call to it *improperly*. It just seemed naturally 
to me to do that as part of the test code, rather than a one-off thing 
in the main code.


However, I could always add a call to my unit test, run it, and see it 
crash -- and then comment it out. Doesn't seem like the prettiest way 
to handle things, but it's OK, I guess together with the idea of making 
the contracts super-simple (and to test any functionality they use 
separately).


[snip]

I guess the conclusion will be that I'll focus on keeping my
preconditions really simple. (And any utility functions I use in them
can then get unit tests of their own instead ;)

That's probably a good way to handle it .


OK, good :)

--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-25 20:04:10 +0100, Jonathan M Davis said:


On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in
my preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is
what assert() throws -- so what's the standard way of writing unit
tests for preconditions that use assert? (I.e., test that they will, in
fact, throw when you break them.)


I think that the reality of the matter is the most of the time people _don't_
check them. And on some level, it doesn't make sense to. It's kind of like
asking how people test their unit tests. Unit tests are already testing 
code. Do

you want to be testing them on top of that? And if you do, do you test _that_
code? Where do you stop?


I guess so. But you could say the same thing about other cases where 
you throw an exception when you detect that something is wrong -- but 
those are normally tested, right? Also, the difference here is that the 
precondition is written as a general "test", whereas my actual test 
would have specific cases.


For example, I have a test that checks that I don't add the same object 
twice to some structure, and the check involves some traversal -- code 
that could potentially be wrong. I wanted to make sure that it wasn't 
by explicitly adding the same object twice -- code (i.e., my unit test) 
that most likely could not be wrong.


But I do see your point.

[snip]

And testing post-conditions and invariants in the manner that you're trying to
do borders on impossible. What are you going to do, repeat the 
post-condition or

invariant test on the result of the function or on the state of the object that
the function was called on after the function was called? That's just doing the
test twice.


Right.


You might as well just re-read the post-conditions and invariants to
make sure that you wrote them correctly.

I do see value in testing pre-conditions if you're using exceptions rather than
assertions (which means that you're not use in blocks). In that case, you're
testing the API to make sure that it does what it's supposed to do. But if
you're dealing with assertions, then it's really test code as opposed to API
code, and I don't see the same value in testing that. You'd just be 
testing test

code.


OK. For the practical reason, I refer you to my explanation above. But 
I guess it's a style issue -- and I'm fine with not testing these 
things, by all means.


[snip]

Those changes _do_ make it so that you can use collectException to
collect an Error (though it defaults to catching Exceptions only), but 
they also

include assertThrown and assertNotThrown which effectively assert that the
Exception or Error that you expected to be thrown (or not) from a particular
expression or function call was indeed thrown (or not).
So, you _can_ use that with AssertError to verify your pre-conditions.


OK, thanks.


However, I would point out that catching Errors is generally a _bad_ idea.

[snip lots of useful stuff]

Thanks for educating me :D

I guess the conclusion will be that I'll focus on keeping my 
preconditions really simple. (And any utility functions I use in them 
can then get unit tests of their own instead ;)


--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-25 17:48:54 +0100, spir said:


On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in my
preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is what
assert() throws -- so what's the standard way of writing unit tests for
preconditions that use assert? (I.e., test that they will, in fact, throw when
you break them.)


See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html.

Denis


Hm. I'm not sure how this answers my question. I know how 
pre/postconditions etc. work -- I was asking for how to test them in a 
unit test (i.e., ensure that they'll kick in if you provide faulty 
intput, for example). Maybe I'm missing something in the doc you 
referred me to?


--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-25 19:18:40 +0100, Jesse Phillips said:


There has been talk of a std.unittest that would help with this, but for now:



unittest {
try {
 callMeWrong(wrong);
 assert(0);
catch(AssertError e) {
}
}

}


Ah. I used something like...

auto thrown = 0;
try foo() catch (AssertError) thrown++;
...
assert(thrown == k);

I guess I could wrap it up a bit, or something.

--
Magnus Lie Hetland
http://hetland.org



How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland
Or, more generally, how do you test asserts (which is what I'm using in 
my preconditions etc.)?


As far as I can see, collectException() won't collect errors, which is 
what assert() throws -- so what's the standard way of writing unit 
tests for preconditions that use assert? (I.e., test that they will, in 
fact, throw when you break them.)


--
Magnus Lie Hetland
http://hetland.org



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

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-21 15:17:44 +0100, Jacob Carlborg said:


On 2011-02-21 14:16, Lars T. Kyllingstad wrote:


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.


Let me first clarify: By "nothing happens", I really mean that. When I 
supply --shebang, the code isn't compiled, and nothing is run. Running 
the script becomes a no-op.


As for your example: The switches to rdmd *don't* appear in args for 
me. So for example, if I have


#!/path/to/rdmd -unittest

... as the shebang line, rdmd finds and passes the -unittest switch to 
dmd (my unit tests work). I get no problems when I add more switches 
either (i.e., rdmd doesn't complain). But, as far as I can see, none of 
these end up in args. (Or are we talking about different things here?)


Instead, args[0] contains the full path to the temporary executable 
built and run by rdmd, and args[1..$] contain any arguments I supplied 
when running the script.


The fact that --shebang borks the whole execution seems like it must be 
a bug. As for the rest of the behavior, it seems pretty useful to me, 
but perhaps OS X-specific? (That would be odd, but who knows...)


--
Magnus Lie Hetland
http://hetland.org



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

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-22 22:46:41 +0100, Paolo Invernizzi said:


Hi Magnus,

This is sligthly OT, but... How I loved AnyGui!


Haha, cool :D Yeah, too bad the project died. Oh, well -- at least we tried :)


It's nice to see you here, in the D bandwagon...


Yeah, I've been looking for a more "close to the metal" language to 
complement Python for a looong time (using C and C++ when I had to -- 
and sometimes Java or Cython and what-have-you). At the moment I'm 
hopeful that D might be what I've been looking for. Loving it so far :)


(Still using Python, though. Just came out with a new Python book, 
"Python Algorithms", last fall ;)




--
Magnus Lie Hetland
http://hetland.org



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

2011-02-21 Thread Magnus Lie Hetland

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?

--
Magnus Lie Hetland
http://hetland.org



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

2011-02-21 Thread Magnus Lie Hetland

On 2011-02-20 22:42:06 +0100, Nick Sabalausky said:

[snip]
We used to have occasional breking changes in the language itself (in 
D2-only), since D2 was the deliberately the "development" branch rather 
than the "stable" branch that D1 has been, but D2's language spec is 
pretty much finalized now.




I just realized I didn't give a direct answer to your question: I'd say 
that most minor releases of DMD are *not* backward-incompatible.


Thanks for both the thorough and the more direct answer. Very helpful/useful :)

--
Magnus Lie Hetland
http://hetland.org



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

2011-02-20 Thread Magnus Lie Hetland

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!

(Yes, it is 4 months old, and I can do the match: 3 < 4, but this *is* 
the same as the latest official version just with my patches applied: 
The latest official commit to rdmd.d was one of my patches (albiet 
slightly modified, IIRC))


However, the latest version of DMD I used this with was 2.050, so it 
might still need some updating for 2.052.


Hm. Are most minor releases of DMD backward-incompatible? (Sort of a 
scary prospect to me, at least...)


--
Magnus Lie Hetland
http://hetland.org



rdmd problems (OS X Leopard, DMD 2.052)

2011-02-19 Thread Magnus Lie Hetland

Hi!

When I installed DMD 2.051 on my OS X boxen, the rdmd executable didn't 
work. I saw others have similar problems online, and concluded that it 
must have been compiled for a more recent version of OS X (Snow 
Leopard, I guess) without the necessary compatibility flags.


I found the rdmd sources online [1] and compiled them myself. (Luckily, 
the other binaries work just fine.) No problems.


Now I'm trying to get DMD 2.052 to work. Same issue with the rdmd 
executable. I tried to compile the same rdmd.d file with the new 
compiler/stdlib, but that failed.


$ dmd rdmd.d
std.contracts has been scheduled for deprecation. Please use 
std.exception instead.
std.date and std.dateparse have been scheduled for deprecation. Please 
use std.datetime instead.
rdmd.d(34): Error: std.regexp.split at 
./../../src/phobos/std/regexp.d(498) conflicts with std.string.split at 
./../../src/phobos/std/string.d(69)
rdmd.d(34): Error: function std.regexp.split (string s, RegExp pattern) 
is not callable using argument types (string)

rdmd.d(34): Error: expected 3 function arguments, not 1

I'm sure I can fix this myself -- but I'm guessing there must be a more 
recent version of the rdmd sources somewhere, assuming that the binary 
in the distribution was compiled with dmd 2.052...? The version in the 
trunk at dsource.org seems to be three months old...


For now I just compiled the rdmd.d from dsource.org with dmd 2.051, and 
use that with dmd 2.052. As rdmd is basically an independent entity, I 
guess that should work well, but this isn't exactly user-friendly 
(i.e., having to replace one of the binaries in the distro with one 
compiled with an older compiler, using sources obtained elsewhere... 
:->).


Not sure if I'm missing The Way to Do It[tm], or if perhaps I should 
submit an issue about this?


[1] http://www.digitalmars.com/d/2.0/rdmd.html

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 16:41:33 +0100, Simen kjaeraas said:

That certainly makes sense. I just got thrown off by the example in 
std.algorithm:


uint hashFun(string) { ... expensive computation ... }
string[] array = ...;
// Sort strings by hash, slow
sort!("hashFun(a) < hashFun(b)")(array);

The only way this could work would be if hashFun was available to the 
sort template, I guess...?


Nope, still std.functional. That's where the string is mixin'ed.


Right. Given the example, there's no way to tell that sort is 
implemented using std.functional, so really meant whichever function is 
actually using the string ;) But, yeah, I understand how it works. 
Thanks.



But thanks for noting that, I've filed it as issue #5513.


Good.

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 16:09:22 +0100, Simen kjaeraas said:


Magnus Lie Hetland  wrote:

Sort of related (though perhaps only remotely) is the following, which 
won't compile (Error: static assert "Bad unary function: f(a) for type 
int"):


Not related. unaryFun and binaryFun are simply glorified string mixins,
and thus can only access functions that are available in the modules
where they are mixed in. That would be std.functional. Because of that,
local functions may not be used as string arguments for *naryFun.


That certainly makes sense. I just got thrown off by the example in 
std.algorithm:


 uint hashFun(string) { ... expensive computation ... }
 string[] array = ...;
 // Sort strings by hash, slow
 sort!("hashFun(a) < hashFun(b)")(array);

The only way this could work would be if hashFun was available to the 
sort template, I guess...?


--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 16:00:16 +0100, Magnus Lie Hetland said:


  import std.functional, std.stdio;
  int f(int x) {return x;}
  void main() {
  alias unaryFun!("f(a)") g;
  writeln(g(3));
  }


Just to be clear -- I realize I could just have used unaryFun!f here 
(or just f, for that matter). The usage case was actually currying. I 
used "f(x,a)" as a compile-time argument to the kind of template that 
we discussed earlier. And the reason I tried that was that this didn't 
work either:


 import std.functional, std.stdio;
 int f(int x, int y) {return x;}
 void main() {
 alias unaryFun!(curry(f, 2)) g;
 writeln(g(3));
 }

At that point, the only thing that worked was using a lambda. And, as I 
pointed out, with the nested templates, that didn't work either.


Seems like the language (or the stdlib) is resisting my efforts at 
every turn here. Perhaps I should just write out those for-loops 
redundantly, rather than using templates ;)


--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 12:37:05 +0100, Simen kjaeraas said:


Magnus Lie Hetland  wrote:

Hm. Just to make sure this *is* a bug, and I'm not just being a dumbass 
... this is a tiny program that illustrates the problem (i.e., gives 
the error above). Perhaps the use of a local function here really is 
prohibited...?


Maybe it is. It really shouldn't be, though. If this is not a bug, then
Walter has a bug for not accepting this as a bug. :p


Hehe :)

Sort of related (though perhaps only remotely) is the following, which 
won't compile (Error: static assert "Bad unary function: f(a) for type 
int"):


 import std.functional, std.stdio;
 int f(int x) {return x;}
 void main() {
 alias unaryFun!("f(a)") g;
 writeln(g(3));
 }

It may not be related -- but I've been trying to use the string 
representation instead of lambda in some places, and I thought maybe a 
similar name lookup problem may be present in the unaryFun template? 
(The detauls of the implementation are a bit beyond me at the moment...)


Maybe there's an unstated restriction against using functions in the 
unaryFun string parameter (at least I couldn't find it in the docs) -- 
but ... there is the following example in the docs for std.algorithms:


 sort!("hashFun(a) < hashFun(b)")(array);

So it would seem like this *should* work?

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 10:12:44 +0100, Magnus Lie Hetland said:


On 2011-01-31 19:46:53 +0100, Simen kjaeraas said:


Magnus Lie Hetland  wrote:

Hm. Using code quite similar to you, supplying a lambda in the second 
aliasing, I get this error:


something.d(93): Error: template instance cannot use local 
'__dgliteral2(__T3)' as parameter to non-global template optArg(alias 
fun)

[snip]


This is a bug. Please report it.


Ah -- OK. Will do.


Hm. Just to make sure this *is* a bug, and I'm not just being a dumbass 
... this is a tiny program that illustrates the problem (i.e., gives 
the error above). Perhaps the use of a local function here really is 
prohibited...?


template A(int op) {
   template A(alias fun) {
   auto A(T)(T x) {
   return 0;
   }
   }
}
alias A!0 B;
int gun() {
   return 0;
}
void main() {
   int fun() {return 0;}
   // alias B!((){return 0;}) C; // Won't compile
   // alias B!(fun) C;   // Won't compile
   alias B!(gun) C;      // Works
}

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 10:49:23 +0100, bearophile said:


Magnus Lie Hetland:


Saw your post on digitalmars.D now, about the currying of templates
(i.e., the main topic here). I guess perhaps that was what you were
talking about?


Tuple unpacking syntax and template currying  are two different things.


Yes, certainly. That was the point of this post -- that I misunderstood 
what you were talking about in the original post (where you said "this 
topic" right after my tuple unpacking paragraph) :)


--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-02-01 10:11:53 +0100, Magnus Lie Hetland said:


On 2011-01-31 22:21:40 +0100, bearophile said:


Magnus Lie Hetland:

[snip]

I'm accustomed to is the ability to
assign to multiple variables, such as

arg, val = minArg(...)

(Yeah, I'm a Python guy... ;)


I will eventually add a detailed enhancement request on this topic.


Great! I think this is really useful -- also for swapping things around 
(a, b = b, a). For multiple return values it makes a huge difference, 
IMO.


Saw your post on digitalmars.D now, about the currying of templates 
(i.e., the main topic here). I guess perhaps that was what you were 
talking about?


That would certainly be great, too :)

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-01-31 19:46:53 +0100, Simen kjaeraas said:


Magnus Lie Hetland  wrote:

Hm. Using code quite similar to you, supplying a lambda in the second 
aliasing, I get this error:


something.d(93): Error: template instance cannot use local 
'__dgliteral2(__T3)' as parameter to non-global template optArg(alias 
fun)

[snip]


This is a bug. Please report it.


Ah -- OK. Will do.

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-02-01 Thread Magnus Lie Hetland

On 2011-01-31 22:21:40 +0100, bearophile said:


Magnus Lie Hetland:

[snip]

I'm accustomed to is the ability to
assign to multiple variables, such as

arg, val = minArg(...)

(Yeah, I'm a Python guy... ;)


I will eventually add a detailed enhancement request on this topic.


Great! I think this is really useful -- also for swapping things around 
(a, b = b, a). For multiple return values it makes a huge difference, 
IMO.


--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-01-31 Thread Magnus Lie Hetland
Hm. Using code quite similar to you, supplying a lambda in the second 
aliasing, I get this error:


something.d(93): Error: template instance cannot use local 
'__dgliteral2(__T3)' as parameter to non-global template optArg(alias 
fun)


It seems it's explicitly objecting to what I want it to do...

Using optArg!"a", for example, works just fine -- but the whole point 
was to include some local state. Using local functions worked (I 
think...?) when I had a global template.


It seems D's compile-time computation system is less straightforward 
than I thought :)


--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-01-31 Thread Magnus Lie Hetland

On 2011-01-31 15:50:41 +0100, Simen kjaeraas said:


You might want to try more from dranges - the reftuple:

_(arg,val) = minArg(...);

[snip]

This is also a possible implementation (coded in about 5 minutes, gives
no nice error messages, but it seems to work :p ):


Thanks :)


Yeah. D has the nice Eponymous Template Trick, but it sadly only works
for one level. :(


Right :-/


So you have to test for every single element of the range?


Yup.


If so, I think this works:


Thanks. Hm. The nesting does seem similar to how I did it, but I guess 
there must be some crucial difference ;-)


At the moment, I'm using a mixing to create the min and max templates 
(as rather large strings). Probably not ideal.


Thanks!

--
Magnus Lie Hetland
http://hetland.org



Re: Partially instantiating templates?

2011-01-31 Thread Magnus Lie Hetland

On 2011-01-31 12:55:07 +0100, Simen kjaeraas said:

ElementType!Range minArg( alias fun, Range )( Range range, out 
ReturnType!fun ) {

 ...
}


Aaaah. I guess I tried ElementType(Range), forgetting to make it a 
compile-time parameter. Thanks. (Hadn't seen ReturnType; makes sense :)



Might I also ask why you use an out parameter instead of a tuple return?


Well... I had a tuple return at first, but one of the advantages of 
returning multiple values that I'm accustomed to is the ability to 
assign to multiple variables, such as


 arg, val = minArg(...)

(Yeah, I'm a Python guy... ;)

As far as I can see, you can't do that here? Using result[0] and 
result[1] or the like, or assigning separately to two variables just 
seemed more cumbersome. Then again, I could use a tuple with named 
members, I guess. In your opinion, what would be the prettiest (in D 
terms) way of doing this?


[snip]

D currently does not support template currying to any good degree.


OK. Well, I guess I don't really need it. Still trying to get a feel 
for what's "normal" D :)



However, there is at least one library out there that does that for you:

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

In the file templates.d, there is the template CurryTemplate, which
rewrites a template to a set of nested templates. This would allow you
to partially instantiate a template, and add more parameters as you go.


I see. I actually don't mind writing nested templates myself -- but for 
some reason I couldn't get them to work properly. (D kept complaining 
about declarations vs instances, and the like; I guess I'll have a look 
at how dranges does it.)


I've been able to make either one of these two pieces of functionality 
work with some twiddling and nesting (i.e., *either* instantiating 
optArg into minArg/maxArg, *or* instantiating explicitly defined 
minArg/maxArg into specialized functions) but combining them has so far 
eluded me (unless I start fiddling with strinc constants and mixin(), 
which seems excessively hacky for such a simple thing).


dranges' templates.CurryTemplate should take care of some of your problems.
Not sure if it will fix them all.


OK, thanks.

By the way, if you have suggestions for other more "D-like" ways of 
encapsulating this functionality (basically a linear scan for an 
element that yields a max/min value for a given expression), I'd be 
interested to hear that too. The best way to solve a problem is often 
to rephrase it :)


--
Magnus Lie Hetland
http://hetland.org



Partially instantiating templates?

2011-01-31 Thread Magnus Lie Hetland
I'm building a function (or template or whatever, really) that is 
related to map and minPos in std.algorithm. Basically, it's the 
standard mathematical argmin, except that it also returns min. It looks 
something like this:


 auto minArg(alias fun, Range, T)(Range range, out T minVal) {
 ...
 }

Already there may be issues -- the return type should be 
ElementType(range) and T should be the return type of fun ... but it 
works. (Suggestions on these issues are welcome, but that's not really 
the main point here.)


The thing is, because I'm also returning the actual value, I'd rather 
not use the strategy of std.algorithm.minPos, which asks you to use an 
inverted function to get maxPos; instead, I'd like an explicit maxArg 
function. My idea was to have a common, more general optArg, which took 
an operator ("<" or ">") as a compile-time argument. Then I could do 
something like


 alias optArg!"<" minArg;
 alias optArg!">" maxArg;

Then, at some *later* time, I might want to do something like:

 alias maxArg!((v) {return dist(u,v);}) farthest;

(By the way: For some reason, I'm not allowed to use curry(dist,u) 
instead of the lambda here, it seems. Any insights on that? Would have 
been nice to use "d(u,a)" as well -- as I do use unaryFunc on the fun 
argument. That doesn't work either, though...)


I've been able to make either one of these two pieces of functionality 
work with some twiddling and nesting (i.e., *either* instantiating 
optArg into minArg/maxArg, *or* instantiating explicitly defined 
minArg/maxArg into specialized functions) but combining them has so far 
eluded me (unless I start fiddling with strinc constants and mixin(), 
which seems excessively hacky for such a simple thing).


Any ideas/suggestions? I'm sure I'm missing something obvious ... 
(Perhaps even existing functionality for minArg/maxArg -- although the 
general question still stands.)


--
Magnus Lie Hetland
http://hetland.org