Re: (u)byte calling char overload instead of int
On Saturday, 1 September 2018 at 17:17:37 UTC, puffi wrote: Hi, Is it by design that when calling functions with either ubyte or byte variables the char overload is called instead of the int (or generic) one? It seems this is by design. "If two or more functions have the same match level, then partial ordering is used to try to find the best match. Partial ordering finds the most specialized function." char is more specialized than int, and since the implicit conversion byte->char exists, it is called. Even f(1UL) will call f(char) rather than f(long).
Re: Is this a good idea?
On Saturday, 1 September 2018 at 16:20:11 UTC, Dr.No wrote: why move flush to outside the synchronized block? flush should be thread safe. In general, yiu want as little code as possible to run under the lock. Not that important though. trying out this approach I found to be ok except in some cases, the output look like that: ... also there's that extra ♪◙ character. Thos sounds memory violation somewhere. This only happens when using parallel. Any guess what's possibily happeing? Hard to say without seeing code. Agree it looks like a race.
Re: Is this a good idea?
On Thursday, 30 August 2018 at 19:59:17 UTC, Dr.No wrote: I would to process the current block in parallel but priting need to be theread-safe so I'm using foreach(x; parallel(arr)) { auto a = f(x); auto res = g(a); synchronized { stdout.writeln(res); stdout.flush(); } } Since f() and g() are some heavy functions, I'd like to process in parallel but the printing (doesn't need to respect order but must be thread-safe) hence I'm using synchronized. Is this counter-productive in any way? I don't see any problem with that assuming f and g are significantly more expensive than writeln. The flush can be moved outside the synchronized block.
Re: Parallelizing factorial computation
On Friday, 24 August 2018 at 13:04:47 UTC, Uknown wrote: I was quite surprised by the fact that parallel ran so much slower than recursive and loop implementations. Does anyone know why? n = 100 is too small to see parallelism gains. Try n = 1 https://run.dlang.io/is/XDZTSd
Patterns to avoid GC with capturing closures?
Consider this code, which is used as an example only: auto scaleAll(int[] xs, int m) { return xs.map!(x => m * x); } As m is captured, the delegate for map will rightly allocate the closure in the GC heap. In C++, you would write the lambda to capture m by value, but this is not a facility in D. I can write scaleAll like this: auto scaleAll(int[] xs, int m) @nogc { return repeat(m).zip(xs).map!(mx => mx[0] * mx[1]); } So that repeat(m) stores m, but it is quite hacky to work like this. I could write my own range that does this, but this is also not desirable. Are there any established patterns, libraries, or language features that can help avoid the GC allocation in a principled way here?
Re: Fun with floating point
On Saturday, 7 February 2015 at 21:33:51 UTC, Kenny wrote: The above code snippet works correctly when I use LDC compiler (it finds expected 'f' value and prints it to console). I'm wondering is it a bug in DMD? p.s. the final code used by both compilers: import std.stdio; import std.conv; int main(string[] argv) { const float eps = 1.0f; float f = 0.0f; while (f + eps != f) f += 1.0f; writeln("eps = ", eps, ", max_f = ", f); return 0; } Intermediate calculations may be performed at higher precision than the precision of the values themselves. In particular, the f + eps may be performed with 80 bits of precision, even though both values are 32-bit. The comparison will then fail. The reason for the difference between DMD and LDC is that DMD tends to use the FPU more with 80 bits of precision, whereas LDC and GDC will use the SSE2 instructions, which only support 32-bit and 64-bit precision.
Re: Fun with floating point
On Saturday, 7 February 2015 at 23:06:15 UTC, anonymous wrote: On Saturday, 7 February 2015 at 22:46:56 UTC, Ali Çehreli wrote: 1.0 is famously not representable exactly. 1.0 is representable exactly, though. I think he meant 0.1 :-)
Re: Shared and GC
On Thursday, 15 January 2015 at 17:05:32 UTC, Ola Fosheim Grøstad wrote: On Thursday, 15 January 2015 at 15:31:17 UTC, Peter Alexander wrote: On Thursday, 15 January 2015 at 15:24:55 UTC, Ola Fosheim Grøstad wrote: That would be nice, because then a precise garbage collector could choose between local collection scans and global collection scans. I think something like this is part of the plan, but shared semantics are still up in the air. That sounds like a very important aspect of a plan to get fast GC without completely changing the language and non-gc performance. I've looked at bit at how to do a fast stop-the-thread GC. Estimates on what the hardware supports (bandwidth and cache performance) suggests that it is possible to get acceptable rates for not-densely-linked heaps with some tweaks to semantics: - shared-awareness in new-expressions to support local collection - removing class-destructors - locating traceable pointers to the same cachelines in class instances (negative offsets is the easy solution) Then you cn use a ache-optimized collector using batched non-caching queues with prefetching to get bitmaps that fits in 1st level cache without wrecking the cache for other threads and having collection dominated by cache misses. Yah, this was all discussed at length not that long ago, although I can't find the thread just now.
Re: Shared and GC
On Thursday, 15 January 2015 at 15:24:55 UTC, Ola Fosheim Grøstad wrote: I am trying to understand the idea behind "shared" typing fully. If I am only allowed to share objects with another thread if it is typed "shared", doesn't that imply that it should be allocated as shared too and only be allowed to contain pointers to "shared"? Yes, shared is transitive. struct S { int* p; } void main() { S s1; shared S s2 = s1; // error, but ok if p is int. } That would be nice, because then a precise garbage collector could choose between local collection scans and global collection scans. I think something like this is part of the plan, but shared semantics are still up in the air.
Re: Copy only frame pointer between objects of nested struct
On Tuesday, 6 January 2015 at 23:32:25 UTC, Artur Skawina via That shows a static struct, so I'm not sure it's the same problem. static structs with template alias parameters to local symbols count as nested structs. Your solution would likely work, but yes, I'm looking for something less hacky :-)
Copy only frame pointer between objects of nested struct
Consider: auto foo(T)(T a) { T b; // Error: cannot access frame pointer of main.X b.data[] = 1; return b; } void main() { struct X { this(int) {} int[4096] data; } foo(X()); } Note the error is because you cannot construct the main.X object without a frame pointer. You could do `T b = a` here to get a's frame pointer, but it would also copy all of a's data, which is expensive and unnecessary. Is there a way to only copy a's frame pointer into b? (Note: this is just an illustrative example, real problem here: https://issues.dlang.org/show_bug.cgi?id=13935)
Re: What exactly shared means?
On Friday, 2 January 2015 at 23:51:05 UTC, John Colvin wrote: The rule (in C(++) at least) is that all data is assumed to be visible and mutable from multiple other threads unless proved otherwise. However, given that you do not write a race, the compiler will provide full sequential consistency. If you do write a race though, all bets are off. The memory is visible and mutable, but that's pretty much the only guarantee you get. Without synchronization, there's no guarantee a write made by thread A will ever be seen by thread B, and vice versa. Analogously in D, if a thread modifies a __gshared variable, there's no guarantees another thread will ever see that modification. The variable isn't thread local, but it's almost as if the compiler to treat it that way. These relaxed guarantees allow the compiler to keep variables in registers, and re-order memory writes. These optimizations are crucial to performance.
Re: Initialization of nested struct fields
On Friday, 2 January 2015 at 00:08:02 UTC, anonymous wrote: Apparently dmd thinks that the result of f must be a nested struct. I.e. it needs a context pointer. And I guess hell would break loose if you'd use a nested struct with a null context pointer. At least when the context pointer is actually used, unlike here. Ah, I see. So the problem is that the nested struct doesn't really have a sensible default value, meaning you must initialize it explicitly in the constructor. Thanks for the clarification.
Initialization of nested struct fields
Can someone please explain this behaviour? I find it totally bizarre. auto f(T)(T x) { struct S { T y; this(int) { } } return S(0); } void main() { f(f(0)); } Error: constructor f376.f!(S).f.S.this field y must be initialized in constructor, because it is nested struct Why must y be initialized in the constructor? It isn't const. Why isn't it default initialized? Is this explained anywhere in the docs? I can't see anything in the nested struct section, or in any constructor section.
Re: Can the order in associative array change when keys are not midified?
On Thursday, 1 January 2015 at 13:13:10 UTC, Andrej Mitrovic via Digitalmars-d-learn wrote: On 1/1/15, Idan Arye via Digitalmars-d-learn wrote: If I have an associative array and I only modify it's values, without changing the keys, can I assume that the order won't change? Associative arrays are not ordered at all. See the first note here: http://dlang.org/hash-map.html The order is unspecified, but an iteration must iterate in *some* order. The question (if I've understood it correctly), is whether that order of iteration changes when the keys aren't changed. The spec doesn't say anything about this, although I would expect in practice that the order will not change. I've added a bug to track this omission from the spec: https://issues.dlang.org/show_bug.cgi?id=13923
Re: readln with buffer fails
You need to take a slice of the buffer: char[] buf = Input[]; readln(buf); // line now in buf The reason for this is because you need to know where the string ends. If you just passed in Input, how would you know how long the line read was?
Re: Reflections on isPalindrome
On Friday, 24 October 2014 at 21:56:20 UTC, Nordlöw wrote: bool isPalindrome(R)(in R range) @safe pure Aside: for templates, just let the compiler infer @safe and pure. You don't know whether the range operations on R are pure or not. As for the actual algorithm, there's no need for the random access version, and you bidirectional version does twice as much as necessary: Just do: while (!range.empty) { if (range.front != range.back) return false; range.popFront(); if (range.empty) break; range.popBack(); } return true; This automatically handles narrow strings. Further, I would like to extend isPalindrome() with a minimum length argument minLength that for string and wstring does import std.uni: byDchar; range.byDchar.array.length >= minLength. AFAIK this will however prevent my algorithm from being single-pass right? I'm not sure what you are saying here, but hopefully the above code obviates this anyway.
Re: Are there desktop appications being developed in D currently?
On Saturday, 9 August 2014 at 00:34:43 UTC, Puming wrote: Yes, rust is a more infantile language compared to D, but people are already using them to create complicate applications like browser! Rust was designed to build Servo. The people building Servo are the people building Rust. With all due respect to Rust, I don't think that counts as endorsement of the language.
Re: spawnProcess command-line arguments help
On Sunday, 3 August 2014 at 23:48:09 UTC, Martin wrote: When I use the spawnProcess function in std.process, the command line arguments that I provide to the function seem to get "quoted". I can't reproduce this on OS X with 2.066rc1 (args are unquoted). Can someone else check Windows? Sounds like a bug to me.
Re: How to test templates for equality?
template Foo(T...) {} template Bar(T...) {} template isFoo(alias F) { enum isFoo = __traits(isSame, F, Foo); } pragma(msg, isFoo!Foo); // true pragma(msg, isFoo!Bar); // false
Re: Compiler support for T(n) notation for initialization of variables
Well, it doesn't work in 2.065, so must be 2.066 :-) P.S. thanks for letting me know about this feature. I had no idea it was going in!
Re: Why function template 'among' is of complexity O(1) and not O(n)?
On Wednesday, 19 February 2014 at 09:46:04 UTC, Gopan wrote: On Wednesday, 19 February 2014 at 09:09:25 UTC, Tobias Pankrath It's O(k) with k = vals.length, which is the number of arguments given to the function, which is a compile time constant and not dependent on any input of the final program. In O(n) the n always relates to the input somehow. I agree that vals.length is known at compile time. But while running the application, it iterates through every val in the input list until a match is found. So, how can that be considered O(1)? ... Or, is my undertanding about Big-O notation of complexity wrong? Your understanding is probably fine. It's just one of those technicalities which is a bit misleading. The algorithm is O(vals.length), there's no arguing about that, but since vals.length is a constant, it's also O(1) because O(1) = O(2) = O(1,000,000) = O(k) for any constant k. If you want to get even more anal about it, searching an array is technically O(1) because an array cannot be bigger than size_t.max, and since size_t.max is a constant, O(size_t.max) is O(1). Again, completely misleading but technically correct in an esoteric, academic way.
Re: std.algorithm.splitter improovement?
On Saturday, 14 December 2013 at 16:00:06 UTC, seany wrote: the std.algorithm.splitter returns a blank or null (eg a null string "") between two consecuting delimeters. for example, splitting "hello world" (two spaces between words) will return ["hello" , "", "world"] is there an improoved version of it, which wont return such a blank/null when multiple delimeters are found consecutively? (i tried to search the tango for d2, but i was not successful, should there be one like this already, it must have escaped my sight) Just filter out the empty ranges: r.splitter().filter!(x => !x.empty)
Re: join of range of ranges?
On Sunday, 22 September 2013 at 18:13:39 UTC, Peter Alexander wrote: On Sunday, 22 September 2013 at 14:26:14 UTC, bearophile wrote: auto r2 = [1, 2] .map!(x => [1, 2].map!(y => '*')) .join("_"); The problem is that you are trying to map a range of range of chars with a range of dchars. This could also be solved by having join return an array of the CommonType of the elements of both ranges.
Re: join of range of ranges?
On Sunday, 22 September 2013 at 14:26:14 UTC, bearophile wrote: auto r2 = [1, 2] .map!(x => [1, 2].map!(y => '*')) .join("_"); The problem is that you are trying to map a range of range of chars with a range of dchars. auto r2 = [1, 2] .map!(x => [1, 2].map!(y => cast(dchar)'*')) .join("_"); This works. I really wish character literals in D where always dchar.
Re: Switch and break
On 19/01/12 9:55 PM, RenatoL wrote: Just curious: why in D we are not obligated to use break in every branch of a swicth structure? That is: switch (i) { case 1: writeln("You wrote 1"); case 2: writeln("You wrote 2"); case 3: writeln("You wrote 3"); default: writeln("I said: 1 or 2 or 3!"); } is good in D, while, for example, similar code in C# is incorrect and if you want to play with fall through you have to make some trick. Again this behaviour of D seems a bit buggy, to me. Are there design reasons? Consistency with C and C++ mainly. Some people find it convenient, but it is unarguably a frequent source of bugs that we could do without.
Re: Get name of enum val at compile-time?
On 15/01/12 10:29 PM, Philippe Sigaud wrote: On Sun, Jan 15, 2012 at 22:19, Timon Gehr wrote: Nick: Goddamnnit, what the fuck is wrong with me? Yes that works :) I suspect a better error message would have prevented this. DMD still has some potential of improvement in that area. =) In that case, to!(Origin, Target) could be extended to deal with to!(Origin,). It's been a long time since I last looked at std.conv.to, but maybe: template to(T) { T to(A...)(A args) { static if (A.length) return toImpl!T(args); else static assert(false, "Trying to use to!("~T.stringof~") with no argument. What were you trying to do?"); } } The compiler should be able to give you a better error message. It shouldn't be the responsibility of the programmer to provide sensible error messages when you call a function with the wrong number of arguments.
Re: Fixed matrix rows joining
On 15/01/12 2:19 AM, Andrej Mitrovic wrote: I guess join() could be specialized for static arrays and then just do a dup and a cast? Would that work ok? There should be no need to allocate extra memory to do this.
Re: A tutorial on D templates
On 13/01/12 10:48 PM, DNewbie wrote: I can't understand it. Why would someone need template programming. What problem does template solve? Suppose you want to write a function to get the minimum of two integers. It's easy: int min(int a, int b) { return a < b ? a : b; } Suppose then you want to use it with floats. You now need to write another function. float min(float a, float b) { return a < b ? a : b; } Suppose you then want to use it with doubles, reals, complex numbers, strings etc. etc. You would quickly get tired of writing these functions, and more importantly you would likely make mistakes at some point. Templates allow you to solve this problem by writing the function once with placeholders for types: T min(T)(T a, T b) { return a < b ? a : b; } This will work for ints, floats, doubles... Anything that has a < operator will work. There's much more you can do with templates, but that's the fundamental problem that they solve.
Re: Is this really a bug?
On 7/01/12 1:19 AM, Daniel wrote: Hi, I've read on Bugzilla Issue 6398 that this is a bug: static int value; ref foo(){ printf("getter\n"); return value; } ref foo(int x){ printf("setter\n"); value = x; return value; } void main(){ foo = 1; } // Should print "setter", but print "getter" in 2.054 But, this is pretty convenient syntax, no? That way you could implement only one function foo() and use it as setter and getter. I'm a bit confused about it. Thanks, Daniel It is convenient syntax, but sometimes you want the getter to return a ref, but want the setter to do something different to "getter() = x". This bug says that there is no way to override a ref returning getter with a custom setter.
Re: An issue with lazy delegates
On 5/01/12 5:26 AM, Andrej Mitrovic wrote: The first call doesn't do anything because the delegate is wrapped inside of another delegate. I want this template to be versatile enough to be used by both lazy expressions and delegate literals, but I don't know how. void test(T)(lazy T dg) { static if (is(T == delegate)) dg()(); else dg(); } void main() { test( writeln("a") ); test( { writeln("b"); } ); }
Re: Cartesian product of ranges?
On 14/12/11 9:21 PM, Timon Gehr wrote: On 12/14/2011 09:14 PM, Justin Whear wrote: I've looked through std.algorithm and std.range, but haven't found anything to compute the Cartesian product of several ranges. I have the nagging feeling that this can be accomplished by combining several of the range transformations in the standard library. What I'm after is something like this: alias Tuple!(int, string) P; assert(equal( cartesianProduct([1, 2], ["a", "b"]), [ P(1, "a"), P(1, "b"), P(2, "a"), P(2, "b") ] )); auto cartesianProduct(R,S)(R r, S s)if(isInputRange!R && isForwardRange!S){ struct CartesianProduct{ private{R r; S s, startS;} this(R r, S s){this.r=r; this.s=s; startS=this.s.save;} @property auto front(){return tuple(r.front, s.front);} @property bool empty(){return r.empty;} void popFront(){ s.popFront(); if(s.empty){ s = startS.save; r.popFront(); } } static if(isForwardRange!R): @property auto save(){return typeof(this)(r.save, s.save);} } return CartesianProduct(r,s); } The implementation of this was discussed at length a while ago. The obvious implementation that you have above was presented, but Andrei was unhappy that it didn't work well with infinite ranges. Some schemes were investigated so that the products of two infinite ranges could would get better sampling, but the whole thing got stuck in analysis paralysis and nothing ever happened. What you have above should be added into Phobos. If people want the product of infinite ranges then they can just to it manually.
Re: auto
On 24/11/11 10:38 PM, Andrej Mitrovic wrote: But I bet you would waste more memory at compile-time if you had to type a long template instance name instead of using auto. We're talkin' bytes here! Actually, using `auto` should be faster because the compiler doesn't need to do any name lookup. auto x = foo(); // deduce type of Foo and use that Foo x = foo(); // find out what 'Foo' refers to, but also deduce type of foo() and then do type checking.
Aligning data in memory / on the stack
Can anyone help me with this? http://stackoverflow.com/questions/7375165/aligning-stack-variables-in-d --- Is there a way to align data on the stack? In particular, I want to create an 16-byte aligned array of floats to load into XMM registers using movaps, which is significantly faster than movups. e.g. void foo() { float[4] v = [1.0f, 2.0f, 3.0f, 4.0f]; asm { movaps XMM0, v; // v must be 16-byte aligned for this to work. ... } }
Re: NaCl stable ABI
On 2/08/11 2:24 AM, Adam Ruppe wrote: From what I can tell, it's Google's alternative to Flash; they want to make crappy games on it. Consider that the first thing they ported to it, again, just like their javascript nonsense, was Quake. (I think Google loves Javascript too much to let it go anyway.) The API has a lot of graphics and audio stuff too which reinforces this. The games industry has been crying out for something like NaCl for a long time. It is exactly what we want: - Ability to launch games within browser without a plugin download - Platform independent ABI - No f*cking Javascript (performance will never match C++) - Safe (no need for end users to worry) JavaScript for high-quality games is a non-starter. It's too slow. You simply cannot do high performance numeric code in Javascript (http://chadaustin.me/2011/01/digging-into-javascript-performance/). Writing C++ code to run outside of the browser is a pain, and inconvenient for the user. First, you have to write your code to handle all the different platforms, which is a huge burden. Once you've done that, you need to convince users to download and install your game. It would be much more convenient to just have users go a website and be done with it. If D were usable in NaCl that would be a huge selling point for the language.
Linker errors on OSX
I've been having strange linker errors recently and I have no ideas why they've started happening. When compiling/linking: import std.stdio; void main() { writeln("Hello"); } with DMD 2.053 I get linker error: Undefined symbols: "_D3std9exception7bailOutFAyaixAaZv", referenced from: _D3std9exception148__T7enforceTbVAyaa60_2f4c6962726172792f436f6d70696c6572732f646d64322f6f73782f62696e2f2e2e2f2e2e2f7372632f70686f626f732f7374642f737464696f2e64Vi1481Z7enforceFbLAxaZb in test.o ld: symbol(s) not found collect2: ld returned 1 exit status My first thought was that it isn't linking with phobos, but compiling with -v confirms that it is: gcc test.o -o test -m32 -Xlinker -L/Library/Compilers/dmd2/osx/bin/../lib -lphobos2 -lpthread -lm My GCC version is 4.2.1 $ gcc --version i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. I've tried re-downloading DMD again, but this didn't work. It appeared to start happening after running an update of all my outdated packages in MacPorts, but I can't be sure that that's the issue. Any help tracking down the problem would be much appreciated. Thanks.
Running DMD tests
I'm trying to run the test suite for DMD, but I'm running into issues. I've cloned dmd from github, and successfully built dmd, but when I run 'make' from the dmd/test dir, I get: $ make Creating output directory: test_results Building d_do_test tool object.d: Error: module object is in file 'object.d' which cannot be read Specify path to file 'object.d' with -I switch make: *** [test_results/d_do_test] Error 1 Do I need to set up my environment differently to run dmd in development? How can I get around this? Note: I'm running OSX 10.6.7 Thanks
Re: "not an lvalue"
On 1/05/11 2:53 PM, Dmitry Olshansky wrote: Ehm.. Well, first things first: you shouldn't use classes for lightweight & plain data things like vectors. There are structs for that. In general, structs are value-like objects living on the stack while classes are reference-like objects living on the heap. Your current code is going to allocate on GC heap new vector in every GetColumn and I suspect also when adding two vectors. structs don't live on the stack. They live wherever they are told to. In fact most structs will live in the heap as parts of class objects, or other heap-allocated objects such as dynamic arrays or AAs. The stack is for local variables and other things to do with the local scope. While struct objects *can* go on the stack, it is false to say that structs live on the stack and classes live on the heap. The type of an object (value type or reference type) is orthogonal to its storage location and the two should not be conflated.
Re: "not an lvalue"
On 1/05/11 2:30 PM, CrypticMetaphor wrote: Hi, I've been away from D for a while, but now I'm back and I'm stuck with an compile time error. I've got a Matrix33 class and a Vector3 class, but something is wrong with the way I return my Vector3 in my matrix class: If I do this I get an error: Matrix33 mtest = new Matrix33(); mtest.SetIdentity(); Vector3 test1 = new Vector3(0, 0, 0); Vector3 test2 = test + mtest.GetColumn(2); I get the error "Error: mtest.GetColumn(x) is not an lvalue" But the following works: Matrix33 mtest = new Matrix33(); mtest.SetIdentity(); Vector3 test1 = new Vector3(0, 0, 0); Vector3 temp = mtest.GetColumn(2); Vector3 test2 = test + temp; // GetColumn method Matrix33 { // ... /// Get a matrix column, horizontal line Vector3 GetColumn(uint index) { assert(!(index > 2), "index is too high"); return new Vector3(cell[index * 3], cell[index * 3 + 1], cell[index * 3 + 2]); } // ... } My questions: What changes do I have to make to make the first example compile? My guess is that your Vector3.opBinary!"+" is taking "ref" arguments instead of just taking them by value. Can you show us that function?
Re: Should writef try to statically check for format specifiers?
On 11/04/11 9:35 PM, Andrej Mitrovic wrote: I realize runtime checks would be out of the question... debug doRuntimeCheck(); :-)
Re: Ranges
On 18/03/11 5:53 PM, Jonathan M Davis wrote: On Friday, March 18, 2011 03:32:35 spir wrote: On 03/18/2011 10:29 AM, Peter Alexander wrote: On 13/03/11 12:05 AM, Jonathan M Davis wrote: So, when you're using a range of char[] or wchar[], you're really using a range of dchar. These ranges are bi-directional. They can't be sliced, and they can't be indexed (since doing so would likely be invalid). This generally works very well. It's exactly what you want in most cases. The problem is that that means that the range that you're iterating over is effectively of a different type than the original char[] or wchar[]. This has to be the worst language design decision /ever/. You can't just mess around with fundamental principles like "the first element in an array of T has type T" for the sake of a minor convenience. How are we supposed to do generic programming if common sense reasoning about types doesn't hold? This is just std::vector from C++ all over again. Can we not learn from mistakes of the past? I partially agree, but. Compare with a simple ascii text: you could iterate over it chars (=codes=bytes), words, lines... Or according to specific schemes for your app (eg reverse order, every number in it, every word at start of line...). A piece of is not only a stream of codes. The problem is there is no good decision, in the case of char[] or wchar[]. We should have to choose a kind of "natural" sense of what it means to iterate over a text, but there no such thing. What does it *mean*? What is the natural unit of a text? Bytes or words are code units which mean nothing. Code units (<-> dchars) are not guaranteed to mean anything neither (as shown by past discussion: a code unit may be the base 'a', the following one be the composite '^', both in "â"). Code unit do not represent "characters" in the common sense. So, it is very clear that implicitely iterating over dchars is a wrong choice. But what else? I would rather get rid of wchar and dchar and deal with plain stream of bytes supposed to represent utf8. Until we get a good solution to operate at the level of "human" characters. Iterating over dchars works in _most_ cases. Iterating over chars only works for pure ASCII. The additional overhead for dealing with graphemes instead of code points is almost certainly prohibitive, it _usually_ isn't necessary, and we don't have an actualy grapheme solution yet. So, treating char[] and wchar[] as if their elements were valid on their own is _not_ going to work. Treating them along with dchar[] as ranges of dchar _mostly_ works. We definitely should have a way to handle them as ranges of graphemes for those who need to, but the code point vs grapheme issue is nowhere near as critical as the code unit vs code point issue. I don't really want to get into the whole unicode discussion again. It has been discussed quite a bit on the D list already. There is no perfect solution. The current solution _mostly_ works, and, for the most part IMHO, is the correct solution. We _do_ need a full-on grapheme handling solution, but a lot of stuff doesn't need that and the overhead for dealing with it would be prohibitive. The main problem with using code points rather than graphemes is the lack of normalization, and a _lot_ of string code can get by just fine without that. So, we have a really good 90% solution and we still need a 100% solution, but using the 100% all of the time would almost certainly not be acceptable due to performance issues, and doing stuff by code unit instead of code point would be _really_ bad. So, what we have is good and will likely stay as is. We just need a proper grapheme solution for those who need it. - Jonathan M Davis P.S. Unicode is just plain ugly :( I must be missing something, because the solution seems obvious to me: char[], wchar[], and dchar[] should be simple arrays like int[] with no unicode semantics. string, wstring, and dstring should not be aliases to arrays, but instead should be separate types that behave the way char[], wchar[], and dchar[] do currently. Is there any problem with this approach?
Re: Ranges
On 13/03/11 12:05 AM, Jonathan M Davis wrote: So, when you're using a range of char[] or wchar[], you're really using a range of dchar. These ranges are bi-directional. They can't be sliced, and they can't be indexed (since doing so would likely be invalid). This generally works very well. It's exactly what you want in most cases. The problem is that that means that the range that you're iterating over is effectively of a different type than the original char[] or wchar[]. This has to be the worst language design decision /ever/. You can't just mess around with fundamental principles like "the first element in an array of T has type T" for the sake of a minor convenience. How are we supposed to do generic programming if common sense reasoning about types doesn't hold? This is just std::vector from C++ all over again. Can we not learn from mistakes of the past?
Re: Double-dispatch
On 13/02/11 9:32 PM, Sean Eskapp wrote: == Quote from bearophile (bearophileh...@lycos.com)'s article Sean Eskapp: Is there a nicer way to do this in D, or am I stuck with the same thing? Andrei has recently said no one needs double dispatch (in D) :-) So Andrei will be interested in your use case. Bye, bearophile The age-old collision handling problem is how I'm using it. Use a 2D array of function pointers, with the indices coming from unique IDs on the shapes.
Re: Starting with D
On 6/02/11 11:35 PM, Julius wrote: Hi there, i'm all new to D but not new to programming in general. I'd like to try D but i didn't find a nice tutorial yet. I don't want to read a whole book, I just want to get the basics so I can start. Can you help me find something like that? Best regards, Julius What languages do you know already? If it's one of C++, C#, or Java, you might just be able to jump right in, and just reference the website every now and then for specifics.
Setting thread priority
How do you set the priority of a thread, or otherwise control how much CPU time it gets? It appears that std.thread had an answer for this, but it has been removed from Phobos by the looks of things. On a side note, why is std.thread still in the online documentation if it was removed long ago? What's the point of having a tool to automatically generate documentation if we're going to have out of date docs anyway?
Re: Asynchronous concurrency with reference types
On 4/02/11 11:44 PM, Sean Kelly wrote: Peter Alexander Wrote: How would you do it with message passing though? As I understand, all of the std.concurrency message passing routines are blocking, and I need this to be asynchronous. What do you mean by blocking? The receive call will block until a message matching one of the supplied types arrives, but if you don't like this you can always use receiveTimeout. send() doesn't deep copy objects, so the only reference types send() will currently accept are those labeled as shared or immutable (Unique!T will probably be added at some point, which is more appropriate for your situation). So to use send() known unique reference data you'll have to cast to/from shared or immutable. Nasty, but it'll work. That's what I meant by blocking (receive). Is using receiveTimeout with a timeout of 0 seconds the D-way of asynchronous message passing? (seems a bit hacky to me). Thanks for your reply.
Re: Asynchronous concurrency with reference types
On 5/02/11 12:11 AM, Sean Kelly wrote: Peter Alexander Wrote: Things might be easier if the error messages associated with D's concurrent features weren't especially unhelpful (for example, trying to spawn a thread with reference type parameters just gives you a 'no match for spawn template' error). It's nice that it stops you from doing such things, but it would be nice if it told me why it's not going to let me do them. Could you provide an example? When passing reference data, the error you should see is: "Aliases to mutable thread-local data not allowed." It's a static assert inside send(). Now that I've investigated a bit more, it appears to be unrelated to reference types, and instead was an error about using a nested function: import std.concurrency; void main() { void foo() {} spawn(&foo); } --- test.d(5): Error: template std.concurrency.spawn(T...) does not match any function template declaration test.d(5): Error: template std.concurrency.spawn(T...) cannot deduce template function from argument types !()(void delegate()) --- Why does it think that the function is a delegate?
Re: Asynchronous concurrency with reference types
On 4/02/11 8:42 PM, spir wrote: On 02/04/2011 07:18 PM, Peter Alexander wrote: I would like to be able to spawn a thread, which does a lot of work, and then returns (in some way) the result of its computations to the main thread. I would really like to avoid copying its results if possible. Logically, what I would like is something like this: class LotsOfData { ... } void doStuff(LotsOfData d) { ... } shared(LotsOfData[]) data; void main() { spawn( &doWork ); while(true) { foreach (d; data) doStuff(d); } } void doWork() { LotsOfData d = new LotsOfData; // lots of computation on d data ~= d; } Essentially, the work that doWork does needs to be returned to the main thread asynchronously, and obviously in a thread-safe manner. What's the best way to do this? The above won't work because ~= isn't atomic, so you can't do it on shared data. (I have few exp in the paradigm, so don't believe me.) It seems your problem is a typical case that cannot be safe as is. Essentially, IIUC, you want a shared set of data to be fed (more generally: mutated) from a thread, while another thread (here, the main one) processes bits of it. How can this be correct as is --except as you say if mutating operations were atomic? I think in such a case you /must/ have a communication protocal between both tasks/threads. It is not due to language features (present ot not, this or that way) but to the problem itself. Correct me if I'm wrong, please. Denis You may be right, I don't know (that's why I'm asking!) I was hoping that I would be able to do something using synchronized classes, but I'm not fully up to speed with how they interact with shared and immutable, and all the semantics associated with it. I understand that passing immutable value types around is very easy, but unfortunately that's rarely practical. Things might be easier if the error messages associated with D's concurrent features weren't especially unhelpful (for example, trying to spawn a thread with reference type parameters just gives you a 'no match for spawn template' error). It's nice that it stops you from doing such things, but it would be nice if it told me why it's not going to let me do them.
Re: Asynchronous concurrency with reference types
On 4/02/11 8:23 PM, Jesse Phillips wrote: Peter Alexander Wrote: Essentially, the work that doWork does needs to be returned to the main thread asynchronously, and obviously in a thread-safe manner. What's the best way to do this? The above won't work because ~= isn't atomic, so you can't do it on shared data. Disclaimer: I don't really do much with threading/concurrency. You might look at using parallelfuture, the library to be added to Phobos as parallelism. An example similar to yours, though instead of the doWork getting a thread it is the doStuff function, and this example is for a call center: https://gist.github.com/774983 Call => LoadsOfData callGenerator => doWork Threed.sleep => doStuff You will probably also want to return an Immutable Call from callGenerator, that should result in a non-copy share (Though maybe it already does that). You may also want to look at std.concurrency and make use of message passing. https://gist.github.com/773979 Hopefully this are a good starting place. Thanks, I'll take a look at parallelism. How would you do it with message passing though? As I understand, all of the std.concurrency message passing routines are blocking, and I need this to be asynchronous.
Asynchronous concurrency with reference types
I would like to be able to spawn a thread, which does a lot of work, and then returns (in some way) the result of its computations to the main thread. I would really like to avoid copying its results if possible. Logically, what I would like is something like this: class LotsOfData { ... } void doStuff(LotsOfData d) { ... } shared(LotsOfData[]) data; void main() { spawn( &doWork ); while(true) { foreach (d; data) doStuff(d); } } void doWork() { LotsOfData d = new LotsOfData; // lots of computation on d data ~= d; } Essentially, the work that doWork does needs to be returned to the main thread asynchronously, and obviously in a thread-safe manner. What's the best way to do this? The above won't work because ~= isn't atomic, so you can't do it on shared data.
Re: Development blog? D news?
On 17/01/11 8:16 AM, bioinfornatics wrote: will be great if we have a planet. An example here : http://planet.fedoraproject.org/ A planet it is a web page who feed several blog, user can use a cms for to write a blog like Dotclear, wordpress ... http://planet.dsource.org/ Problem is: it's not very active, and also, apparently people don't know about it :-)
Development blog? D news?
Take a look at the website (either digitalmars, or d-programming-language). There is absolutely no indication on those sites that the D language is actually going anywhere. Other than version numbers on the downloads, nothing changes. Outsiders have no idea what's going on. Here's a suggestion: Why not start a development blog, on the home page of d-programming-language.com, or digitalmars.com that Walter and/or Andrei (maybe anyone working on D) post to regularly? Things are always being discussed inside the news groups, and I'm sure other people would like to read about your thoughts on language and library design. More importantly though, it would show that the language is actively under development, and would get people excited about D. I know that Walter and Andrei often post articles on Infomit or DDJ, but what's the point of linking people away from the actual D sites? Get people linking here. One potential problem with this is that both websites seem to be raw HTML hacked together with no CMS to be found. I would recommend just starting over at d-programming-language.com with a Joomla install (or something similar). You could easily have it all set up in under a day. I'm no web-guru, but I could help out if needed. P.S. Whoever is responsible for d-programming-language.com, please use google.com/webmasters... The 'Library Reference' link has been broken for a while now, which is unacceptable when there's a free tool out there that will tell you about it.
Re: Initialising arrays at compile time
On 2/01/11 2:16 PM, bearophile wrote: Is this good enough? struct Vec { double[2] e; static enum Vec zero = Vec([0.0, 0.0]); this(real x, real y) { e[0] = x; e[1] = y; } } Well it works, so yes :-) That's quite irritating. Why does the automatically generated one work, but not the hand written one. Grrr... I also discovered that this works: enum Vec zero = Vec([0.0, 0.0]); this(double[2] v) { foreach (size_t i, ref r; e) r = v[i]; } Which works in the general case of an arbitrary sized vector.
Initialising arrays at compile time
Ok, someone put me out of my misery, I can't figure out for the life of me how to do this. Basically, I have a vector class and want enums for the zero vectors: struct Vec { this(real x, real y) { e[0] = x; e[1] = y; } real[2] e; enum Vec zero = Vec(0, 0); } What can I do? The above doesn't work because: test.d(3): Error: Index assignment this.e[0u] = x is not yet supported in CTFE test.d(3): Error: Index assignment this.e[1u] = y is not yet supported in CTFE Changing the constructor to do e = [x, y] doesn't work either. test.d(3): Error: Slice operation this.e[] = [x,y] cannot be evaluated at compile time test.d(5): Error: cannot evaluate __ctmp1.this(0L,0L) at compile time test.d(5): Error: cannot evaluate __ctmp1.this(0L,0L) at compile time What can I do? And once I do that, I need to do it also for: struct Vec(int N) { real[N] e; ... } Thanks in advance.
Re: Understanding isInfinite(Range)
== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article > On Fri, 03 Sep 2010 11:12:29 -0400, Andrej Mitrovic > wrote: > > What does char[1 + Range.empty] do? It looks rather cryptic.. > char[1+Range.empty] is a type. If Range.empty is a compile-time constant, > then this type is valid, otherwise it's not valid (the is expression > results to true if the argument is a valid type). > If it's valid, then Range.empty never changes. If it never changes and > it's always false, then it's infinite. > -Steve That's really ugly code :-( Is there a way you could write an isStatic(expr) template? Using something like that would make the code a hell of a lot more readable. At the moment, the code itself does a very poor job of conveying what it's trying to accomplish. These SFINAE-like tricks should be black-boxed as much as possible, or (at the very least) commented so that people know what's going on.
Re: Is "is" the same as ptr == ptr for arrays?
On 7/08/10 4:33 PM, simendsjo wrote: Is the following equalent? int[] a; int[] b = a; assert(a is b); assert(a.ptr == b.ptr); No. (a is b) implies (a.ptr == b.ptr) but (a.ptr == b.ptr) does not imply (a is b) For example: int[] a = [1, 2, 3]; int[] b = a[0..1]; Here, a.ptr == b.ptr, but a !is b. The ptr property returns a pointer to the first element, which is true in this case, but it doesn't mean that they both refer to the same range.
Re: Default constructor for structs
On 7/08/10 3:44 PM, bearophile wrote: Peter Alexander: Bye, bearophile Thanks for your detailed reply. However, I'm not particularly satisfied with any of those :( I have already gone with the single parameter init constructor in my code until I find something better, but really, I just want the matrix to be default initialised to zeroes without having to explicitly specify it in client code. Initialising to NaNs is highly unintuitive (especially since ints auto-initialise to 0...) and this has already caused me unnecessary grief. I understand the reasoning, and I might agree with it if it wasn't forced on you...
Default constructor for structs
Since default constructors for structs are not allowed, how do I go about making all the elements of this Matrix struct default to zero? (floats default to nan by default). struct Matrix(int M, int N) { float[M][N] elements; } Matrix(3, 3) m; assert(m[0][0] == 0); ?
Re: Partial template function specialization
Lars T. Kyllingstad Wrote: > Disclaimer: You didn't say whether you use D1 or D2, but I use D2, so > I'll give my answer in D2 code. It is highly likely it will also work in D1. I'm using neither :) I'm just considering learning at the moment. > First of all, I don't know how it is in C++, but in D you rarely write > function declarations without definitions. So unless you have a very > general function body for your "general case", I'd simply drop it. If > you have, the general case looks like this: > > > > For more info, check out http://www.digitalmars.com/d/2.0/template.html > > -Lars Excellent! Thanks a lot. I was hoping that D could overcome this problem. Ah, one (maybe) final question: Is there an equivalent to friends in D (didn't see any in the docs)? If so, do they work with templates easily? In my style of programming, I very rarely use member functions (I think they are an atrocity in language design), so I create global functions for almost everything, and when they need to access to private members, I have the class declare the function as a friend. Does D support my style of programming? Here's a concrete example of something I'd like to do (pseudocode): class Foo { private int x; friend globalFun; } class Bar { private int y; friend globalFun; } void globalFun(ref Foo foo, ref Bar bar) { foo.x = bar.y; } Is there anything like this in D? Export sounds like the right thing, but can that be used in the example above, assuming that Foo and Bar are in separate modules?
Re: Partial template function specialization
Simen Kjaeraas Wrote: > > T foo( T, U )( U value ) {...} > > template fooPartial( T ) { >alias foo!( T, int ) fooPartial; > } > > This may or may not have been what you want. Not quite sure what's going on there, but it doesn't look like what I want. I want a general function: T foo(T, U)(U value) and one specialized for when U = Vector3!(T) Also, it's important that the original and the specialization have the same function name, otherwise it's not really generic at all. > Macros are currently scheduled for D3. In the meantime, you can do just > about anything with string mixins and CTFE. Cool. Is there any sort of ETA on D3?
Partial template function specialization
Hey all, I'm considering learning D at the moment, and one thing that has bothered me in C++ is the lack of partial template function specializations. For example, you can create something like this: template const Field norm(const V& v); and you can specialize it: template <> const double norm(const double& d) { return d < 0.0 ? -d : d; } but you can't partially specialize it: template const Field norm(const Vector3& v) { /* return sqrt( ... ) */ } Unless I'm mistaken... Also, while I'm here. Does D have any macro support? I know it doesn't have pre-processor macros, but something like Nemerle's macros would be really, really nice. Thanks in advance.