Re: Multidimensional slicing
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]
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
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
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
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
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
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]
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
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
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]
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.
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
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
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
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
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?
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?
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?
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?
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?
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