Re: Library design
On Friday, 13 June 2014 at 05:54:02 UTC, TheFlyingFiddle wrote: On Friday, 13 June 2014 at 04:11:38 UTC, Rutger wrote: I'm trying to create a minimal tweening library in D based on the commonly used easing equations by Robert Penner (http://www.robertpenner.com/easing/). One of the goals with the design of the library is that any numeric type should be tweenable.(The user of the library shouldn't have to do any casting of their own etc) Now how do I go about and design a data structure that can take either floats, ints or doubles, store them and modify them? This is what I hacked together earlier today: abstract class TweenWrapper{ } class Tween(T) : TweenWrapper{ T owner; string[] members; /** Duration in milliseconds */ int duration; /** Elapsed time in milliseconds */ int elapsedTime; bool isComplete; /** Type of easing */ EasingType easingType; } TweenWrapper is just what it sounds like, a wrapper so I don't have to specify any type for the container holding the Tween objects(DList!TweenWrapper). __traits(getMember, owner, members[0]) = valueReturnedFromEasingFunction; Was How I planned to use this class.. but you know, compile time only. Let me know if this isn't enough to go on. Is what I'm asking even possible(the easy way) in D? TL;DR Help me make D Dynamic! From what i can tell you want something similar to this. interface ITween { void update(int elapsedTime); } class Tween(T, string member) : ITween { //Expands to //|alias memberType = typeof(T.memberName);| mixin("alias memberType = typeof(" ~ T.stringof ~ "." ~ member ~ ");"); memberType from; memberType to; EasingType type; int duration; int elapsedTime; T owner; @property bool isComplete() { return elapsedTime >= duration; } void update(int time) { elapsedTime = min(elapsedTime + time, duration); double amount = elapsedTime / cast(double)duration; auto tweened = ease(type, from, to, amount); __traits(getMember, owner, member) = tweened; } } Where ease is a method that will look something like this: T ease(T)(EasingType type, T from, T to, double amount) if(isNumeric!T) { double result; if(type == EasingType.linear) result = linearEase(amount); else assert(0, "Not yet implemented"); return cast(T)((to - from) * result + from)); } double linearEase(double amount) { return amount; } This will work for all number types. Hope this was helpful. Gonna try this later, thanks a lot!
Re: Working on a library: request for code review
On Thursday, 12 June 2014 at 19:30:06 UTC, Rene Zwanenburg wrote: I need to go. Please don't mind any typo's and untested code ;). Didn't take a look at writers yet, readers and util need some more scrutiny, but the main theme is: eliminate unnecessary temporary GC allocations. Thank you for feedback, hoping for more! I will apply the suggestions tonight.
Re: Cannot alias null
On Thursday, 12 June 2014 at 21:07:47 UTC, Tom Browder via Digitalmars-d-learn wrote: What I was really trying to do was D'ify C expressions like this: typedef ((struct t*)0) blah; This doesn't compile for me with GCC, and I don't know what it's supposed to mean. ((struct t*) 0) is a value, not a type... Where does it come from?
Re: Cannot alias null
On Thursday, 12 June 2014 at 22:54:20 UTC, Ali Çehreli wrote: On 06/12/2014 03:38 PM, monarch_dodra wrote: > So there's something special about "null". The difference is that null is an expression. It is the same limitation as not being able to alias a literal. alias zero = 0; alias blah = null; Oh! Right. That makes sense. So you should use enum instead: enum zero = 0; enum blah = null; Thanks.
Re: Cannot alias null
On Fri, Jun 13, 2014 at 7:59 AM, via Digitalmars-d-learn wrote: > On Thursday, 12 June 2014 at 21:07:47 UTC, Tom Browder via > Digitalmars-d-learn wrote: >> >> What I was really trying to do was D'ify C expressions like this: >> >> typedef ((struct t*)0) blah; > > > This doesn't compile for me with GCC, and I don't know what it's supposed to > mean. ((struct t*) 0) is a value, not a type... Sorry, you're correct. It is from a C macro and would be used for an rvalue. Something like this: $ cat chdr.h struct t; #define t_nullptr ((struct t*)0) struct t* t_ptr = t_nullptr; After pre-processing with "gcc -E -P" that should read: $ cat chdr.h.i struct t; struct t* t_ptr = ((struct t*)0); which does compile. So I'm not sure how to translate that into D. I do know my first attempt here doesn't work, even with it being surrounded by extern (C) {}: $ cat chdr.d struct t; struct t* t_ptr = null; > Where does it come from? The usage comes from many of the C API headers in the BRL-CAD package (http://brlcad.org). Best, -Tom
Re: Dub. Mercurial (bitbucket.org). Projects deployment
Thanks for all the answers) 8. I have another more simple question about rdmd utility. It takes one *.d file and searches for all dependencies. What if I need to pass independent *.d file or *.ddoc file directly to dmd compiler? How could I do that using dmd? I have no idea how I could include *.ddoc file with set of DDOC macroses. I have tried to use string mixin. mixin(import("mysettings.ddoc")); But I haven't succeed. My be compiler strips all the comments before mixing in or I doing something wrong. Another way is to use dmd.conf but I don't like this, because it's brutal way of doing so and as I think it's not compiler independent.
Re: Cannot alias null
On Friday, 13 June 2014 at 15:05:49 UTC, Tom Browder via Digitalmars-d-learn wrote: On Fri, Jun 13, 2014 at 7:59 AM, via Digitalmars-d-learn wrote: On Thursday, 12 June 2014 at 21:07:47 UTC, Tom Browder via Digitalmars-d-learn wrote: What I was really trying to do was D'ify C expressions like this: typedef ((struct t*)0) blah; This doesn't compile for me with GCC, and I don't know what it's supposed to mean. ((struct t*) 0) is a value, not a type... Sorry, you're correct. It is from a C macro and would be used for an rvalue. Something like this: $ cat chdr.h struct t; #define t_nullptr ((struct t*)0) struct t* t_ptr = t_nullptr; After pre-processing with "gcc -E -P" that should read: $ cat chdr.h.i struct t; struct t* t_ptr = ((struct t*)0); which does compile. So I'm not sure how to translate that into D. I do know my first attempt here doesn't work, even with it being surrounded by extern (C) {}: $ cat chdr.d struct t; struct t* t_ptr = null; Where does it come from? The usage comes from many of the C API headers in the BRL-CAD package (http://brlcad.org). Best, -Tom Remove the struct from the pointer: struct t; t* t_ptr = null;
Re: Cannot alias null
On Friday, 13 June 2014 at 15:05:49 UTC, Tom Browder via Digitalmars-d-learn wrote: So I'm not sure how to translate that into D. I do know my first attempt here doesn't work, even with it being surrounded by extern (C) {}: $ cat chdr.d struct t; struct t* t_ptr = null; This seems to work fine for me. What's the problem? Note this isn't *strictly* the same as what you have in C, as "null" is not strongly bindded to a single type. If you want a null pointer which is pre-emptivelly strongly, then you can use an eponymous template: enum nullptr(T) = (T*).init; auto p = nullptr!t; Throw in an alias, and you got it working exactly like an C: enum nullptr(T) = (T*).init; alias t_nullptr = nullptr!t; struct t* t_ptr = t_nullptr; That said, I'd advise against this. Just use "null" and move on. It's idiomatic.
Re: Cannot alias null
On Fri, Jun 13, 2014 at 10:15 AM, monarch_dodra via Digitalmars-d-learn wrote: > On Friday, 13 June 2014 at 15:05:49 UTC, Tom Browder via Digitalmars-d-learn > wrote: >> >> So I'm not sure how to translate that into D. I do know my first >> attempt here doesn't work, even with it being surrounded by extern (C) >> {}: >> >> $ cat chdr.d >> struct t; >> struct t* t_ptr = null; > > > This seems to work fine for me. What's the problem? I use "dmd -c .d" (note file name change) and get: t.d(2): Error: { } expected following aggregate declaration t.d(2): Error: Declaration expected, not '*' Taking Philpax's suggestion I try $ cat t.d struct t; t* t_ptr = null; $ dmd -c t.d and get a good build. > Note this isn't *strictly* the same as what you have in C, as "null" is not ... > strongly bindded to a single type. If you want a null pointer which is > pre-emptivelly strongly, then you can use an eponymous template: ... > That said, I'd advise against this. Just use "null" and move on. It's > idiomatic. So this is the correct (i.e., good enough) solution then: $ cat t.d struct t; t* t_ptr = null; Sounds good to me. Thanks all. Best, -Tom
User defined forward range - foreach initializes f.r.
Hi, I have a template class "List" which should provide generic list functionality. In my use case, using a class instead a struct is more comfortable. Following unittest fails, although the forward range implements the save method. unittest { auto intList = new List!int(1,2,3); assert(intList.length == 3); foreach(item; intList) {} assert(intList.length == 3); } class List(T) { private T[] items; this(T[] items...) { this.items = items; } bool empty() const { return items.length == 0; } @property int length() const { return items.length; } void popFront() { items = items[1..$]; } @property List!T save() const { return new List!T( cast(T[]) items); } T front() const { return opIndex(0); } T opIndex(size_t index) const { return cast(T) items[index]; } } I already tried different thinks, like using dup or importing std.array. But nothing helps, the unittest fails. Why it fails? Kind regards André
Re: User defined forward range - foreach initializes f.r.
On Fri, Jun 13, 2014 at 08:14:11PM +0200, Andre via Digitalmars-d-learn wrote: > Hi, > > I have a template class "List" which should provide generic list > functionality. In my use case, using a class instead a struct > is more comfortable. > > Following unittest fails, although the forward range > implements the save method. [...] Generally, it's a bad idea to conflate a container with a range over its contents. In this sense, built-in arrays are a very bad example, because they show precisely this sort of conflation. But they get away with it because of their hybrid value/reference semantics. Most containers, however, don't have this sort of complex semantics, so they don't mix very well with ranges directly. It's much better to separate the container from a range over its contents. So I wouldn't put the range API methods in the List class, but implement an opSlice method that returns a struct that performs the list iteration, that implements the range API. This allows you to write: auto myList = new List(...); foreach (item; myList[]) { // N.B., myList[] calls myList.opSlice() ... } Since the range struct returned by opSlice is separate from the container itself, you don't have any risk of iteration also consuming the container. T -- Let X be the set not defined by this sentence...
Re: User defined forward range - foreach initializes f.r.
Am 13.06.2014 20:22, schrieb H. S. Teoh via Digitalmars-d-learn: [...] Generally, it's a bad idea to conflate a container with a range over its contents. In this sense, built-in arrays are a very bad example, because they show precisely this sort of conflation. But they get away with it because of their hybrid value/reference semantics. Most containers, however, don't have this sort of complex semantics, so they don't mix very well with ranges directly. It's much better to separate the container from a range over its contents. So I wouldn't put the range API methods in the List class, but implement an opSlice method that returns a struct that performs the list iteration, that implements the range API. This allows you to write: auto myList = new List(...); foreach (item; myList[]) { // N.B., myList[] calls myList.opSlice() ... } Since the range struct returned by opSlice is separate from the container itself, you don't have any risk of iteration also consuming the container. T Thank you, this information is really helpful. Kind regards André
Re: User defined forward range - foreach initializes f.r.
On Friday, 13 June 2014 at 18:14:10 UTC, Andre wrote: Hi, I have a template class "List" which should provide generic list functionality. In my use case, using a class instead a struct is more comfortable. Following unittest fails, although the forward range implements the save method. unittest { auto intList = new List!int(1,2,3); assert(intList.length == 3); foreach(item; intList) {} assert(intList.length == 3); } ... I already tried different thinks, like using dup or importing std.array. But nothing helps, the unittest fails. Why it fails? Kind regards André To add to what H.S. Teoh said, which is good advice, but doesn't quite explain why your unittest failed: Foreach takes a copy of your range, and then "consumes it". This may or may not have an effect on the original range. If you plan to use your range again after a call, you are supposed to *save* it: unittest { auto intList = new List!int(1,2,3); assert(intList.length == 3); foreach(item; intList.save) {} //HERE assert(intList.length == 3); } There.
Initialization sequence of runtime environment
I recently posted another thread (regarding crt1.o: could not read symbols: Bad value - I'm creating a new thread because it's another problem) and I figured out that the following error: stack_bottom = 7fc98804ae18 thread_stack 0x4 /usr/sbin/mysqld(my_print_stacktrace+0x35)[0x8cea15] /usr/sbin/mysqld(handle_fatal_signal+0x4a4)[0x65e0d4] /lib64/libpthread.so.0(+0xf710)[0x7fc98abcb710] /usr/lib64/libphobos2.so.0.65(gc_malloc+0x29)[0x7fc951a70e05] ... occures when I never call rt_init()/rt_term() (or Runtime.initialize()/Runtime.terminate()). That solved the problem and I can successfully execute all my D-code. I'm using the shared library as UDF in MySQL. My current code looks as follows: export extern(C){ my_bool mysql_d_udf_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { return (rt_init() ? 0 : 1); } void mysql_d_udf_deinit(UDF_INIT *initid) { rt_term(); } char* mysql_d_udf(UDF_INIT* initid, UDF_ARGS* args, char* result, c_ulong *length, char* is_null, char* error) { string res = "Hello World!"; result = cast(char*) res.ptr; *length = res.length; return cast(char*) result; } } When I register the function in MySQL and execute "select mysql_d_udf()" everything works fine. I'm receiving "Hello World!" and everything is fine. But when I try to restart the server, the server is not responding. I've to kill the server manually which is impracticable in productional environment. I first thought that rt_term() throws an exception (or something else) that prevents the MySQL server from being restartet gracefully. So I removed rt_term() from my deinit()-function. But that didn't solve the problem. When I also remove rt_init() I'm getting the gc_malloc-exception as described above. So it seems that rt_init() registers/enables something I'm unable to release I don't know exactly. Fact is that I see no exception or log entry in my MySQL log and the server restarts successfully without my D-based UDF plugin. So something seems to be wrong... I don't know if my initialization of the D-runtime environment is correct? I sometimes read something about gc_init() (but I thought rt_init()/Runtime.initialize() handles that for me...). Any suggestions how to initialize/terminate the runtime environment in shared libraries? Probably I'm doing something wrong... If there's no solution, I've to write the UDF functions using C (I don't prefer that way because all other projects are D-based).
Re: User defined forward range - foreach initializes f.r.
I am making the following comment to have others confirm, as well as remind others about a potential problem. On 06/13/2014 11:14 AM, Andre wrote: > unittest > { > auto intList = new List!int(1,2,3); [...] > class List(T) > { > private T[] items; > > this(T[] items...) > { > this.items = items; > } Unrelated to your question, I think that is a bug because you are keeping a reference to a temporary array. The compiler will generate a temporary array for 1, 2, and 3 and then that array will disappear. Am I remembering correctly? If so, I would recommend against 'T[] items...' but use an explicit slice: this(T[] items) The users will slightly be inconvenienced but the program will be correct. Or, you can continue with 'T[] items...' and then have to take a copy of the argument: this.items = items.dup;// copied That is obviously slower when the user actually passed in a slice. That's why I think it is better to take an explicit slice as a parameter. Ali
Re: User defined forward range - foreach initializes f.r.
On Friday, 13 June 2014 at 19:03:12 UTC, Ali Çehreli wrote: I am making the following comment to have others confirm, as well as remind others about a potential problem. On 06/13/2014 11:14 AM, Andre wrote: > unittest > { > auto intList = new List!int(1,2,3); [...] > class List(T) > { > private T[] items; > > this(T[] items...) > { > this.items = items; > } Unrelated to your question, I think that is a bug because you are keeping a reference to a temporary array. The compiler will generate a temporary array for 1, 2, and 3 and then that array will disappear. Am I remembering correctly? If so, I would recommend against 'T[] items...' but use an explicit slice: this(T[] items) The users will slightly be inconvenienced but the program will be correct. Or, you can continue with 'T[] items...' and then have to take a copy of the argument: this.items = items.dup;// copied That is obviously slower when the user actually passed in a slice. That's why I think it is better to take an explicit slice as a parameter. Ali Yes. `fun(T)(T[]...)` is just both `fun(T...)(T t)` and `fun(T)(T[] t)` both "conveniently" packaged into one, but with twice the pitfalls. I'd suggest avoiding it altogether. It's a non-feature (IMO).
Why is stdin.byLine.writeln so slow?
I've been playing around with D and noticed that: stdin.byLine.writeln takes ~20 times as long as: foreach(line; stdin.byLine) writeln(line); I asked on IRC and this was suggested: stdin.byLine(KeepTerminator.yes).copy(stdout.lockingTextWriter) which is slightly faster than the foreach case. It was suggested that there is something slow about writeln taking the input range, but I'm not sure I see why. If I follow the code correctly, formatRange in std.format will eventually be called and iterate over the range.
Re: Why is stdin.byLine.writeln so slow?
On Friday, 13 June 2014 at 20:48:16 UTC, Jyxent wrote: I've been playing around with D and noticed that: stdin.byLine.writeln takes ~20 times as long as: foreach(line; stdin.byLine) writeln(line); I asked on IRC and this was suggested: stdin.byLine(KeepTerminator.yes).copy(stdout.lockingTextWriter) which is slightly faster than the foreach case. It was suggested that there is something slow about writeln taking the input range, but I'm not sure I see why. If I follow the code correctly, formatRange in std.format will eventually be called and iterate over the range. Because: stdin.byLine.writeln and foreach(line; stdin.byLine) writeln(line); Don't produce the same output. One prints a range that contains strings, whereas the second repeatedly prints strings. Given this input: line 1 line2 Yo! Then "stdin.byLine.writeln" will produce this string: ["line 1", "line\t2", "Yo!"] So that's the extra overhead which is slowing you down, because *each* character needs to be individually parsed, and potentially escaped (eg: "\t"). The "copy" option is the same as the foreach one, since each string is individually passed to the writeln, which doesn't parse your string. The "lockingTextWriter" is just sugar to squeeze out extra speed.
Re: Working on a library: request for code review
On 06/12/2014 09:30 PM, Rene Zwanenburg wrote: I remember a function which does something like only only + canFind on one go. It would look something like header.colorMapDepth.among(16, 32); but I can't find it right now.. Maybe it was only proposed but never added. http://dlang.org/library/std/algorithm/among.html -- Mike Wey
Re: Why is stdin.byLine.writeln so slow?
On 06/13/2014 02:08 PM, monarch_dodra wrote: > Given this input: > line 1 > line2 > Yo! > > Then "stdin.byLine.writeln" will produce this string: > ["line 1", "line\t2", "Yo!"] Do you mean writeln() first generates an array and then prints that array? I've always imagined that it used the range interface and did similar to what copy() does. Is there a good reason why the imagined-by-me-range-overload of writeln() behaves that way? Ali
Re: Why is stdin.byLine.writeln so slow?
On Friday, 13 June 2014 at 21:08:08 UTC, monarch_dodra wrote: On Friday, 13 June 2014 at 20:48:16 UTC, Jyxent wrote: I've been playing around with D and noticed that: stdin.byLine.writeln takes ~20 times as long as: foreach(line; stdin.byLine) writeln(line); I asked on IRC and this was suggested: stdin.byLine(KeepTerminator.yes).copy(stdout.lockingTextWriter) which is slightly faster than the foreach case. It was suggested that there is something slow about writeln taking the input range, but I'm not sure I see why. If I follow the code correctly, formatRange in std.format will eventually be called and iterate over the range. Because: stdin.byLine.writeln and foreach(line; stdin.byLine) writeln(line); Don't produce the same output. One prints a range that contains strings, whereas the second repeatedly prints strings. Given this input: line 1 line2 Yo! Then "stdin.byLine.writeln" will produce this string: ["line 1", "line\t2", "Yo!"] So that's the extra overhead which is slowing you down, because *each* character needs to be individually parsed, and potentially escaped (eg: "\t"). The "copy" option is the same as the foreach one, since each string is individually passed to the writeln, which doesn't parse your string. The "lockingTextWriter" is just sugar to squeeze out extra speed. Hah. You're right. I had seen writeln being used this way and just assumed that it printed every line, without looking at the output too closely. Thanks for clearing that up.
Re: Why is stdin.byLine.writeln so slow?
On Friday, 13 June 2014 at 21:17:27 UTC, Ali Çehreli wrote: On 06/13/2014 02:08 PM, monarch_dodra wrote: > Given this input: > line 1 > line2 > Yo! > > Then "stdin.byLine.writeln" will produce this string: > ["line 1", "line\t2", "Yo!"] Do you mean writeln() first generates an array and then prints that array? No, it just receives a range, so it does range formating. eg: "[" ~ Element ~ ", " ~ Element ... "]". I've always imagined that it used the range interface and did similar to what copy() does. That wouldn't make sense. Then, if I did "[1, 2, 3].writeln();", it would print: 123 instead of [1, 2, 3] Is there a good reason why the imagined-by-me-range-overload of writeln() behaves that way? Ali As I said, it's a range, so it prints a range. That's all there is to it. That said, you can use one of D's most powerful formating abilities: Range formating: writefln("%-(%s\n%)", stdin.byLine()); And BOOM. Does what you want. I freaking love range formatting. More info here: http://dlang.org/phobos/std_format.html#.formattedWrite TLDR: %( => range start %) => range end %-( => range start without element escape (for strings mostly).
Re: Why is stdin.byLine.writeln so slow?
On 06/13/2014 03:02 PM, monarch_dodra wrote: > No, it just receives a range, so it does range formating. eg: > "[" ~ Element ~ ", " ~ Element ... "]". It still looks like it could send the formatting characters as well as the elements separately to the output stream: "[" Element ", " ... "]" I am assuming that the slowness in OP's example is due to constructing a long string. Ali
Re: Why is stdin.byLine.writeln so slow?
On Friday, 13 June 2014 at 22:12:01 UTC, Ali Çehreli wrote: On 06/13/2014 03:02 PM, monarch_dodra wrote: > No, it just receives a range, so it does range formating. eg: > "[" ~ Element ~ ", " ~ Element ... "]". It still looks like it could send the formatting characters as well as the elements separately to the output stream: "[" Element ", " ... "]" I am assuming that the slowness in OP's example is due to constructing a long string. Ali We'd have to check, but don't think that formatted write actually ever allocates anywhere, so there should be no "constructing a long string". The real issue (I think), is that when you ask formatted write to write a string, it just pipes the entire char array at once to the underlying stream. If the characters are escaped though (which is the case when you print an array of strings), then formatedWrite needs to check each character individually, and then also pass each character individually to the underlying stream. And *that* could definitely justify the order of magnitude slowdown observed. What's more this *may* trigger a per-character decode-encode loop. I'd have to check. But that shouldn't be observable next to the stream overhead anyways.
Re: Why is stdin.byLine.writeln so slow?
On Fri, Jun 13, 2014 at 10:02:49PM +, monarch_dodra via Digitalmars-d-learn wrote: [...] > That said, you can use one of D's most powerful formating abilities: > Range formating: > writefln("%-(%s\n%)", stdin.byLine()); > > And BOOM. Does what you want. I freaking love range formatting. > More info here: > http://dlang.org/phobos/std_format.html#.formattedWrite > > TLDR: > %( => range start > %) => range end > %-( => range start without element escape (for strings mostly). I wrote part of that documentation, and my favorite example is matrix formatting: auto mat = [[1,2,3], [4,5,6], [7,8,9]]; writefln("[%([%(%d %)]%|\n %)]", mat); Output: [[1 2 3] [4 5 6] [7 8 9]] D coolness at its finest! Whoever invented %(, %|, %) is a genius. It takes C's printf formatting from weak sauce to whole new levels of awesome. I remember debugging some range-based code, and being able to write stuff like: debug writefln("%(%(%s, %); %)", buggyNestedRange().take(10)); at strategic spots in the code is just pure win. In C/C++, you'd have to manually write nested loops to print out the data, which may involve manually calling accessor methods, manually counting them, perhaps storing intermediate output fragments in temporary buffers, encapsulating all this jazz in a throwaway function so that you can use it at multiple strategic points (in D you just copy-n-paste the single line above), etc.. Pure lose. (Speaking of which, this might be an awesome lightning talk topic at the next DConf. ;-) Or did somebody already do it?) T -- Having a smoking section in a restaurant is like having a peeing section in a swimming pool. -- Edward Burr
Re: Why is stdin.byLine.writeln so slow?
On Friday, 13 June 2014 at 22:25:25 UTC, H. S. Teoh via Digitalmars-d-learn wrote: In C/C++, you'd have to manually write nested loops to print out the data, which may involve manually calling accessor methods, manually counting them, perhaps storing intermediate output fragments in temporary buffers, encapsulating all this jazz in a throwaway function so that you can use it at multiple strategic points (in D you just copy-n-paste the single line above), etc.. Pure lose. T In C++, I usually use copy/transform: *std::copy(begin(), end(), std::ostream_iterator(std::cout, "\n")) = "\n"; or *std::tranform(begin(), end(), std::ostream_iterator(std::cout, "\n"), [](???){???}) = "\n"; It's a bit verbose, and looks like ass to the non-initiated, but once you are used to it, it's quite convenient. It's just something that grows on you. You can stack on a "foreach" if you need more "depth". foreach(begin(), end(), [](R& r){ *std::copy(r.begin(), r.end(), std::ostream_iterator(std::cout, "\n")) = "\n"; }); Though arguably, that's just a loop in disguise :)
does there exist a dimensional analysis library for D?
something similar to boost/units?
Does __gshared have shared semantics?
In other words, is 'shared __gshared' redundant?
Re: Does __gshared have shared semantics?
On Saturday, 14 June 2014 at 01:24:05 UTC, Mike Franklin wrote: In other words, is 'shared __gshared' redundant? All __gshared does is makes the variable not go into thread-local storage, nothing more. Shared does this, as well as modify the type to be shared(T) instead of just T. So yes, it's redundant.
DMD Fails with fPIC error
Hi, I'm new to D and am trying to compile a simple hello world program. I get the following error when compiling it: dmd test.d /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: /opt/dmd-2.065/lib64/libphobos2.a(lifetime_488_4cd.o): relocation R_X86_64_32 against `_D15TypeInfo_Shared7__ClassZ' can not be used when making a shared object; recompile with -fPIC /opt/dmd-2.065/lib64/libphobos2.a: could not read symbols: Bad value collect2: error: ld returned 1 exit status --- errorlevel 1 This error occurs regardless of whether I use the -fPIC option or not. Compiling DMD from source does not change anything. I am using DMD 2.065.0 on Sabayon amd64, compiled from the dlang overlay with gcc (Gentoo Hardened 4.7.3-r1 p1.4, pie-0.5.5) 4.7.3. Thanks in advance.
Casts and @trusted
This seems to work from quick testing, but it has casts in get_ref that I want to avoid. cast(T*) refs[i] is obviously not @safe. cast(T*) _buffer[read].ptr doesn't seem necessary, since _buffer[read] is conceivably a T so _buffer[read].ptr should be a T*. But without it I get "Error: cannot implicitly convert expression (&this._buffer[read]) of type const(char)* to char[5]*" I do want to pass in a preallocated buffer to store some pointers, at least as one get option. I also want to disallow modification to the ring buffer through those pointers. How might I rework things to enable that usage while being @safe? enum TakeStrategy { cyclic, once } alias TS = TakeStrategy; struct StaticRingBuffer(T, size_t cap) { static assert (cap > 1); private T[cap] _buffer; private size_t _index = cap-1; private size_t _fill = 0; @property size_t extra() nothrow const { return cap-fill; } @property size_t index() nothrow const { return _index; } @property size_t fill() nothrow const { return _fill; } @property const ref front() nothrow const { return _buffer[index]; } void put(T ele) pure nothrow { if (index == cap-1) _index = 0; else ++_index; _buffer[index] = ele; if (fill < cap) ++_fill; } void put(T[] eles) pure nothrow { foreach(e; eles) put(e); } @trusted void get_ref(TS strat=TS.cyclic)(size_t n, const(T*)[] refs) const nothrow { assert(refs.length == n); static if (strat==TS.once) size_t numreads = fixNToFill(n); else size_t numreads = n; size_t read = index; foreach(i;0..numreads) { cast(T*) refs[i] = cast(T*) _buffer[read].ptr; if (read == 0) read = fill-1; else --read; } } private size_t fixNToFill(size_t n) const nothrow { return (n > fill) ? fill : n; } }
Re: Casts and @trusted
On 06/13/2014 06:56 PM, Anonymous wrote: > @trusted void get_ref(TS strat=TS.cyclic)(size_t n, const(T*)[] > refs) const nothrow > { [...] > cast(T*) refs[i] = cast(T*) _buffer[read].ptr; The left-hand side violates a promise: The function takes a slice where the elemenst are const. So, the function says that it will not modify the elements. Also, _buffer[read] is an element, not a slice: private T[cap] _buffer; So, there is no .ptr property. However, perhaps my test code fails to demonstrate your problem: auto s = StaticRingBuffer!(int, 10)(); int i; int*[] arr; arr ~= &i; s.get_ref(0, arr); Please show us complete code. :) Ali
Universal Construction Syntax for Pointers?
I thought this was possible, but DMD 2.065 doesn't allow it, saying "no constructor for int": int* p = new int(3); Is something like this planned for the future? I know we can already do: int n = int(3);
Re: does there exist a dimensional analysis library for D?
Hi Vlad, you can try David Nadlinger's std.units: http://klickverbot.at/code/units/std_units.html See the discussion at http://forum.dlang.org/thread/io1vgo$1fnc$1...@digitalmars.com >From what I deemly remember of Boost/units, it's a bit less complete, but far easier to use.
Re: Universal Construction Syntax for Pointers?
On 06/13/2014 10:29 PM, Meta wrote: I thought this was possible, but DMD 2.065 doesn't allow it, saying "no constructor for int": int* p = new int(3); Is something like this planned for the future? I know we can already do: int n = int(3); Those both compile with 2.066 Ali
Re: Universal Construction Syntax for Pointers?
On Saturday, 14 June 2014 at 06:39:56 UTC, Ali Çehreli wrote: On 06/13/2014 10:29 PM, Meta wrote: I thought this was possible, but DMD 2.065 doesn't allow it, saying "no constructor for int": int* p = new int(3); Is something like this planned for the future? I know we can already do: int n = int(3); Those both compile with 2.066 Ali Right, thanks. It's difficult to keep track of what's already released and what's in Git HEAD.