Re: Multidimensional slicing

2012-10-26 Thread bearophile

Joseph Rushton Wakeling:

Suppose I have some data in an 2-dimensional associative array 
(it could be larger dimension, but let's limit it to 2d for 
now).  I'm using an associative array because the underlying 
data is sparse, i.e. for any given index pair (i, j) there's 
most likely not an entry.


In Python people that want to use a associative arrays to store a 
sparse 2D array usually use just one associative array, where the 
keys are (r,c) pairs. But you can't "slice" this.


In low level languages for sparse 2D arrays often people use 
something different. One popular choice is to use just a (dense) 
array for the first coordinate, and to put just index-value pairs 
(with ordered indexes) into such arrays. It's a simple solution, 
but it's often good enough. If the rows contain many items (more 
than 50-100) it's better to chunk each row in some way.


If you want to slice on both coordinates consider using two data 
structures, where the second contains pointers to the first, and 
if you want to add/remove items then maybe each value needs a 
pointer to the start of the array.


See also:
http://en.wikipedia.org/wiki/Sparse_matrix


It's trivial to take a slice of this data using the first 
dimension, i.e. if a[i][j] gives the value for the key pair (i, 
j), a[i] will give the array of values for all values of j, and 
a[i].keys will give me all the values of j that are "connected" 
to i.


... however, I can't do this the opposite way, i.e. to slice it 
a[][j] -- I get an error message, e.g.:


Error: ulong[ulong][ulong] cannot be sliced with []

and similarly there is no way to identify a[][j].keys i.e. all 
the i indexes associated with j.


Maybe you are able to create a wrapper, that wraps the 2D 
associative array, and uses a little "most recently used" cache 
stored in a little array to memoize some of the last lookups on 
the first coordinate. But first it's better to try simpler 
solutions.


Bye,
bearophile


Re: GDC build [was: Re: Sort order of dirEntries]

2012-10-26 Thread Joseph Rushton Wakeling

On 10/26/2012 04:51 AM, H. S. Teoh wrote:

Hmm. Try apt-get install libppl0.11-dev, maybe? That's where that file
should be. AFAIK apt-get build-dep should've pulled that one in, but
just in case it didn't, this may help.


It's installed, but the headers in /usr/include/x86_64-linux-gnu/ instead of 
just /usr/include/ -- it's a multiarch thing again.


So, I symlinked /usr/include/x86_64-linux-gnu/ppl* to /usr/include/ and that 
seems to get round it.


I also tried running make without the -j4 option, in case there was something 
about the parallel build jobs that was screwing things up.


So, now it falls over with a whole bunch of new errors, ending with the 
following:

---
libbackend.a(tree-scalar-evolution.o): In function 
`gt_ggc_mx_scev_info_str(void*)':
tree-scalar-evolution.c:(.text+0x4bd0): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'

libbackend.a(tree-scalar-evolution.o): In function 
`gt_pch_nx_scev_info_str(void*)':
tree-scalar-evolution.c:(.text+0x4c91): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'

libbackend.a(tree-scalar-evolution.o): In function 
`gt_ggc_mx_scev_info_str(void*)':
tree-scalar-evolution.c:(.text+0x4bdf): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'

libbackend.a(tree-scalar-evolution.o): In function 
`gt_pch_nx_scev_info_str(void*)':
tree-scalar-evolution.c:(.text+0x4ca0): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'

libbackend.a(tree.o): In function `gt_pch_nx_type_hash(void*)':
tree.c:(.text+0x785): undefined reference to `gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o): In function `gt_ggc_mx_type_hash(void*)':
tree.c:(.text+0x844): undefined reference to `gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1ab8): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1ac0): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1ae8): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1af0): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1b78): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1b80): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1ba0): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1ba8): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1bc8): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1bd0): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1bf0): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1bf8): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1c18): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(tree.o):(.rodata+0x1c20): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x55b8): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x55c0): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x55e0): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x55e8): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5608): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5610): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x56f8): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5700): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5720): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5728): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5748): undefined reference to 
`gt_ggc_mx_lang_tree_node(void*)'
libbackend.a(i386.o):(.rodata+0x5750): undefined reference to 
`gt_pch_nx_lang_tree_node(void*)'

collect2: error: ld returned 1 exit status
make[3]: *** [cc1d] Error 1
---

What's really annoying is that AFAICS all of these last errors occur at the 
point where the gdc executable is being linked ... :-\




How to "extend" built-in types

2012-10-26 Thread simendsjo

Not sure if this is a bug or intended behavior:

import std.traits;
struct S {
 int i;
 T opCast(T)() if(isFloatingPoint!T) {
 return cast(T)i;
 }
}

template myIsFloatingPoint(T) {
 enum myIsFloatingPoint =  isFloatingPoint!T
 || __traits(compiles, { cast(real)T.init; });
}

void main() {
 auto s = S(10);
 assert(cast(real)s == 10.0);
 // static assert( isFloatingPoint!S); // false
 static assert( myIsFloatingPoint!S);
 static assert( myIsFloatingPoint!float);
 static assert(!myIsFloatingPoint!int);
}


Think of a Fraction or RangedInt struct for instance:

import std.traits;

struct Ranged(T, T minValue, T maxValue)
 if(isNumeric!T)
{
 enum T max = maxValue;
 enum T min = minValue;
 T value = min;

 invariant() {
 assert(value >= min && value <= max);
 }

 T opCast()() {
 return value;
 }

 void opAssign(T value) {
 this.value = value;
 }

 bool opEquals(T value) {
 return this.value == value;
 }
}

void f(int v) {}

void g(T)(T v) if(isNumeric!T) {
}

void main() {
 Ranged!(int, 10, 20) v;
 assert(v == 10);
 v = 20;
 //v = 21; // assert as expected
 // f(v); // ok if we would use an alias this, but then the
Ranged isn't in effect anymore
 //g(v); // oops.. Ranged is not numeric

}

So.. What do I need to implement for a struct to be a valid
built-in type?
All valid properties (min, max etc) and operators for that type?


Re: Sort order of dirEntries

2012-10-26 Thread Regan Heath
On Thu, 25 Oct 2012 01:15:06 +0100, Joseph Rushton Wakeling  
 wrote:



Hello all,

I've just been playing with dirEntries and by the looks of it, it  
returns these entries in arbitrary order.


On windows, assuming it was using FindFirstFile or similar you would get  
alphabetical order on some platforms/file systems and FAT table order on  
others.  I imagine linux and associated platforms have similar behaviour.


Is there a way to get it to sort the entries in alphabetical order,  
other than the obvious one of storing them in an array and sorting  
that?  (This is untenable because I'm talking about a lot of files...:-)


To get a sorted list someone has to load all the entries and sort them.  I  
doubt the file system is going to do it, so either the library routine  
would have to, or you're going to have to.  As most file systems and  
libraries should take the most efficient approach first and foremost it's  
likely you're going to have to do it yourself.


:)

R

--
Using Opera's revolutionary email client: http://www.opera.com/mail/


Re: Proxy addition

2012-10-26 Thread Dan

On Thursday, 25 October 2012 at 16:39:57 UTC, Dan wrote:
From bug tracker I see that Proxy has a few issues, so this has 
likely been seen. But what would cause this error?


tmp/c.d(16): Error: overloads pure nothrow @safe double(auto 
ref CcRate b) and pure nothrow @safe double(auto ref CcRate b) 
both match argument list for opBinary


The error refers to two methods with the same signature. In 
typecons there are only two "Binary" methods, opBinary and 
opBinaryRight, both in Proxy, so where is the 
duplication/conflict coming from?


Thanks
Dan
---
import std.stdio;
import std.typecons;
import std.algorithm;

struct CcRate {
  private double rate = 0;
  mixin Proxy!rate;

  this(double rate) {
this.rate = rate;
  }
}

unittest {
CcRate r1 = 0.033, r2 = 0.002;
writeln(r1+r2);  // compile error
}
---


Still trying to understand this. I found that if I change the 
following in Proxy it this example (r1 + r2) works fine. Plus the 
unit tests that are there still work. But, honestly I don't 
understand why...yet.


Thanks,
Dan

- From typecons.Proxy -
auto ref opBinary (string op, this X, B)(auto ref B b) { 
return mixin("a "~op~" b"); }

- To -
auto ref opBinary (string op, this X, B)(auto ref B b) 
if(!is(X == B)) { return mixin("a "~op~" b"); }

-


Re: How to "extend" built-in types

2012-10-26 Thread Dan

On Friday, 26 October 2012 at 13:55:35 UTC, simendsjo wrote:

Not sure if this is a bug or intended behavior:
...
So.. What do I need to implement for a struct to be a valid
built-in type?
All valid properties (min, max etc) and operators for that type?


I am looking for something similar. I ended up looking at Proxy 
in typecons because the description says "// Enable operations 
that original type has". So for instance it looks like you could 
wrap an int or double in a struct and it is almost exactly like 
an int or a double. Presumably you could then overload just the 
changes (min/max for range, etc). I've found issues for my case, 
but at least its worth a look.


http://forum.dlang.org/post/ycayokcwncqfwfsto...@forum.dlang.org

If I try to check that this struct is numeric, unfortunately it 
is not.

writeln("Is numeric ", isNumeric!CcRate); // false
writeln("Is numeric ", isNumeric!double); // true


-
struct CcRate {
  private double rate = 0;
  mixin Proxy!rate;

  this(double rate) {
this.rate = rate;
  }
}


Thanks
Dan



Re: How to "extend" built-in types

2012-10-26 Thread Jonathan M Davis
On Friday, October 26, 2012 15:55:34 simendsjo wrote:
> So.. What do I need to implement for a struct to be a valid
> built-in type?
> All valid properties (min, max etc) and operators for that type?

So, you want stuff like isFloatingPoint and isNumeric to return true for a 
user-defined struct? That pretty much defeats their purpose if that happens. 
They're checking for exact matches, not implicit conversions, and a function 
intended to work explicitly with float isn't necessarily going to work with 
your struct, so it needs isFloatingPoint to be false for something that isn't 
truly a built-in floating point type.

- Jonathan M Davis


Re: GDC build [was: Re: Sort order of dirEntries]

2012-10-26 Thread H. S. Teoh
On Fri, Oct 26, 2012 at 02:36:18PM +0200, Joseph Rushton Wakeling wrote:
> On 10/26/2012 04:51 AM, H. S. Teoh wrote:
> >Hmm. Try apt-get install libppl0.11-dev, maybe? That's where that
> >file should be. AFAIK apt-get build-dep should've pulled that one in,
> >but just in case it didn't, this may help.
> 
> It's installed, but the headers in /usr/include/x86_64-linux-gnu/
> instead of just /usr/include/ -- it's a multiarch thing again.

Hmm. Are the Ubuntu patches incomplete then? I would've thought the
patches in debian/patches should have taken care of this.


> So, I symlinked /usr/include/x86_64-linux-gnu/ppl* to /usr/include/
> and that seems to get round it.
> 
> I also tried running make without the -j4 option, in case there was
> something about the parallel build jobs that was screwing things up.

I always built with -j6 (don't have the patience to wait that long) and
that never seemed to have made a difference in whether the build
succeeded.


> So, now it falls over with a whole bunch of new errors, ending with the 
> following:
> 
> ---
> libbackend.a(tree-scalar-evolution.o): In function 
> `gt_ggc_mx_scev_info_str(void*)':
> tree-scalar-evolution.c:(.text+0x4bd0): undefined reference to
> `gt_ggc_mx_lang_tree_node(void*)'
[...]

Hmm. Googling for the missing symbol seems to relate it to LTO, so maybe
try --disable-lto to see if that gets it through?

Also, if you aren't already, make sure you start with a clean, empty
objdir everytime you rebuild (I usually run \rm -rf *; configure ...;
make -j6), because the miserable system doesn't know how to continue
building from where it left off, and sometimes detritus leftover from
previous attempts can interfere with the build. You probably already
know this, but, just to make sure all bases are covered.


T

-- 
When solving a problem, take care that you do not become part of the problem.


scope(failure): get exception

2012-10-26 Thread Justin Whear
Is there a way to get the current exception inside a scope(failure)?  I 
have a try..catch around my main loop which simply logs the caught 
exception and rethrows it.  I'd like to replace this with a simple scope
(failure) but I haven't found any way to access the exception causing the 
unwinding.


Re: TypeInfo manipulation

2012-10-26 Thread Zhenya

On Thursday, 25 October 2012 at 15:05:05 UTC, Zhenya wrote:

Hi!
Tell me please,are any TypeInfo/typeid/classinfo manipulations 
possible?
For example I need a struct that overload typeid, or something 
like that?


Some time ago I tried to write some smart pointer that overlad 
classinfo property  in accordance with the real type of hold 
object,but I failed to do this becouse of
not having possibility to declar static and non-static version 
of the one function.Maybe there are better ways to do this?


Or maybe there are a possibility to parametrize class by TypeInfo?


Re: GDC build [was: Re: Sort order of dirEntries]

2012-10-26 Thread Joseph Rushton Wakeling

On 10/26/2012 06:57 PM, H. S. Teoh wrote:

Hmm. Are the Ubuntu patches incomplete then? I would've thought the
patches in debian/patches should have taken care of this.


I've posted a follow-up to the d.gnu list, since that's really where this 
discussion belongs, but just to say you were probably right to suspect something 
was wrong with my application of the patches.  I decided to download a fresh 
copy of the apt-get source and reapply the patches; now, with the symlinks 
removed, the build proceeds without the errors related to crti.o or header files.


It still falls over in what looks like the same place as last described, though, 
even if I try the --disable-lto option. :-(



Also, if you aren't already, make sure you start with a clean, empty
objdir everytime you rebuild (I usually run \rm -rf *; configure ...;
make -j6), because the miserable system doesn't know how to continue
building from where it left off, and sometimes detritus leftover from
previous attempts can interfere with the build. You probably already
know this, but, just to make sure all bases are covered.


Yea, it's what I was doing, removing and making a fresh build.  Re the -j 
option, I still find that the build falls over in different ways depending on 
whether I use that option or not (cf. my post in d.gnu).




Compiling shared example.

2012-10-26 Thread Peter Sommerfeld

To learn about shared attribute I've copied nearly verbatim an
example from Andreis book. The code:

import core.atomic;

struct Data{
  int value;
}

shared struct SharedStack(T) {

  private shared struct Node{
T data;
Node* next;
this(T value){data = value;};
  }
  private Node* root;

  // push

  void push(T value){
auto n = new Node(value);
shared(Node)* oldRoot;
do {
  oldRoot = root;
  n.next = oldRoot;
} while(!cas(&root,oldRoot,n)); // line 30
  }
  // ...
}

SharedStack!(Data) q;

void main(string[] args){

  Data m;
  q.push(m); // line 40
}

I got the following error (dmd 2.060 win):

(40) Error function main.SharedStack!(Data).SharedStack.push(Data value)
shared is not callable using argument types (Data)

(30) template core.atomic.cas does not match any function template  
declaration


What is wrong here ?

Peter


Re: scope(failure): get exception

2012-10-26 Thread Jonathan M Davis
On Friday, October 26, 2012 19:53:04 Justin Whear wrote:
> Is there a way to get the current exception inside a scope(failure)? I
> have a try..catch around my main loop which simply logs the caught
> exception and rethrows it. I'd like to replace this with a simple scope
> (failure) but I haven't found any way to access the exception causing the
> unwinding.

If you want to see the exception, you must catch it. scope statements do not 
provide access to exceptions. So, scope works great as long as you don't need 
access to the exception, but if you do, you need to use try-catch blocks.

- Jonathan M Davis


Re: scope(failure): get exception

2012-10-26 Thread Justin Whear
On Fri, 26 Oct 2012 17:33:48 -0400, Jonathan M Davis wrote:

> On Friday, October 26, 2012 19:53:04 Justin Whear wrote:
>> Is there a way to get the current exception inside a scope(failure)? I
>> have a try..catch around my main loop which simply logs the caught
>> exception and rethrows it. I'd like to replace this with a simple scope
>> (failure) but I haven't found any way to access the exception causing
>> the unwinding.
> 
> If you want to see the exception, you must catch it. scope statements do
> not provide access to exceptions. So, scope works great as long as you
> don't need access to the exception, but if you do, you need to use
> try-catch blocks.
> 
> - Jonathan M Davis

My understanding is that scope(failure) simply lowers to the catch block 
of a try..catch, so there's no implementation obstacle to making the 
exception available.  Are there known syntax or correctness obstacles to 
allowing something like this:

scope(failure)(Exception ex) writeln(ex.msg);


Re: scope(failure): get exception

2012-10-26 Thread Jonathan M Davis
On Friday, October 26, 2012 21:37:00 Justin Whear wrote:
> My understanding is that scope(failure) simply lowers to the catch block
> of a try..catch, so there's no implementation obstacle to making the
> exception available. Are there known syntax or correctness obstacles to
> allowing something like this:
> 
> scope(failure)(Exception ex) writeln(ex.msg);

Yes. It lowers to a try-catch block, but that's effectively an implementation 
detail. As it stands, technically speaking, a compiler could probably 
implement it without any lowering whatsoever (I don't think that the spec says 
anything about how it's implemented). But even if the compiler has to use 
lowering, the main problem with your suggestion is that in complicates how 
scope statements work, since then it's only going to be run if the exception 
type being caught matches what was being thrown, whereas right now 
scope(failure) statements run on all exceptions regardless. And scope 
statements aren't really meant for exception handling. Rather, they're 
intended for providing a clean means of making code exception-safe. So, I 
suspect that what you suggest would be rejected, but I don't know. You can 
certainly create an enhancement request for it if you want to:

http://d.puremagic.com/issues

- Jonathan M Davis


Re: Proxy addition

2012-10-26 Thread cal

On Friday, 26 October 2012 at 15:14:56 UTC, Dan wrote:
Still trying to understand this. I found that if I change the 
following in Proxy it this example (r1 + r2) works fine. Plus 
the unit tests that are there still work. But, honestly I don't 
understand why...yet.


Thanks,
Dan

- From typecons.Proxy -
auto ref opBinary (string op, this X, B)(auto ref B b) 
{ return mixin("a "~op~" b"); }

- To -
auto ref opBinary (string op, this X, B)(auto ref B b) 
if(!is(X == B)) { return mixin("a "~op~" b"); }

-


From http://dlang.org/operatoroverloading.html, it is an error 
for both overloads of opBinary (opBinary and opBinaryRight) to 
match. Since the signatures for the two overloads in std.typecons 
are identical, this looks like a bug to me.


Your modified version works (far as I can see) because it 
excludes one of the overloads from being matched, allowing the 
other to be used (opBinaryRight).


Re: Why is "delete" unsafe?

2012-10-26 Thread Adam D. Ruppe

On Friday, 26 October 2012 at 23:03:15 UTC, Minas wrote:

What is unsafe about it?


If you delete something but keep a reference to it, at some point 
down the line, the memory could be reused.


Then your old reference points to a different type of object and 
could treat it differently.



Just for example:

string code = something;

delete code;

// but oops code is still there and pointing at some memory...

int[] something = new int(10); // this might reuse the memory


eval(code); // now this evals a bunch of ints as if they were 
code which certainly isn't what you expected




Re: Why is "delete" unsafe?

2012-10-26 Thread Alex Rønne Petersen

On 27-10-2012 01:03, Minas wrote:

So the delete keyword has been deprecated - so good bye manual memory
management...


Um, no. Use destroy() from the object module instead. To free memory 
from the GC, use core.memory.GC.free().




I have read in some threads that delete is an unsafe operation. What
does this exactly mean? What is unsafe about it? What does it have to do
with the GC? (if there was no garbage collection, would it be unsafe?)


void* p = malloc(__traits(classInstanceSize, Object));
p[0 .. __traits(classInstanceSize, Object)] = typeid(Object).init[];
Object o = cast(Object)p;
delete o; // Spot the bug.

--
Alex Rønne Petersen
a...@lycus.org
http://lycus.org


Re: Why is "delete" unsafe?

2012-10-26 Thread H. S. Teoh
On Sat, Oct 27, 2012 at 01:03:14AM +0200, Minas wrote:
> So the delete keyword has been deprecated - so good bye manual
> memory management...

Um, that's a misconception. If you want manual memory management, use
malloc(), free(), and emplace.


> I have read in some threads that delete is an unsafe operation. What
> does this exactly mean? What is unsafe about it? What does it have
> to do with the GC? (if there was no garbage collection, would it be
> unsafe?)

The problem is that you can call delete on GC'd objects, which in some
cases causes bad interaction with the GC. That's why it has been
deprecated.

The intention was never to get rid of manual memory management. It was
to prevent unsafe interactions with the GC. If you don't want to use the
GC, use malloc(), free(), and emplace. (In fact, this way you can have
*both* GC and manual memory management. The emplace()'d objects will be
manually managed, and the others will be collected by the GC.)


T

-- 
All men are mortal. Socrates is mortal. Therefore all men are Socrates.


Re: Why is "delete" unsafe?

2012-10-26 Thread Jonathan M Davis
On Friday, October 26, 2012 16:12:15 H. S. Teoh wrote:
> The problem is that you can call delete on GC'd objects, which in some
> cases causes bad interaction with the GC. That's why it has been
> deprecated.
> 
> The intention was never to get rid of manual memory management. It was
> to prevent unsafe interactions with the GC. If you don't want to use the
> GC, use malloc(), free(), and emplace. (In fact, this way you can have
> *both* GC and manual memory management. The emplace()'d objects will be
> manually managed, and the others will be collected by the GC.)

Exactly. In general, you should do manual memory management with memory that 
is manually allocated and _not_ with memory which is GC-allocated (which is 
where delete goes wrong).

- Jonathan M Davis


Re: Why is "delete" unsafe?

2012-10-26 Thread Jonathan M Davis
On Saturday, October 27, 2012 01:09:39 Alex Rønne Petersen wrote:
> On 27-10-2012 01:03, Minas wrote:
> > So the delete keyword has been deprecated - so good bye manual memory
> > management...
> 
> Um, no. Use destroy() from the object module instead.

Definitely, though it's important to note that what it's doing is inherently 
different. It destroys what you pass to it but does _not_ free the memory, 
which is why it's safer.

> To free memory
> from the GC, use core.memory.GC.free().

Yes. But using core.memory.GC.free is unsafe for the same reasons that delete 
is. It's just that it's a druntime function instead of a part of the language, 
so it's less likely for someone to free GC memory without knowing what they're 
doing. It's there because there _are_ times when it makes sense and is useful, 
but it's definitely not safe, so you have to be careful and know what you're 
doing.

- Jonathan M Davis