Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Bayan Rafeh via Digitalmars-d-learn

On Sunday, 25 January 2015 at 08:39:42 UTC, Bayan Rafeh wrote:
On Sunday, 25 January 2015 at 00:43:43 UTC, Vladimir Panteleev 
wrote:
On Saturday, 24 January 2015 at 12:16:38 UTC, Bayan Rafeh 
wrote:
This problem is a tough one. I've been getting this error 
when I run my unittests, and apparently it is caused by 
attempting an allocation in the destructor from what little I 
could find online about the subject.


The error is triggered once all my tests are complete, so I'm 
assuming the garbage collector is running before termination, 
but I tried placing logging messages in all my destructors 
and I didn't get anything, so none of them are being called.


Is there any other possible reason to get this error?


Hi,

I created a wiki page which I hope will help you solve this 
problem:


http://wiki.dlang.org/InvalidMemoryOperationError

Hope this helps.


Thank you very much, this will certainly be useful in debugging 
it.


The allocations may be indirect. For example, formatting a 
string to log a message may allocate. Try marking your 
destructors as @nogc to see whether the compiler agrees.


I tried what you said and I think I see the problem. I managed 
to create an example program that duplicates the problem:



import std.stdio;

class A {
string path;

this(string p) {
path = p;
}
~this() {
}
void a(){}

void b(){}
}

class B {
A a;
this() {
this.a = new A(laladiv);
}
~this() {
delete a;
}
}

void main() {
B a = new B();
B b = new B();
delete b;
}


The solution was just to remove the delete a from the 
destructor if someone comes across this later. Could someone tell 
me why though?


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Vladimir Panteleev via Digitalmars-d-learn

On Sunday, 25 January 2015 at 08:41:25 UTC, Bayan Rafeh wrote:
The solution was just to remove the delete a from the 
destructor if someone comes across this later. Could someone 
tell me why though?


The non-reentrant bit applies to all GC operations, really - 
not just allocations. Explicit deletions are forbidden as well.


Use of the delete keyword is discouraged, and in that context, 
it is also not used in a safe way. By the time B's destructor is 
called, the A instance might have been already collected by the 
garbage collector, causing a double free bug (one of the reasons 
to not use delete).


Re: crash on args.getopt

2015-01-25 Thread Tobias Pankrath via Digitalmars-d-learn

On Sunday, 25 January 2015 at 10:21:34 UTC, Suliman wrote:
But is it good practice to fail with exception during passing 
unknown parameters? Maybe std.getopt.config.passThrough should 
be as default?


I really can't remember Apps that crush if pass to in unknown 
parameters.


Almost all programs fail with an error message, if you pass 
unknown parameter. Just catch that exception.


Re: using the full range of ubyte with iota

2015-01-25 Thread bearophile via Digitalmars-d-learn

Vlad Levenfeld:

What's this about !`[]` and std.range.uniform?? It's not in the 
documentation.


It's an enhancement I have proposed.

Bye,
bearophile


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Bayan Rafeh via Digitalmars-d-learn
On Sunday, 25 January 2015 at 00:43:43 UTC, Vladimir Panteleev 
wrote:

On Saturday, 24 January 2015 at 12:16:38 UTC, Bayan Rafeh wrote:
This problem is a tough one. I've been getting this error when 
I run my unittests, and apparently it is caused by attempting 
an allocation in the destructor from what little I could find 
online about the subject.


The error is triggered once all my tests are complete, so I'm 
assuming the garbage collector is running before termination, 
but I tried placing logging messages in all my destructors and 
I didn't get anything, so none of them are being called.


Is there any other possible reason to get this error?


Hi,

I created a wiki page which I hope will help you solve this 
problem:


http://wiki.dlang.org/InvalidMemoryOperationError

Hope this helps.


Thank you very much, this will certainly be useful in debugging 
it.


The allocations may be indirect. For example, formatting a 
string to log a message may allocate. Try marking your 
destructors as @nogc to see whether the compiler agrees.


I tried what you said and I think I see the problem. I managed to 
create an example program that duplicates the problem:



import std.stdio;

class A {
string path;

this(string p) {
path = p;
}
~this() {
}
void a(){}

void b(){}
}

class B {
A a;
this() {
this.a = new A(laladiv);
}
~this() {
delete a;
}
}

void main() {
B a = new B();
B b = new B();
delete b;
}


Re: crash on args.getopt

2015-01-25 Thread Suliman via Digitalmars-d-learn
But is it good practice to fail with exception during passing 
unknown parameters? Maybe std.getopt.config.passThrough should be 
as default?


I really can't remember Apps that crush if pass to in unknown 
parameters.


Re: What to do with InvalidMemoryOperationError

2015-01-25 Thread Nordlöw
On Sunday, 25 January 2015 at 00:44:07 UTC, Vladimir Panteleev 
wrote:

I created a wiki page which I hope will help you solve this
problem:

http://wiki.dlang.org/InvalidMemoryOperationError

Hope this helps.


Great! Thanks!


Re: crash on args.getopt

2015-01-25 Thread FG via Digitalmars-d-learn

On 2015-01-25 at 11:42, Tobias Pankrath wrote:

On Sunday, 25 January 2015 at 10:21:34 UTC, Suliman wrote:

But is it good practice to fail with exception during passing unknown 
parameters? Maybe std.getopt.config.passThrough should be as default?

I really can't remember Apps that crush if pass to in unknown parameters.


Almost all programs fail with an error message, if you pass unknown parameter. 
Just catch that exception.


It's much better to fail up front than to create the illusion that everything is fine after the user has 
mistyped one of the parameters. Let's say foo a b copies from a to b, but foo --reverse a 
b does the opposite. Then, when someone types for example foo --revrse a b, and it is 
silently accepted, the program does exactly the opposite of what the user expects!

A side note: GTK applications accept extra parameters used to initialize GTK, but it is 
not passThrough. What really happens is that the app calls gtk_init(argc, 
argv) (or Main.init(args) in case of GtkD) before it starts parsing arguments on 
its own. The call to gtk_init removes the options recognized by GTK from the list of 
program arguments, and this filtered array can be then processed in a normal way -- 
which means that whichever parameters are still left unrecognised, the program should 
fail with an error message.


Re: using the full range of ubyte with iota

2015-01-25 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

On Sunday, 25 January 2015 at 10:42:51 UTC, bearophile wrote:

Vlad Levenfeld:

What's this about !`[]` and std.range.uniform?? It's not in 
the documentation.


It's an enhancement I have proposed.


Hm. I had more something in mind like paramCast - a kind of big 
scissors that cut everything a function is called with to the 
size it can cope with, so replacing


map!fn

not with

map!(x = fn(cast(ParameterTypeTuple!fn[0])x)

but instead with

map!(paramCast!fn)

Because this is useful in more situations, e.g. in every place 
where you know the values would fit into the parameter (and for a 
single call would use a cast).


But so far I couldn't manage to make this work :-/


Re: using the full range of ubyte with iota

2015-01-25 Thread Tobias Pankrath via Digitalmars-d-learn
On Sunday, 25 January 2015 at 12:25:35 UTC, Dominikus Dittes 
Scherkl wrote:


map!(x = fn(cast(ParameterTypeTuple!fn[0])x)

but instead with

map!(paramCast!fn)

Because this is useful in more situations, e.g. in every place 
where you know the values would fit into the parameter (and for 
a single call would use a cast).


But so far I couldn't manage to make this work :-/


http://dpaste.dzfl.pl/07b1fa3c2dad


Re: using the full range of ubyte with iota

2015-01-25 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

On Sunday, 25 January 2015 at 13:03:16 UTC, bearophile wrote:

Dominikus Dittes Scherkl:


Because this is useful in more situations,


Right, but it's still a cast. And in D you want to minimize the 
number of usages of casts. The proposed syntax iota![] is 
cast-safe.


I don't case too much, if I have ensured the cast is safe by 
constraints beforehand.


I need to cast often anyway, because I work with small types and 
most operators permanently change everything to int, especially 
the bit-operations for which a signed type makes no sense at all:


ubyte x = 50;
auto y = x  0x11; // y is int! I hate that!

even if I use unsigned literals:
auto z = x  0x12u; // z is uint - better but still bad. More so 
as  should result in the smaller of the two types!!


But I need not even use literals (which unfortunately cannot be 
makred as ubyte or short). Look at this:


auto x2 = (x4) | (x4); // swap nibbles - but result in an 
int!


Re: Link errors with curl, libevent, OpenSSL

2015-01-25 Thread AndyC via Digitalmars-d-learn

On Sunday, 25 January 2015 at 15:11:33 UTC, AndyC wrote:
On Sunday, 25 January 2015 at 05:48:26 UTC, Vladimir Panteleev 
wrote:
On my Ubuntu Server, I can't link any D program which uses 
libraries other than Phobos.


Example:

//
import std.net.curl;
import std.stdio;

void main()
{
   writeln(get(dlang.org));
}
//

dlang@k3:~/2015-01-25$ dmd -L-lcurl test.d
/usr/local/lib/x86_64-linux-gnu/libphobos2.a(curl.o): In 
function `_D3std3net4curl4HTTP19_sharedStaticCtor34FZv':

/usr/local/src/phobos/std/net/curl.d:2503: undefined reference



What weirdness has Ubuntu done that this doesn't work?  I'm 
running Slackware and just tried your example and it works fine.


Does Ubuntu have developer curl packages as well as regular 
curl packages?  Maybe libcurl-dev package?


-Andy



Yep, Ubuntu bug:

https://bugs.launchpad.net/ubuntu/+source/curl/+bug/1001576

-Andy


Re: Conflicts with Import error - New to D, trying to build a new project

2015-01-25 Thread Gan via Digitalmars-d-learn

Thanks. I didn't realize that could conflict.

On Sunday, 25 January 2015 at 21:22:50 UTC, Ali Çehreli wrote:

On 01/25/2015 11:30 AM, Gan wrote:

Here's a screenshot: http://cl.ly/image/2n282v0B1X2M

The error is: 
/Users/Matt/Projects/spacecraft/source/Game/Game.d(0,0):
Error: class Game.Game.Game conflicts with import 
Game.Game.Game at

source/Game/Game.d(2) (spacecraft)

I figure it's because I did imports wrong or something. I'm 
still very

new to D. Can anyone help?


The problem is with having three constructs with the same name: 
package, module, and class.


I would use lowercase for package, and module names, and 
differentiate between the package and the module:


.../source/foogame/game.d

module foogame.game;

class Game
{
// ...
}

Ali




Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 01/25/2015 02:06 PM, Bayan Rafeh wrote:


is invariant() called during the destruction phase?


Something is fishy.

import std.stdio;

void main(){
writeln(entered main);
auto a = new A();
writeln(leaving main);
}

class A {
File file;

this() {
writeln(this);
}

~this() {
writeln(~this);
}

invariant() {
writeln(invariant);
}
}

The program produces the following output:

entered main
this
invariant
leaving main
invariant
invariant-- ?
~this
invariant-- ?

Removing the File member changes the output. Now two of the invariant 
calls are missing:


entered main
this
invariant
leaving main
invariant
~this

However, the last invariant is still there and I think by design: The 
destructor should see a valid state.


Ali



Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Bayan Rafeh via Digitalmars-d-learn

On Sunday, 25 January 2015 at 22:46:56 UTC, Ali Çehreli wrote:

On 01/25/2015 02:06 PM, Bayan Rafeh wrote:


is invariant() called during the destruction phase?


Something is fishy.

import std.stdio;

void main(){
writeln(entered main);
auto a = new A();
writeln(leaving main);
}

class A {
File file;

this() {
writeln(this);
}

~this() {
writeln(~this);
}

invariant() {
writeln(invariant);
}
}

The program produces the following output:

entered main
this
invariant
leaving main
invariant
invariant-- ?
~this
invariant-- ?

Removing the File member changes the output. Now two of the 
invariant calls are missing:


entered main
this
invariant
leaving main
invariant
~this

However, the last invariant is still there and I think by 
design: The destructor should see a valid state.


Ali


Could this be a bug in D?


Re: Turning Executable into Application?

2015-01-25 Thread Laeeth Isharc via Digitalmars-d-learn

On Monday, 26 January 2015 at 03:36:32 UTC, Gan wrote:
With Xamarin Studio I create a D project and run it. It runs an 
Executable Unix file through the terminal. How can I turn that 
into an Application that doesn't open the Terminal?


Thanks.


Have you tried running your executable from the command line?  I 
suspect Xamarin is just opening a terminal for you as a 
convenience.


Question about Allocating

2015-01-25 Thread Gan via Digitalmars-d-learn
I've been working on my game and am getting some pretty gnarly 
memory problems. I think it's how I'm allocating.


Sometimes when I use variables I can do Color(255, 255, 255). But 
why is that different than new Color(255, 255, 255)?

Same when I'm making arrays. new int[](0) vs [].


What's the difference?


vibe.d error

2015-01-25 Thread Phil via Digitalmars-d-learn

dub init name vibe.d
cd name
dub

Results in

Fetching libevent 2.0.1+2.0.16...
Error executing command upgrade: Failed to download 
http://code.dlang.org/packages/libevent/2.0.1%252B2.0.16.zip: 404 
Not Found


I'm not sure if the error is the file not being there or dub 
looking there. Is there a workaround for this? Thanks


Re: using the full range of ubyte with iota

2015-01-25 Thread ketmar via Digitalmars-d-learn
On Sun, 25 Jan 2015 14:11:09 +, Dominikus Dittes Scherkl wrote:

 On Sunday, 25 January 2015 at 13:03:16 UTC, bearophile wrote:
 Dominikus Dittes Scherkl:

 Because this is useful in more situations,

 Right, but it's still a cast. And in D you want to minimize the number
 of usages of casts. The proposed syntax iota![] is cast-safe.

 I don't case too much, if I have ensured the cast is safe by constraints
 beforehand.
 
 I need to cast often anyway, because I work with small types and most
 operators permanently change everything to int, especially the
 bit-operations for which a signed type makes no sense at all:
 
 ubyte x = 50;
 auto y = x  0x11; // y is int! I hate that!
 
 even if I use unsigned literals:
 auto z = x  0x12u; // z is uint - better but still bad. More so as 
 should result in the smaller of the two types!!
 
 But I need not even use literals (which unfortunately cannot be makred
 as ubyte or short). Look at this:
 
 auto x2 = (x4) | (x4); // swap nibbles - but result in an int!

this is true for C and C++ too, as all three languages doing integer 
promotion. the only difference is that D forbids potentially lossy 
assigns.

you best bet is to not use `auto`, but specify required type explicitly. 
or use ints/uints and cast to bytes only when it is necessary.

signature.asc
Description: PGP signature


Re: Sqlite

2015-01-25 Thread Paul via Digitalmars-d-learn
I'd like to vary the query based on input but if I try to move 
the string out of the sqlite3_exec call like this:


string sqlStatement = CREATE TABLE people(id INT PRIMARY KEY NOT 
NULL, surname TEXT NOT NULL);;

result = sqlite3_exec(db, sqlStatement, aCallback, null, msg);

...it won't compile:

Error: function etc.c.sqlite3.sqlite3_exec (sqlite3*, 
const(char)* sql,...

is not callable using argument types (sqlite3*, string,...

I can assign using:

const char *sqlStatement = CREATE TABLE...

So how do I get a constant character pointer that can be modified 
at runtime?


Paul





Re: Sqlite

2015-01-25 Thread Tobias Pankrath via Digitalmars-d-learn

On Sunday, 25 January 2015 at 18:15:21 UTC, Paul wrote:
I'd like to vary the query based on input but if I try to move 
the string out of the sqlite3_exec call like this:


string sqlStatement = CREATE TABLE people(id INT PRIMARY KEY 
NOT NULL, surname TEXT NOT NULL);;

result = sqlite3_exec(db, sqlStatement, aCallback, null, msg);

...it won't compile:

Error: function etc.c.sqlite3.sqlite3_exec (sqlite3*, 
const(char)* sql,...

is not callable using argument types (sqlite3*, string,...

I can assign using:

const char *sqlStatement = CREATE TABLE...

So how do I get a constant character pointer that can be 
modified at runtime?


Paul


Only string literals convert to const(char)*, because only for 
them it is guaranteed that they are null terminated. For 
everything else use toStringz.


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread ketmar via Digitalmars-d-learn
On Sun, 25 Jan 2015 08:41:24 +, Bayan Rafeh wrote:

 I tried what you said and I think I see the problem. I managed to
 create an example program that duplicates the problem:


 import std.stdio;

 class A {
 string path;

 this(string p) {
 path = p;
 }
 ~this() {
 }
 void a(){}

 void b(){}
 }

 class B {
 A a;
 this() {
 this.a = new A(laladiv);
 }
 ~this() {
 delete a;
 }
 }

 void main() {
 B a = new B(); B b = new B(); delete b;
 }
 
 The solution was just to remove the delete a from the destructor if
 someone comes across this later. Could someone tell me why though?

there is no guarantees on destruction order. and GC will not nullify any 
references to collected data. so, `a` can be already collected and 
finalized when `B.~this()` is called. yet reference is still there, so 
`delete a;` will try to delete already dead object. this will lead to 
crash.

without precise GC collector is not able to automatically nullify all 
dead references. and even if there will be such possibility, it can 
slow down collections alot (GC will nullifying alot of references that 
aren't used anyway), so i don't think that it do nullifying.

there is a simple rule: dtor should not touch GC-managed resources. 
this will not give you predictable destruction order (that's why most 
people try to manually delete something in dtor), and this simply will 
not work at all.

if you want predictable destruction order, don't use GC at all, use 
manual memory management. it doesn't matter which hack you will invent to 
force destruction order, any hack will either be very fragile, or will 
not work. this is due to nature of GC-manged memory.

so: don't use GC-managed resources in dtors. don't use in any way -- this 
including accessing 'em. i.e. reading `a.path` in dtor is invalid too. it 
will not necessarily crash, but it's the source of use after free error.

and don't even think that you can trick GC using checks from 
`core.memory`! this will not work too. sure, you can check if memory used 
by `a` is still alive, but that memory can be used by completely 
different object!

tl;dr:
1. don't use GC-managed objects in dtors. not even try to access 'em.
2. don't try to trick GC. either don't use it, or cooperate with it.

signature.asc
Description: PGP signature


Re: Sqlite

2015-01-25 Thread Paul via Digitalmars-d-learn

On Sunday, 25 January 2015 at 18:19:47 UTC, Tobias Pankrath wrote:
Only string literals convert to const(char)*, because only for 
them it is guaranteed that they are null terminated. For 
everything else use toStringz.


So, as a trivial example, is this how it's done?:

string semiC = ;;
const char *sqlStatement = toStringz(CREATE TABLE people(id INT 
PRIMARY KEY NOT NULL, surname TEXT NOT NULL)~semiC);


Seems rather ugly but I guess it's a result of interfacing with 
C...


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread ketmar via Digitalmars-d-learn
On Mon, 26 Jan 2015 05:25:48 +, Bayan Rafeh wrote:

 There are 2 problems here:
 
 1. By definition, after the destructor is called the object state is
 destroyed. It makes no sense to check the invariant after the destructor
 is called because there is no state for us to check.
i agree that calling invariant after destruction is invalid. i believe 
that this is a bug.

 2. Invariants theoretically describe the legal states the object can be
 in which includes variables that are GC managed, therefore I should be
 able to check the invariant on GC managed objects as well. What's the
 point of having this feature if I can't even check the invariants of a
 simple data structure like a set, let alone classes involving files?
checking something that is not owned by an object is invalid. invariants 
MUST NOT be dependent on external data or system state. invariants that 
tries to check for GC objects ARE dependent of external state. let alone 
invariants that checking for files, which can be removed while the object 
is still alive.

object can own another object, but it can't own another object *state*.

if you want to check something that involves checking something like 
that, you should use `assert()`s in function body and/or in/out function 
parts.

you are trying to use invariants for the things that invariants can't 
(and must not) check. invariants are meant for checking *internal* 
*object* *consistency*. NOT correctness. NOT applicability. ONLY 
consistency. object can be in inapplicable state, but still consistent.

signature.asc
Description: PGP signature


Re: Turning Executable into Application?

2015-01-25 Thread Gan via Digitalmars-d-learn

On Monday, 26 January 2015 at 06:37:34 UTC, tcak wrote:

On Monday, 26 January 2015 at 03:36:32 UTC, Gan wrote:
With Xamarin Studio I create a D project and run it. It runs 
an Executable Unix file through the terminal. How can I turn 
that into an Application that doesn't open the Terminal?


Thanks.


I use MonoDevelop. I haven't tried that but in Project Options 
(Not Solution Options), there is a checkbox saying Run on 
External Console. Uncheck that one maybe.


As far as I understand, you want to make a GUI program by 
saying application.


That's it! Thank you!


Turning Executable into Application?

2015-01-25 Thread Gan via Digitalmars-d-learn
With Xamarin Studio I create a D project and run it. It runs an 
Executable Unix file through the terminal. How can I turn that 
into an Application that doesn't open the Terminal?


Thanks.


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Bayan Rafeh via Digitalmars-d-learn


the thing is that your invariant is not a correct invariant at 
all.
invariants are meant to check *internal* object consistency, 
not external
conditions. compiler is free to call invariant block at any 
time after
object is properly initialised (i.e. after ctor is complete) 
and is not
executing member method. so it's perfectly legal to call 
invariant before
dtor, as you should not check anything that is not belonging to 
the

object itself in in.


in other words: you can't check any contents of any 
reference-typed
variables in your invariant block. `string` is reference-typed 
(it's a
dynamic array managed by GC in your case), so you can't check 
it contents
in invariant. you CAN, however, use `f` methods in your 
invariant, as `f`
is a struct which lives *inside* your object, and not a 
reference var.


but note that it's a bad practice anyway, as some struct can 
use some GC-

managed objects which can't be safely used in invariant block.


There are 2 problems here:

1. By definition, after the destructor is called the object state
is destroyed. It makes no sense to check the invariant after the
destructor is called because there is no state for us to check.

2. Invariants theoretically describe the legal states the object
can be in which includes variables that are GC managed, therefore
I should be able to check the invariant on GC managed objects as
well. What's the point of having this feature if I can't even
check the invariants of a simple data structure like a set, let
alone classes involving files?


Re: Difference between concatenation and appendation

2015-01-25 Thread WhatMeWorry via Digitalmars-d-learn

On Monday, 26 January 2015 at 01:57:04 UTC, bearophile wrote:

Laeeth Isharc:

I think concatenation and append are used as synonyms (the 
same meaning is meant).  a~=b or a=a~b


a=a~b always allocates a new array, while a~=b sometimes 
re-allocates in place.


Bye,
bearophile


Perfect! Thank you.  I'll scribble your quote you in the margin 
of my TDPL book.







Re: Difference between concatenation and appendation

2015-01-25 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, January 26, 2015 01:17:15 WhatMeWorry via Digitalmars-d-learn wrote:
 Ok, I just made up that word. But what is the difference between
 appending and concatenating?  Page 100 of TPDL says The result
 of the concatenation is a new array... and the section on
 appending talks about possibly needing expansion and reallocation
 of memory.

 But I still don't feel like I have a grasp on the subtleties
 between them. Can someone give a short and sweet rule of thumb?

 It might be so obvious that I'll regret posting this.

~ is the concatenation operator. ~= is the append operator. ~ takes two
objects (most typically arrays, but user-defined types can define the same
operators) and returns a new one which contains the data from the first one
followed by the data from the second without affecting either object. ~=
takes two objects and adds the data from the second one to the end of the
first one (without affecting the second object). ~ is forced to allocate,
because it's creating a new object. Whether ~= allocates depends on the
data involved and the implementation, though ideally, it would avoid
allocation if it can.

In the case of arrays rather than user-defined objects, ~= is managed by the
GC. So, whether ~= allocates or not depends on whether there's room/capacity
in the block of memory that the array is a slice of after the array. If
there's enough room, then it will just increase the size of the array, and
put the new data in that memory, but if there isn't enough room (e.g.
because the memory block doesn't have enough room or because another array
refers to a pointer farther in the block of memory than the one being
appended to), then a new block of memory is allocated, the data is then
assigned to there, and the array is changed to be a slice of that memory
block. For user-defined types, it depends entirely on how ~= is implemented,
but it's probably going to either be doing something similar or be forced to
reallocate every time.

In any case, the main difference between ~ and ~= is that ~ creates a new
array or object _every_ time, and ~= mutates the first argument and will
generally only result in an allocation if it has to (particularly if you're
dealing with arrays).

I'd sugges that you read this article on D arrays:

http://dlang.org/d-array-article.html

It mixes up its terminology a bit with regards to dynamic arrays (the
language considers int[] to be a dynamic array, whereas the article refers
to the GC-allocated block of memory that the array refers to as being the
dynamic array), but it should definitely clarify a lot about D arrays for
you.

- Jonathan M Davis



Re: Turning Executable into Application?

2015-01-25 Thread tcak via Digitalmars-d-learn

On Monday, 26 January 2015 at 03:36:32 UTC, Gan wrote:
With Xamarin Studio I create a D project and run it. It runs an 
Executable Unix file through the terminal. How can I turn that 
into an Application that doesn't open the Terminal?


Thanks.


I use MonoDevelop. I haven't tried that but in Project Options 
(Not Solution Options), there is a checkbox saying Run on 
External Console. Uncheck that one maybe.


As far as I understand, you want to make a GUI program by saying 
application.


Re: Link errors with curl, libevent, OpenSSL

2015-01-25 Thread AndyC via Digitalmars-d-learn
On Sunday, 25 January 2015 at 05:48:26 UTC, Vladimir Panteleev 
wrote:
On my Ubuntu Server, I can't link any D program which uses 
libraries other than Phobos.


Example:

//
import std.net.curl;
import std.stdio;

void main()
{
writeln(get(dlang.org));
}
//

dlang@k3:~/2015-01-25$ dmd -L-lcurl test.d
/usr/local/lib/x86_64-linux-gnu/libphobos2.a(curl.o): In 
function `_D3std3net4curl4HTTP19_sharedStaticCtor34FZv':
/usr/local/src/phobos/std/net/curl.d:2503: undefined reference 
to `curl_version_info'
/usr/local/lib/x86_64-linux-gnu/libphobos2.a(curl.o): In 
function `_D3std3net4curl4Curl19_sharedStaticCtor35FZv':
/usr/local/src/phobos/std/net/curl.d:3497: undefined reference 
to `curl_global_init'
/usr/local/lib/x86_64-linux-gnu/libphobos2.a(curl.o): In 
function `_D3std3net4curl4Curl19_sharedStaticDtor36FZv':
/usr/local/src/phobos/std/net/curl.d:3503: undefined reference 
to `curl_global_cleanup'

[...]
collect2: error: ld returned 1 exit status
--- errorlevel 1


The library (.a and .so) is installed and DMD passes -lcurl to 
gcc.


This is what DMD runs:

gcc test.o -o test -m64 -lcurl 
-L/usr/local/lib/x86_64-linux-gnu -Xlinker --export-dynamic 
-l:libphobos2.a -lpthread -lm -lrt


I got the above program to build by editing /etc/dmd.conf and 
adding -L-l:libphobos2.a -L-lcurl to DFLAGS. However, this 
doesn't help when linking with other D libraries, e.g. when 
using Dub.


I believe this problem is documented here:

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

I don't see a workaround that would apply to dub, though.

Is there a fix or workaround? I think this can be fixed in Dub 
to make it pass the libraries in the correct order, but I don't 
normally use Dub so I'm not sure. I sort of need this to be 
able to work on dlang.org - some functionality is only provided 
by posix.mak, which doesn't work under Cygwin.



What weirdness has Ubuntu done that this doesn't work?  I'm 
running Slackware and just tried your example and it works fine.


Does Ubuntu have developer curl packages as well as regular curl 
packages?  Maybe libcurl-dev package?


-Andy


Re: using the full range of ubyte with iota

2015-01-25 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

On Sunday, 25 January 2015 at 12:56:14 UTC, Tobias Pankrath wrote:
On Sunday, 25 January 2015 at 12:25:35 UTC, Dominikus Dittes 
Scherkl wrote:


map!(x = fn(cast(ParameterTypeTuple!fn[0])x)

but instead with

map!(paramCast!fn)

Because this is useful in more situations, e.g. in every place 
where you know the values would fit into the parameter (and 
for a single call would use a cast).


But so far I couldn't manage to make this work :-/


http://dpaste.dzfl.pl/07b1fa3c2dad


Hey cool.
With unary function I can even remove the string and mixin magic:

template paramCast(alias fn)
{
   ReturnType!fn paramCast(T)(T x)
   {
  return fn(cast(ParameterTypeTuple!fn[0])x);
   }
}

Many Thanks!


unittest with Visual D

2015-01-25 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn
I finaly got managed to install Visual D on my Windows PC (thanks 
to the new community version of Visual Studio), but the cool 
point Compile and Run seems to have a problem with some of my 
unittests:


I get the error template instance xy is not defined if a 
specific instantiation is not used in my main program.
But shouldn't the compiler build all instantiations used within a 
unittest?!?


What am I missing?


Suggestions on what to use for testing?

2015-01-25 Thread Johannes Bornhold via Digitalmars-d-learn
Just doing my first moves around with D and I realize that I want to 
structure my tests. Wondering what you are using as a test runner / test 
framework on top of plain unittest support in D itself?


So far I am ending up with adding comments into my code to structure 
things:

https://github.com/johbo/photo-sort/blob/master/source/store.d#L85

It suggest to me that I want something like a setup/teardown mechanism 
together with a way to give names to tests.


Saw that there are already a few suggestions in the wiki:
http://wiki.dlang.org/Libraries_and_Frameworks#Unit_Testing_Framework

So that's were I will continue to explore things. Still if someone 
already tried those out, sharing conclusions would be appreciated ;-)


Re: using the full range of ubyte with iota

2015-01-25 Thread bearophile via Digitalmars-d-learn

Dominikus Dittes Scherkl:


Because this is useful in more situations,


Right, but it's still a cast. And in D you want to minimize the 
number of usages of casts. The proposed syntax iota![] is 
cast-safe.


Bye,
bearophile


Re: Extracting Structure from HTML using Adam's dom.d

2015-01-25 Thread Suliman via Digitalmars-d-learn

Adam, I understood how to select URLs, but how extract values of
attributes from such selection?

  a href=/ class=post-tag title=show questions tagged
'javascript' rel=somedata

I need extract data inside rel (somedata)


Re: Conflicts with Import error - New to D, trying to build a new project

2015-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 01/25/2015 11:30 AM, Gan wrote:

Here's a screenshot: http://cl.ly/image/2n282v0B1X2M

The error is: /Users/Matt/Projects/spacecraft/source/Game/Game.d(0,0):
Error: class Game.Game.Game conflicts with import Game.Game.Game at
source/Game/Game.d(2) (spacecraft)

I figure it's because I did imports wrong or something. I'm still very
new to D. Can anyone help?


The problem is with having three constructs with the same name: package, 
module, and class.


I would use lowercase for package, and module names, and differentiate 
between the package and the module:


.../source/foogame/game.d

module foogame.game;

class Game
{
// ...
}

Ali



Re: using the full range of ubyte with iota

2015-01-25 Thread ketmar via Digitalmars-d-learn
On Sun, 25 Jan 2015 20:42:47 +, Dominikus Dittes Scherkl wrote:

 But in a function you need the cast anyway:
 ubyte swapNibbles(ubyte x) { return (x4) | (x4); } // compiler not
 happy
sure, it can't be happy, as `x` is promoted to int in the expression, so 
the expression result is `int`. better range analysis can prove that the 
resuit can be fit in `ubyte`, of course. or you can do `0xff` -- the 
compiler is intelligent enough to see that this fits to ubyte too.

 or if you index with a long, even after explicit check:
 
 int foo(ulong x)
 {
 int[10] a;
 return (x  10) ? a[x] : 0; // cannot index with long
 }
why do you index with `ulong`s in the first place? there is ugly `size_t` 
type for this.

anyway, what you talking about is a missing integer range analysis in 
complier. i'm not sure that it worth adding, as it slows down compilation 
and hiding some potentially bad code. i can grep for `cast`s to see where 
author is playing with fire, but i can't grep for range analysis. ;-)

p.s. `a[xsize_t.max]` works fine in your sample. and to be honest, i 
prefer either this, or `cast` -- any form of explicit type transformation.

p.p.s. what is bad is that compiler happily accepts this:

  int foo (int x) {
int[10] a;
return a[x];
  }

WTF?! why, in the name of Ruler of Hell, array indexing with int doesn't 
generate any warning?! D design decision to silently allow conversion of 
`int` to `uint`/`ulong` is conceptually flawed. but this is one of the 
things that will never be fixed, so we have to live with it.

signature.asc
Description: PGP signature


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread Bayan Rafeh via Digitalmars-d-learn

On Sunday, 25 January 2015 at 19:15:54 UTC, ketmar wrote:

On Sun, 25 Jan 2015 08:41:24 +, Bayan Rafeh wrote:

I tried what you said and I think I see the problem. I 
managed to

create an example program that duplicates the problem:


import std.stdio;

class A {
string path;

this(string p) {
path = p;
}
~this() {
}
void a(){}

void b(){}
}

class B {
A a;
this() {
this.a = new A(laladiv);
}
~this() {
delete a;
}
}

void main() {
B a = new B(); B b = new B(); delete b;
}


The solution was just to remove the delete a from the 
destructor if
someone comes across this later. Could someone tell me why 
though?


there is no guarantees on destruction order. and GC will not 
nullify any
references to collected data. so, `a` can be already collected 
and
finalized when `B.~this()` is called. yet reference is still 
there, so
`delete a;` will try to delete already dead object. this will 
lead to

crash.

without precise GC collector is not able to automatically 
nullify all
dead references. and even if there will be such possibility, 
it can
slow down collections alot (GC will nullifying alot of 
references that

aren't used anyway), so i don't think that it do nullifying.

there is a simple rule: dtor should not touch GC-managed 
resources.
this will not give you predictable destruction order (that's 
why most
people try to manually delete something in dtor), and this 
simply will

not work at all.

if you want predictable destruction order, don't use GC at all, 
use
manual memory management. it doesn't matter which hack you will 
invent to
force destruction order, any hack will either be very fragile, 
or will

not work. this is due to nature of GC-manged memory.

so: don't use GC-managed resources in dtors. don't use in any 
way -- this
including accessing 'em. i.e. reading `a.path` in dtor is 
invalid too. it
will not necessarily crash, but it's the source of use after 
free error.


and don't even think that you can trick GC using checks from
`core.memory`! this will not work too. sure, you can check if 
memory used

by `a` is still alive, but that memory can be used by completely
different object!

tl;dr:
1. don't use GC-managed objects in dtors. not even try to 
access 'em.
2. don't try to trick GC. either don't use it, or cooperate 
with it.


All right, I removed all my destructors(turns out I don't really 
need them), but I'm still running into this very same error.


This is another problematic example program:
import std.stdio;

void main(){
auto a = new A(/tmp/invalid);
}

class A {
File f;
string path;

this(string path) {
this.path = path;
//f = File(path, r);
}

invariant() {
File test = File(path, r);
}
}

is invariant() called during the destruction phase?


Re: Extracting Structure from HTML using Adam's dom.d

2015-01-25 Thread Adam D. Ruppe via Digitalmars-d-learn

On Sunday, 25 January 2015 at 21:24:06 UTC, Suliman wrote:

I need extract data inside rel (somedata)


string s = element.rel;


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread ketmar via Digitalmars-d-learn
On Sun, 25 Jan 2015 22:06:26 +, Bayan Rafeh wrote:

 This is another problematic example program:
 import std.stdio;
 
 void main(){
  auto a = new A(/tmp/invalid);
 }
 
 class A {
  File f;
  string path;
 
  this(string path) {
  this.path = path;
 //f = File(path, r);
  }
 
  invariant() {
  File test = File(path, r);
  }
 }
 
 is invariant() called during the destruction phase?

the thing is that your invariant is not a correct invariant at all. 
invariants are meant to check *internal* object consistency, not external 
conditions. compiler is free to call invariant block at any time after 
object is properly initialised (i.e. after ctor is complete) and is not 
executing member method. so it's perfectly legal to call invariant before 
dtor, as you should not check anything that is not belonging to the 
object itself in in.

in other words: you can't check any contents of any reference-typed 
variables in your invariant block. `string` is reference-typed (it's a 
dynamic array managed by GC in your case), so you can't check it contents 
in invariant. you CAN, however, use `f` methods in your invariant, as `f` 
is a struct which lives *inside* your object, and not a reference var.

but note that it's a bad practice anyway, as some struct can use some GC-
managed objects which can't be safely used in invariant block.

signature.asc
Description: PGP signature


Re: Difference between concatenation and appendation

2015-01-25 Thread Laeeth Isharc via Digitalmars-d-learn

On Monday, 26 January 2015 at 01:17:17 UTC, WhatMeWorry wrote:
Ok, I just made up that word. But what is the difference 
between appending and concatenating?  Page 100 of TPDL says 
The result of the concatenation is a new array... and the 
section on appending talks about possibly needing expansion and 
reallocation of memory.


But I still don't feel like I have a grasp on the subtleties 
between them. Can someone give a short and sweet rule of 
thumb?


It might be so obvious that I'll regret posting this.

Thanks.



At the risk of the blind leading the blind (I am no expert), I 
think concatenation and append are used as synonyms (the same 
meaning is meant).  a~=b or a=a~b


If there isn't enough space then the whole array is reallocated.  
You can see this/change this property by reading capacity or 
calling reserve.


If you want to do lots of appends / concatenates then use 
appender in std.array which is faster and more efficient.


Re: Difference between concatenation and appendation

2015-01-25 Thread Laeeth Isharc via Digitalmars-d-learn

On Monday, 26 January 2015 at 01:57:04 UTC, bearophile wrote:

Laeeth Isharc:

I think concatenation and append are used as synonyms (the 
same meaning is meant).  a~=b or a=a~b


a=a~b always allocates a new array, while a~=b sometimes 
re-allocates in place.


Bye,
bearophile


Thanks. That makes sense.


Re: core.exception.InvalidMemoryOperationError@(0)

2015-01-25 Thread ketmar via Digitalmars-d-learn
On Sun, 25 Jan 2015 22:06:26 +, Bayan Rafeh wrote:

p.s. yet creating new `File` in invariant is wrong nevertheless, as it 
changes the program state. invariant checks SHOULD NEVER CHANGE THE 
PROGRAM STATE.

signature.asc
Description: PGP signature


Difference between concatenation and appendation

2015-01-25 Thread WhatMeWorry via Digitalmars-d-learn
Ok, I just made up that word. But what is the difference between 
appending and concatenating?  Page 100 of TPDL says The result 
of the concatenation is a new array... and the section on 
appending talks about possibly needing expansion and reallocation 
of memory.


But I still don't feel like I have a grasp on the subtleties 
between them. Can someone give a short and sweet rule of thumb?


It might be so obvious that I'll regret posting this.

Thanks.


Re: Difference between concatenation and appendation

2015-01-25 Thread 岩倉 澪

On Monday, 26 January 2015 at 01:17:17 UTC, WhatMeWorry wrote:
Ok, I just made up that word. But what is the difference 
between appending and concatenating?  Page 100 of TPDL says 
The result of the concatenation is a new array... and the 
section on appending talks about possibly needing expansion and 
reallocation of memory.


But I still don't feel like I have a grasp on the subtleties 
between them. Can someone give a short and sweet rule of 
thumb?


It might be so obvious that I'll regret posting this.

Thanks.


I'm no expert, so take what I say with a grain of salt. That 
said, here is my understanding:


When you append to an array with ~=, it attempts to reallocate 
the array in-place, meaning it allocates on top of the already 
used space, but grabs some more space past the end of the array. 
If there isn't enough space after the array then obviously it 
can't do that, so it allocates memory somewhere else that it can 
fit and then it copies the contents of the array to the new 
location. If you were to do myArray = myArray ~ moreStuff; I 
assume this is no different from ~=. Conceptually ~= is just 
syntactic sugar in the same way that += or -= is, you are just 
doing a concatenation and then updating the array to point to the 
new result. The fact that it can reallocate in place if there is 
enough space is just like an optimization, in my mind.


Re: Difference between concatenation and appendation

2015-01-25 Thread bearophile via Digitalmars-d-learn

Laeeth Isharc:

I think concatenation and append are used as synonyms (the same 
meaning is meant).  a~=b or a=a~b


a=a~b always allocates a new array, while a~=b sometimes 
re-allocates in place.


Bye,
bearophile


Re: Linking C library (.dll) to D on windows

2015-01-25 Thread Mike Parker via Digitalmars-d-learn

On 1/26/2015 5:45 AM, Roman wrote:

Stuff:
1. There are C code module.c and module.h
2. MinGW
3. DMD 2.066.1
4. Window 8.1

module.c:

#include module.h
int add(int a, int b) {return a + b;}

module.h:

int add(int,int);

I want to use function add from D

so i call


cc -shared module.c -o module.dll


Then D code

main.d:

import std.stdio;

extern(C)
{
 int add(int a, int b);
}

void main()
{
 writefln(From C Dll %d,add(2,3));
}


So how i should compile with dmd, to get this work?


dmd main.d -L=module.dll


prints:
OPTLINK (R) for Win32  Release 8.00.15
Copyright (C) Digital Mars 1989-2013  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
OPTLINK : Error 8: Illegal Filename
main,,nul,user32+kernel32/noi=module.dll;

   ^
--- errorlevel 1

I've tried to found smthing here
http://wiki.dlang.org/Compiling_and_linking_with_DMD_on_Windows
but dll tutorial is missing

So does DMD available to link dll files?


Problem #1: linking directly to dlls is not common in the Windows 
ecosystem. AFAIK, MinGW is the only toolchain that supports that. By 
default, DMD uses the OPTLINK linker for 32-bit apps and uses the MS 
linker for 64-bit, neither of which have the ability to link directly 
with dlls. You need an import library.


Problem #2: OPTLINK only understands the OMF format for object files, 
whereas MinGW and the MS compiler output COFF. So you have three options 
for linking with 32-bit DMD:


* Compile with the Digital Mars C/C++ compiler (DMC) and generate an 
import library along with the dll.
* Compile with another compiler and run implib (part of the free Basic 
Utilities Package from Digital Mars, downloadable from [1]) on the dll 
to generate an import library in OMF format.

* Load the DLL dynamically, then you don't need an import library.

extern( C ) alias addptr = int function(int, int);
addptr add;

auto handle = LoadLibrary( MyLib.dll );
add = cast( addptr )GetProcAddress( handle, add );

Alternatively, you could compile as 64-bit, generate an import library 
with the DLL when you compile it with MinGW, and link directly with the 
import lib (the next version of DMD will support COFF for 32-bit). 
However, I have had trouble attempting to link static MinGW libraries 
with 64-bit DMD. Some have worked, some haven't. An import library is 
not the same and I assume it would work, but I've never tried.


Then again, since 64-bit DMD requires the MS toolchain to be installed, 
another option is to forego MinGW and use the MS compiler instead.


Re: Linking C library (.dll) to D on windows

2015-01-25 Thread Mike Parker via Digitalmars-d-learn

On 1/26/2015 11:18 AM, Mike Parker wrote:


* Compile with another compiler and run implib (part of the free Basic
Utilities Package from Digital Mars, downloadable from [1]) on the dll
to generate an import library in OMF format.


[1] http://www.digitalmars.com/download/freecompiler.html



Linking C library (.dll) to D on windows

2015-01-25 Thread Roman via Digitalmars-d-learn

Stuff:
1. There are C code module.c and module.h
2. MinGW
3. DMD 2.066.1
4. Window 8.1

module.c:

#include module.h
int add(int a, int b) {return a + b;}

module.h:

int add(int,int);

I want to use function add from D

so i call


cc -shared module.c -o module.dll


Then D code

main.d:

import std.stdio;

extern(C)
{
int add(int a, int b);
}

void main()
{
writefln(From C Dll %d,add(2,3));
}


So how i should compile with dmd, to get this work?


dmd main.d -L=module.dll


prints:
OPTLINK (R) for Win32  Release 8.00.15
Copyright (C) Digital Mars 1989-2013  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
OPTLINK : Error 8: Illegal Filename
main,,nul,user32+kernel32/noi=module.dll;

  ^
--- errorlevel 1

I've tried to found smthing here 
http://wiki.dlang.org/Compiling_and_linking_with_DMD_on_Windows

but dll tutorial is missing

So does DMD available to link dll files?


Conflicts with Import error - New to D, trying to build a new project

2015-01-25 Thread Gan via Digitalmars-d-learn

Here's a screenshot: http://cl.ly/image/2n282v0B1X2M

The error is: 
/Users/Matt/Projects/spacecraft/source/Game/Game.d(0,0): Error: 
class Game.Game.Game conflicts with import Game.Game.Game at 
source/Game/Game.d(2) (spacecraft)


I figure it's because I did imports wrong or something. I'm still 
very new to D. Can anyone help?


Re: PostgreSQL driver

2015-01-25 Thread ChrisG via Digitalmars-d-learn
So, it's been about a year since you asked this. Did you ever 
determine which PostgreSQL library to use? Is there one that 
makes any more sense than the others?


Re: using the full range of ubyte with iota

2015-01-25 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

On Sunday, 25 January 2015 at 18:59:04 UTC, ketmar wrote:
auto x2 = (x4) | (x4); // swap nibbles - but result in an 
int!


this is true for C and C++ too, as all three languages doing 
integer
promotion. the only difference is that D forbids potentially 
lossy

assigns.

you best bet is to not use `auto`, but specify required type 
explicitly.

or use ints/uints and cast to bytes only when it is necessary.


in normal assignments I never use auto - it's not simpler than 
writing the type explicit but later makes it more complicated to 
see what type it is.


But in a function you need the cast anyway:
ubyte swapNibbles(ubyte x) { return (x4) | (x4); } // 
compiler not happy


or if you index with a long, even after explicit check:

int foo(ulong x)
{
   int[10] a;
   return (x  10) ? a[x] : 0; // cannot index with long
}

So there are plenty of places in D where cast is necessary but 
should not be.
I think both of above cases should be safe without cast, and 
enhancing the compilerr that it can handle these cases is more 
important than a iota![].


Until then I prefer paramCast!fn, because this is more flexible 
than the iota extension and my code is full of casts anyway.


Re: Link errors with curl, libevent, OpenSSL

2015-01-25 Thread Vladimir Panteleev via Digitalmars-d-learn

On Sunday, 25 January 2015 at 15:23:03 UTC, AndyC wrote:

On Sunday, 25 January 2015 at 15:11:33 UTC, AndyC wrote:
On Sunday, 25 January 2015 at 05:48:26 UTC, Vladimir Panteleev 
wrote:
On my Ubuntu Server, I can't link any D program which uses 
libraries other than Phobos.


Example:

//
import std.net.curl;
import std.stdio;

void main()
{
  writeln(get(dlang.org));
}
//

dlang@k3:~/2015-01-25$ dmd -L-lcurl test.d
/usr/local/lib/x86_64-linux-gnu/libphobos2.a(curl.o): In 
function `_D3std3net4curl4HTTP19_sharedStaticCtor34FZv':

/usr/local/src/phobos/std/net/curl.d:2503: undefined reference



What weirdness has Ubuntu done that this doesn't work?  I'm 
running Slackware and just tried your example and it works 
fine.


Does Ubuntu have developer curl packages as well as regular 
curl packages?  Maybe libcurl-dev package?


-Andy



Yep, Ubuntu bug:

https://bugs.launchpad.net/ubuntu/+source/curl/+bug/1001576


Thank you. It looks like this is an incompatibility between DMD 
and Ubuntu enabling --as-needed. This pointed me in the right 
direction to find a workaround:


https://issues.dlang.org/show_bug.cgi?id=12572#c5


Re: When to use typecons.proxy vs alias this?

2015-01-25 Thread Adam D. Ruppe via Digitalmars-d-learn

On Sunday, 25 January 2015 at 05:57:37 UTC, weaselcat wrote:
So the only difference is that proxy doesn't have implicit 
conversions? Hm. Might be worth pointing out on the docs.


I don't think it is the *only* difference - the implementations 
are very different - but I do think it is the most significant 
one.