Re: Disabling All Inlining in DMD Debug Builds
On Tuesday, 25 October 2022 at 08:14:26 UTC, Per Nordlöw wrote: On Monday, 24 October 2022 at 20:43:45 UTC, ryuukk_ wrote: I wish we could do ``version(DebugFast | Release)`` Moreover, I've been using, for instance, ```d version(D_Coverage) {} else pragma(inline, true); void foo() {} ``` to get correct coverage inclusion of `foo()`. Is this still neeed? This looks like a workable solution for now. Thanks
Disabling All Inlining in DMD Debug Builds
I use ``` pragma(inline, true) function definition ``` all over my code. And by default, DMD inlines these functions even in debug builds, which normally is great. I have a custom dynamic array container and if the indexing operator overload function wasn't inlined the debug build would have a ~10x slowdown and become un-testable in many ways. What sucks about this is that stepping through the code in a debugger is way worse because the the "step-over" operation no longer works properly. Maybe this is a bug in the PDB output, but trying to step over an inlined function call still takes you into the inlined function body as if it were a step-in. So is there a way to tell DMD to ignore these pragmas in certain builds?
Re: Using getSymbolsByUDA in a static foreach loop
On Thursday, 20 January 2022 at 01:14:51 UTC, Adam Ruppe wrote: On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer wrote: static foreach(member; __traits(allMembers, Manager)) member here is a string, not the member. I prefer to call it memberName. Then you __traits(getMember, Manager, memberName) to actually get the alias you can pass to getAttributes. Thanks, that fixed it. Final working version for anyone who finds this thread: ```d import std.traits; import std.stdio; enum Runnable; struct SubSystem { void run() { writeln("SubSystem ran"); } } struct Manager { @Runnable SubSystem subsystem; void run() { static foreach(memberName; __traits(allMembers, Manager)) { static foreach (attribute; __traits(getAttributes, __traits(getMember, Manager, memberName))) { static if (is(attribute == Runnable)) { __traits(getMember, Manager, memberName).run(); } } } } } void main() { Manager m; m.run(); } ```
Re: Using getSymbolsByUDA in a static foreach loop
On Wednesday, 19 January 2022 at 21:49:12 UTC, Adam D Ruppe wrote: I never use most of std.traits, they just complicate things. Bleh idk, I wouldn't bother with it and loop through the __traits instead. Unless I'm missing something obvious this has to be a DMD bug, because this prints nothing: ```d import std.traits; import std.stdio; enum Runnable; struct SubSystem { void run() { writeln("SubSystem ran"); } } struct Manager { @Runnable SubSystem subsystem; void run() { static foreach(member; __traits(allMembers, Manager)) { static foreach (attribute; __traits(getAttributes, member)) { static if (attribute == Runnable) { __traits(child, Manager, member).run(); } } } } } void main() { Manager m; m.run(); } ``` The `__traits(getAttributes, member)` call always returns an empty tuple. Calling `__traits(getAttributes, Manager.subsystem)` manually works as expected.
Re: Using getSymbolsByUDA in a static foreach loop
On Wednesday, 19 January 2022 at 20:53:29 UTC, Adam D Ruppe wrote: So you want to `__traits(child, system, this).run()` and it should work - the traits child will re-attach a this value. The error is actually coming from trying to use the result of getSymbolsByUDA in the right part of the `static foreach`, not the call to the `run` function. Which was odd to me because I thought it just returned a `AliasSeq`. Here's a link to the erroring code with your traits change: https://run.dlang.io/is/gO84ox
Using getSymbolsByUDA in a static foreach loop
I'm trying to use getSymbolsByUDA in order to loop over all of the members in a struct with a certain UDA, and then call a function on the member. The plan is to use this to avoid looping over an array of function pointers. However, the compiler is giving a strange error and the documentation of getSymbolsByUDA is unhelpful, as there are no practical use-case examples. Here's a very simplified version of my code ```d import std.traits; enum Runnable; struct SubSystem { void run(); } struct Manager { @Runnable SubSystem subsystem; void run() { static foreach(system; getSymbolsByUDA!(Manager, Runnable)) { system.run(); } } } void main() { Manager m; m.run(); } ``` Result: ``` onlineapp.d(16): Error: value of `this` is not known at compile time ``` This seems to me to be the logical way to write this code. What am I missing?
Re: Generating C Headers From D Code
On Thursday, 5 August 2021 at 17:02:33 UTC, Tejas wrote: On Thursday, 5 August 2021 at 16:28:35 UTC, Jack Stouffer wrote: I need to generate plain C99 .h files from a D module's extern(C) declarations, so that I can link a DMD generated .o file with a C code base. Are there any automated tools which do this? I know the compiler has C++ header generation, and there's tons of tools which exist for importing C headers into D code. I'm not aware of anything which goes the other direction. Google wasn't much help either. I also can't find anything... until someone else comes with a better answer, maybe you can do this: Use the ```-H``` compiler flag to generate ```.di``` files. Remove all the ```extern(C)``` decls in the .di files. Rename the file extension from ```.di``` to ```.h``` Technically, it should work. Hopefully someone else knows better. Well, that's disappointing. I suppose everyone just makes there main file a D file when converting C projects so they don't have this problem. Eventually I'll have to write a script which takes .di files and generates .h files, but doing it manually will have to work for now.
Generating C Headers From D Code
I need to generate plain C99 .h files from a D module's extern(C) declarations, so that I can link a DMD generated .o file with a C code base. Are there any automated tools which do this? I know the compiler has C++ header generation, and there's tons of tools which exist for importing C headers into D code. I'm not aware of anything which goes the other direction. Google wasn't much help either.
Re: Auto expiring cache library
On Friday, 27 April 2018 at 09:07:31 UTC, Pasqui23 wrote: I want a library that offers an in-memory data structure,such that I can write,for example: cache.insert(key,value,expiry) and I can retrieve the value with something like cache[key],unless it has passed expiry seconds. Can be done?What library should I use? Memcached
Re: Is there anyway to access LLVM's 128 bit int type for C from LDC?
On Friday, 15 December 2017 at 02:08:12 UTC, Nicholas Wilson wrote: See also https://github.com/d-gamedev-team/gfm/tree/master/integers/gfm/integers Thanks
Re: Is there anyway to access LLVM's 128 bit int type for C from LDC?
On Thursday, 14 December 2017 at 23:33:34 UTC, Nicholas Wilson wrote: On Thursday, 14 December 2017 at 19:47:53 UTC, Jack Stouffer wrote: Clang has __int128. Is there anyway to use this with D with LDC? Not really as a plain type, although there is effort to get [u]cent working. I could have sworn that mir was using InlineIR with it for multiplication. But InlineIR is the only way to get at it. What operation do you need on it? I'm looking to use it to store the coefficient in my precise decimal type when you need more than 9 significant digits. I might just end up translating Boost's multiprecision lib to D if ucent is impossible.
Is there anyway to access LLVM's 128 bit int type for C from LDC?
Clang has __int128. Is there anyway to use this with D with LDC?
Re: Recently added __equal
On Monday, 17 April 2017 at 19:15:06 UTC, Nordlöw wrote: What's the plan for the recent adding __equal overloads at https://github.com/dlang/druntime/pull/1808/files Is it only meant for runtime and phobos to be updated? Or does user-libraries, such as container libraries, need to be updated aswell? __equal is never really mean to be called directly. It's a druntime template that will be used via inserted calls with the complier front end when array comparisons are used.
Re: Is DMD breaking BigInt?
On Friday, 7 April 2017 at 17:06:31 UTC, Russel Winder wrote: Simple Dub build of a Factorial example using Unit-Threaded for testing. Works fine with ldc2 breaks with dmd. Can you post the code your using?
Re: DMD default safety command line switch
On Friday, 10 March 2017 at 01:13:26 UTC, XavierAP wrote: On Friday, 10 March 2017 at 00:48:39 UTC, Jack Stouffer wrote: Don't know the history, but as recently as a week ago Andrei has argued against such behavior has balkanizing the community. What behavior? Anyway my question is answered, thanks :) Changing default behavior which results in incompatible code.
Re: @safe console input?
On Friday, 10 March 2017 at 00:42:35 UTC, XavierAP wrote: On Thursday, 9 March 2017 at 23:55:35 UTC, Adam D. Ruppe wrote: Just wrap it in a @trusted function. I knew this answer already of course ;) but I take it as implying that there is no other way. Actually I really wonder why std.stdio.readln() itself is not flagged @trusted. I wouldn't think such a function skips any buffer bounds checking, even in -release -- having to wait for user input anyway performance is no issue. Its use of __gshared. Making it shared is non trivial.
Re: DMD default safety command line switch
On Thursday, 9 March 2017 at 17:48:04 UTC, XavierAP wrote: Andrei's 2010 book states that the default safety level can be changed from @system to @safe by means of a -safe command line switch, in the case of the DMD compiler. Now I've tried it and it's not recognized. Was this feature remove on purpose? I could imagine that. The default safety keeps being @system, right? PS I've found this old thread... I'm looking for a bit less long answer to read ;) http://forum.dlang.org/thread/hcqb44$1nc9$1...@digitalmars.com Don't know the history, but as recently as a week ago Andrei has argued against such behavior has balkanizing the community.
Re: How to get the name for a Tid
On Wednesday, 23 November 2016 at 21:04:38 UTC, Christian Köstlin wrote: std.concurrency contains the register function to associate a name with a Tid. This is stored internally in an associative array namesByTid. I see no accessors for this. Is there a way to get to the associated names of a Tid? Thanks, Christian looks like there needs to be a Tid overload of std.concurrency.locate https://issues.dlang.org/show_bug.cgi?id=17231
Re: Returning the address of a reference return value in @safe code - 2.072 regression?
On Monday, 20 February 2017 at 20:54:31 UTC, Jack Stouffer wrote: On Monday, 20 February 2017 at 20:49:43 UTC, Johan Engelen wrote: ... Yeah, this is another regression caused by DIP1000. Christ. For the record, the current list of regressions caused by DIP1000 https://issues.dlang.org/show_bug.cgi?id=17213 https://issues.dlang.org/show_bug.cgi?id=17188 https://issues.dlang.org/show_bug.cgi?id=17123 https://issues.dlang.org/show_bug.cgi?id=17117
Re: Returning the address of a reference return value in @safe code - 2.072 regression?
On Monday, 20 February 2017 at 20:49:43 UTC, Johan Engelen wrote: ... Yeah, this is another regression caused by DIP1000. Christ.
Re: Can you read the next line while iterating over byLine?
On Thursday, 2 February 2017 at 18:18:13 UTC, John Doe wrote: Let's say you're trying to parse a file format like: Name http://example.com 123234 Foo Bar http://dlang.org 88 with blocks separated by varying amount of blank lines. - import std.stdio; void main(string[] args){ auto range = File("text.txt").byLine(); foreach( line; range ){ if (line != ""){ writeln(line); // char[] url = range.??? // char[] num = range.??? } } } - How can you read the next line while iterating over a file line by line, so that the next iteration uses the line after next? If this isn't possible byLine is a design flaw and D should instead provide a regular readLine function. btw: What is this? A forum for a programming language that doesn't support code blocks? If you understand the underlying range interface, the answer becomes clear: import std.stdio; void main(string[] args) { auto range = File("text.txt").byLineCopy(); foreach (line; range) { if (line != "") { writeln(line); range.popFront; char[] url = range.front(); range.popFront; char[] num = range.front(); } } }
Re: Compile to C?
On Saturday, 21 January 2017 at 18:38:22 UTC, Nestor wrote: Hi friends, Is there a way to "compile" d code to C, similar to what nim does? That would be cool for greater portability. No, and this is actually a terrible idea. See https://forum.dlang.org/post/n1vbos$11ov$1...@digitalmars.com
Re: Changing template parameters
On Monday, 16 January 2017 at 15:32:33 UTC, Dlearner wrote: Hey, quick question! I'm messing around with std.random and noticed that you can change the boundaries parameter to be either open or closed intervals on either side. By default it is "[)". How do I change these template parameters? Same way you use any template parameters, auto i = uniform!("(]")(0, 1000);
Re: std.container.array.Array is not @nogc?
On Sunday, 15 January 2017 at 13:08:52 UTC, drug007 wrote: Thanks for answer. Looking forward for your PR. https://github.com/dlang/phobos/pull/5036
Re: std.container.array.Array is not @nogc?
On Sunday, 15 January 2017 at 11:47:06 UTC, drug007 wrote: Is there a way to use Array in @nogc code: ``` import std.container.array : Array; @nogc: void main(string[ ] args) { Array!int ai; ai ~= 1; assert(ai[0] == 1); } ``` fails: ``` main.d(8): Error: @nogc function 'D main' cannot call non-@nogc function 'std.container.array.Array!int.Array.opOpAssign!("~", int).opOpAssign' main.d(9): Error: @nogc function 'D main' cannot call non-@nogc function 'std.container.array.Array!int.Array.opIndex' ``` am I doing something wrong? No you're not. Array was designed before the @nogc attribute was created, so it wasn't coded with it's requirements in mind. Looking at the code, Array allocates GC memory for exception throwing in some cases. These can and should be changed to asserts. I am writing a PR now to fix this. There doesn't seem to be too many cases to fix.
Re: Why Does Dscanner Warn About a Missing toHash if opEquals is Defined?
On Sunday, 31 July 2016 at 17:48:48 UTC, BLM768 wrote: writeln(n1.hashOf == n2.hashOf); // false = BAD! Ok, yeah that is bad. Next question: what's the fastest hashing implementation that will provide the least collisions? Is there a hash implementation that's perfered for AAs?
Re: Why Does Dscanner Warn About a Missing toHash if opEquals is Defined?
On Sunday, 31 July 2016 at 15:30:15 UTC, LaTeigne wrote: On Sunday, 31 July 2016 at 15:21:01 UTC, Jack Stouffer wrote: Is it really a problem? What are the pitfalls of defining one but not the other? iirc usage in an AA requires both. But D provides a default toHash for every type if it's not defined. I was wondering why not just rely on that version.
Why Does Dscanner Warn About a Missing toHash if opEquals is Defined?
Is it really a problem? What are the pitfalls of defining one but not the other?
Re: shuffle a character array
On Wednesday, 20 July 2016 at 17:31:18 UTC, Ali Çehreli wrote: making it impossible to access randomly making it impossible to access randomly __correctly__, unless you're safely assuming there's only ASCII in your string.
Re: Go’s march to low-latency GC
On Wednesday, 6 July 2016 at 16:58:45 UTC, chmike wrote: In case you missed it https://blog.twitch.tv/gos-march-to-low-latency-gc-a6fa96f06eb7#.emwja62y1 This should have been posted in General.
Re: Build a SysTime from a string
On Wednesday, 6 July 2016 at 15:38:00 UTC, Andrea Fontana wrote: On Wednesday, 6 July 2016 at 14:55:51 UTC, Jonathan M Davis wrote: auto st = SysTime.fromISOExtString("2011-03-02T15:30:00+01:00"); That's perfect. I didn't notice that static method. My fault! Also, if you need to parse other formats: https://github.com/JackStouffer/date-parser#simple-example
Re: Way to use var instead of auto?
On Sunday, 3 July 2016 at 22:00:39 UTC, MMJones wrote: I like the term var better than auto. Is there a way to alias auto? If you're thinking of var as in JS's var, they're not the same thing. Even if you could alias it I would advise against doing something like that; assume your code will be maintained by someone else one day.
Re: Implementing a cache
On Sunday, 3 July 2016 at 17:15:32 UTC, Lodovico Giaretta wrote: To avoid the ~= operator and reallocations of the cache array, you could impose a max number of cache entries, preallocate the array and use it as a circular buffer. Here's a simple ring buffer I use, feel free to take it struct RingBuffer (T, uint buffer_length = 10) { private T[buffer_length] buffer; private int lastIndex; @safe @nogc nothrow pure { this(const T initial_value) { this.lastIndex = 0; reset(initial_value); } void reset(const T value) { for (int i = 0; i < this.buffer.length; ++i) { this.buffer[i] = value; } } void put(const T value) { this.buffer[this.lastIndex] = value; // store the new sample // advance the index and wrap it around this.lastIndex += 1; if (this.lastIndex >= buffer_length) { this.lastIndex = 0; } } auto ref opIndex(size_t n) { return buffer[n]; } auto opSlice() { return buffer[]; } auto opAssign(T[] rhs) in { assert(rhs.length <= buffer.length); } body { reset(); foreach (e; rhs) { put(e); } return this; } } }
Re: Fibers under the hood
On Thursday, 9 June 2016 at 16:13:21 UTC, Jonathan Marler wrote: I don't see that documentation anywhere on that page. https://issues.dlang.org/show_bug.cgi?id=16148
Re: std.conv.parse not accepting ByCodeUnitImpl
On Wednesday, 25 May 2016 at 18:43:05 UTC, Steven Schveighoffer wrote: If parse can do it, to should as well. I think it's a question of how the template constraints are done. Please file an issue. Found this: https://issues.dlang.org/show_bug.cgi?id=15800
Re: std.conv.parse not accepting ByCodeUnitImpl
On Wednesday, 25 May 2016 at 16:53:30 UTC, Steven Schveighoffer wrote: to should work wherever parse works (in fact, whenever you call to!someType(someString), I believe it just forwards to parse). This is not the case; to doesn't work with ranges: auto str = "1234567".byCodeUnit; auto result = parse!int(str); auto result2 = to!int(str); // doesn't compile
Re: std.conv.parse not accepting ByCodeUnitImpl
On Wednesday, 25 May 2016 at 15:34:45 UTC, Steven Schveighoffer wrote: parse consumes data from the string as it goes. I know that, I'm asking why. This disallows the natural range chaining and forces you to save to a variable before calling parse even though the function works just as well without it. If you want to leave the data there, use to instead. Can't without calling std.array.array.
Re: std.conv.parse not accepting ByCodeUnitImpl
On Tuesday, 24 May 2016 at 05:01:39 UTC, ag0aep6g wrote: You're missing that `parse`'s parameter is `ref`. Do you what the rationale behind this is? I just removed the ref from the floating point from input range overload and it works fine for strings.
Re: std.conv.parse not accepting ByCodeUnitImpl
On Tuesday, 24 May 2016 at 05:01:39 UTC, ag0aep6g wrote: You're missing that `parse`'s parameter is `ref`. `splitValue.front` is not an lvalue, so it can't be passed in a ref parameter. This works: auto f = splitValue.front; parse!int(f); Thanks. DMD desperately needs better error messages :/
std.conv.parse not accepting ByCodeUnitImpl
Consider the following code - import std.range; import std.conv; import std.utf; import std.algorithm; auto test(R)(R s) { auto value = s.byCodeUnit; auto splitValue = value.splitter('.'); parse!int(splitValue.front); } void main() { test("1.8"); } - This fails to compile and I can't for the life of me understand why. The std.conv.parse call doesn't match any parse overload when it should match the second one: - std.conv.parse(Target, Source)(ref Source s) if ( isSomeChar!(ElementType!Source) && isIntegral!Target && !is(Target == enum)) - Manually verifying the template constraints proves that it should work, - pragma(msg, isSomeChar!(ElementType!(typeof(splitValue.front))), isIntegral!int, !is(int == enum)); truetruetrue - Any help here would be appreciated.
Re: missing data with parallel and stdin
On Monday, 23 May 2016 at 08:59:31 UTC, moechofe wrote: void delegate(string source,string dest) handler; if(use_symlink) handler = delegate(string s,string d){ symlink(s,d); }; else handler = delegate(string s,string d){ copy(s,d); }; Boy that's a confusing way to write that. Here's a clearer version if(use_symlink) handler = delegate(string s,string d){ symlink(s,d); }; else handler = delegate(string s,string d){ copy(s,d); }; What did I do wrong? Sounds like a data race problem. Use a lock on the file write operation and see if that helps.
Re: Small-Size-Optimized Array
On Monday, 16 May 2016 at 11:05:40 UTC, Nordlöw wrote: Does Phobos contain any standard small-size-optimized (SSO) array that starts with a stack array and union-converts into a standard builtin D-array when grown beyond the size of the stack array? No. If not has anybody put together one? Not that I know of. Grapheme has small string optimized code in it though.
Re: char array weirdness
On Thursday, 31 March 2016 at 12:49:57 UTC, ag0aep6g wrote: I get theses timings then: auto-decoding 642 ms, 969 μs, and 1 hnsec byCodeUnit 84 ms, 980 μs, and 3 hnsecs And 643 / 85 ≅ 8. Ok, so not as bad as 100x, but still not great by any means. I think I will do some investigation into why array of dchar is so much slower than calling array with char[].
Re: char array weirdness
On Wednesday, 30 March 2016 at 22:49:24 UTC, ag0aep6g wrote: When byCodeUnit takes no time at all, isn't 1µs infinite times slower, instead of 100 times? And I think byCodeUnits's 1µs is so low that noise is going to mess with any ratios you make. It's not that it's taking no time at all, it's just that it's less than 1 hecto-nanosecond, which is the smallest unit that benchmark works with. Observe what happens when the times are no longer averaged, I also made some other changes to the script: import std.datetime; import std.stdio; import std.array; import std.utf; import std.uni; enum testCount = 1_000_000; void test(char[] var) { auto a = var.array; } void test2(char[] var) { auto a = var.byCodeUnit.array; } void test3(char[] var) { auto a = var.byGrapheme.array; } void main() { import std.conv : to; import std.random : uniform; import std.string : assumeUTF; // random string ubyte[] data; foreach (_; 0 .. 200) { data ~= cast(ubyte) uniform(33, 126); } auto result = to!Duration(benchmark!(() => test(data.assumeUTF))(testCount)[0]); auto result2 = to!Duration(benchmark!(() => test2(data.assumeUTF))(testCount)[0]); auto result3 = to!Duration(benchmark!(() => test3(data.assumeUTF))(testCount)[0]); writeln("auto-decoding", "\t\t", result); writeln("byCodeUnit", "\t\t", result2); writeln("byGrapheme", "\t\t", result3); } $ ldc2 -O3 -release -boundscheck=off test.d $ ./test auto-decoding 1 sec, 757 ms, and 946 μs byCodeUnit 87 ms, 731 μs, and 8 hnsecs byGrapheme 14 secs, 769 ms, 796 μs, and 6 hnsecs
Re: char array weirdness
On Wednesday, 30 March 2016 at 05:16:04 UTC, H. S. Teoh wrote: If we didn't have autodecoding, would be a simple matter of searching for sentinel substrings. This also indicates that most of the work done by autodecoding is unnecessary -- it's wasted work since most of the string data is treated opaquely anyway. Just to drive this point home, I made a very simple benchmark. Iterating over code points when you don't need to is 100x slower than iterating over code units. import std.datetime; import std.stdio; import std.array; import std.utf; import std.uni; enum testCount = 1_000_000; enum var = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent justo ante, vehicula in felis vitae, finibus tincidunt dolor. Fusce sagittis."; void test() { auto a = var.array; } void test2() { auto a = var.byCodeUnit.array; } void test3() { auto a = var.byGrapheme.array; } void main() { import std.conv : to; auto r = benchmark!(test, test2, test3)(testCount); auto result = to!Duration(r[0] / testCount); auto result2 = to!Duration(r[1] / testCount); auto result3 = to!Duration(r[2] / testCount); writeln("auto-decoding", "\t\t", result); writeln("byCodeUnit", "\t\t", result2); writeln("byGrapheme", "\t\t", result3); } $ ldc2 -O3 -release -boundscheck=off test.d $ ./test auto-decoding 1 μs byCodeUnit 0 hnsecs byGrapheme 11 μs
Re: char array weirdness
On Tuesday, 29 March 2016 at 23:42:07 UTC, H. S. Teoh wrote: Believe it or not, it was only last year (IIRC, maybe the year before) that Walter "discovered" that Phobos does autodecoding, and got pretty upset over it. If even Walter wasn't aware of this for that long... The link (I think this is what you're referring to) to that discussion: http://forum.dlang.org/post/lfbg06$30kh$1...@digitalmars.com It's a shame Walter never got his way. Special casing ranges like this is a huge mistake.
Re: char array weirdness
On Tuesday, 29 March 2016 at 23:15:26 UTC, Basile B. wrote: I've seen you so many time as a reviewer on dlang that I belive this Q is a joke. Even if obviously nobody can know everything... https://www.youtube.com/watch?v=l97MxTx0nzs seriously you didn't know that auto decoding is on and that it gives you a dchar... It's not a joke. This is the first time I've run into this problem in my code. I just started using D more and more in my work and I've never written anything that was really string heavy.
Re: char array weirdness
On Monday, 28 March 2016 at 23:07:22 UTC, Jonathan M Davis wrote: ... Thanks for the detailed responses. I think I'll compile this info and put it in a blog post so people can just point to it when someone else is confused.
Re: char array weirdness
On Monday, 28 March 2016 at 22:43:26 UTC, Anon wrote: On Monday, 28 March 2016 at 22:34:31 UTC, Jack Stouffer wrote: void main () { import std.range.primitives; char[] val = ['1', '0', 'h', '3', '6', 'm', '2', '8', 's']; pragma(msg, ElementEncodingType!(typeof(val))); pragma(msg, typeof(val.front)); } prints char dchar Why? Unicode! `char` is UTF-8, which means a character can be from 1 to 4 bytes. val.front gives a `dchar` (UTF-32), consuming those bytes and giving you a sensible value. But the value fits into a char; a dchar is a waste of space. Why on Earth would a different type be given for the front value than the type of the elements themselves?
char array weirdness
void main () { import std.range.primitives; char[] val = ['1', '0', 'h', '3', '6', 'm', '2', '8', 's']; pragma(msg, ElementEncodingType!(typeof(val))); pragma(msg, typeof(val.front)); } prints char dchar Why?
Compiler Specific dub Dependencies
Is there any way in dub to specify that a module should only be linked and compiled for DMD and not for LDC? I am using the Economic Modeling containers library, and because it uses std.experimental.allocator, it can't be used with LDC through dub. I have coded in such a way with static if's that LDC will still compile without it, but dub will try to compile it anyway because it's in the dependencies JSON dictionary.
Empty Associative Aarray Literal
I want to have one of the parameters on a function be optional. The problem is, is that it's a AA and D does not seem to support empty AA literals. Observe: string func(int a, int[int] b = []) { return "mem1"; } void main() { func(1); } $ dmd test test.d(8): Error: cannot implicitly convert expression ([]) of type void[] to int[int] This doesn't work either string func(int a, int[int] b = int[int].init) { return "mem1"; } void main() { func(1); }
Re: Member Access Based On A Runtime String
On Tuesday, 1 March 2016 at 08:53:20 UTC, Adrian Matoga wrote: struct Foo { string foo = "dog"; int bar = 42; int baz = 31337; } void set(P, T)(ref P p, string name, auto ref T value) { foreach (mem; __traits(allMembers, P)) { static if (is(typeof(__traits(getMember, p, mem)) Q)) { static if (is(Q : T)) { if (mem == name) { __traits(getMember, p, mem) = value; return; } } } } assert(0, P.stringof ~ " has no member " ~ name); } unittest { Foo foo; foo.set("bar", 15); assert(foo.bar == 15); foo.set("foo", "cat"); assert(foo.foo == "cat"); } Thanks. This should be in Phobos
Member Access Based On A Runtime String
In Python, I can do this: my_obj = Obj() string_from_func = func() setattr(my_obj, string_from_func, 100) Say func() returns "member1" or "member2", the setattr would then set either one of those to 100. Is there any equivalent in D?
Re: Simple performance question from a newcomer
On Sunday, 21 February 2016 at 14:32:15 UTC, dextorious wrote: Now, seeing as how my experience writing D is literally a few hours, is there anything I did blatantly wrong? Did I miss any optimizations? Most importantly, can the elegant operator chaining style be generally made as fast as the explicit loops we've all been writing for decades? First off, you should really be using GDC or LDC if you want speed. On how to do that, see my blog post about here: http://jackstouffer.com/blog/nd_slice.html. Specifically the section titled "Getting Hands On". Secondly, both of your other sum examples use naive element by element summation rather than the more accurate pairwise summation which sum uses with random access floating point ranges. So your not really comparing apples to apples here. Since Phobos' pairwise summation is recursive, it's very likely that DMD isn't doing all the optimizations that LDC or GDC can, such as inlining or tail call optimizations. I haven't compiled your code so I can't check myself. Also, templates are auto attributed, so there's no reason to include @safe nothrow, etc. on templated functions.
Re: ndslice of an array structure member?
On Monday, 21 December 2015 at 23:59:07 UTC, Jay Norwood wrote: I'm trying to learn ndslice. It puzzles me why t3 compiles ok, but t4 causes a compiler error in the example below. Should I be able to slice a struct member that is an array? import std.stdio; import std.experimental.ndslice; import std.experimental.ndslice.iteration: transposed; struct sample{ ulong [10] core_ctr; } struct block{ ulong[60] samples; } void main() { auto a1 = new sample[60]; auto t3 = a1.sliced!(ReplaceArrayWithPointer.no)(3,4,5); auto b1 = new block; auto t4 = b1.samples.sliced!(ReplaceArrayWithPointer.no)(3,4,5); } The problem is that t3 is slicing a1 which is a dynamic array, which is a range, while t4 is trying to slice a static array, which is not a range. The ranges primitive popFront mutates the length of the range, so static arrays cannot be used as ranges. But, if you take a slice of b1.samples, you can use that as a range. auto t4 = b1.samples[].sliced!(ReplaceArrayWithPointer.no)(3,4,5); See the section on ranges on this page for more general info on ranges: http://dlang.org/overview.html
Re: ndslice and limits of debug info and autocompletion
On Tuesday, 22 December 2015 at 00:21:16 UTC, Jay Norwood wrote: import std.experimental.ndslice.iteration: transposed; I don't use visualD so I can't help you there, but I wanted to point out that this import is unnecessary.
Re: isBidirectionalRange fails for unknown reasons
On Wednesday, 16 December 2015 at 21:40:44 UTC, anonymous wrote: The `.save` primitive of forward ranges must return the very same type that the range has. But your ReferenceBidirectionalRange!T.save returns a ReferenceForwardRange!T, because it's inherited. That makes isForwardRange!(ReferenceBidirectionalRange!T) fail, and everything that depends on it. You can override `save` in ReferenceBidirectionalRange or try something clever like using a template this parameter: @property auto save(this This)() {return new This( _payload);} Thanks! That did the trick.
Re: isBidirectionalRange fails for unknown reasons
On Wednesday, 16 December 2015 at 20:43:02 UTC, Jack Stouffer wrote: unittest { static assert(isInputRange!(ReferenceInputRange!int)); // works static assert(isForwardRange!(ReferenceForwardRange!int)); // works static assert(isBidirectionalRange!(ReferenceBidirectionalRange!int)); //fails } Also, this works just fine = unittest { auto a = new ReferenceBidirectionalRange!int([1,2]); a.popBack(); a.back.writeln; // prints 1 }
isBidirectionalRange fails for unknown reasons
I'm trying to add a ReferenceBidirectionalRange range type to std.internal.test.dummyrange so I can test some range code I'm writing, but I've hit a wall and I'm not sure why. For some reason, the isBidirectionalRange check fails even though back and popBack are present. Any help here would be appreciated. the code: import std.range; class ReferenceInputRange(T) { import std.array : array; this(Range)(Range r) if (isInputRange!Range) { _payload = array(r); } final @property ref T front(){ return _payload.front; } final void popFront(){ _payload.popFront(); } final @property bool empty(){ return _payload.empty; } protected T[] _payload; } class ReferenceForwardRange(T) : ReferenceInputRange!T { this(Range)(Range r) if (isInputRange!Range) { super(r); } final @property ReferenceForwardRange save() {return new ReferenceForwardRange!T( _payload); } } class ReferenceBidirectionalRange(T) : ReferenceForwardRange!T { this(Range)(Range r) if (isInputRange!Range) { super(r); } final @property ref T back(){ return _payload.back; } final void popBack(){ _payload.popBack(); } } unittest { static assert(isInputRange!(ReferenceInputRange!int)); // works static assert(isForwardRange!(ReferenceForwardRange!int)); // works static assert(isBidirectionalRange!(ReferenceBidirectionalRange!int)); //fails }
Re: Regression?
On Wednesday, 9 September 2015 at 01:35:26 UTC, Sebastiaan Koppe wrote: Thanks for your advice. But that is not what I asked for. The question was, why doesn't this work anymore with the latest (2.068.0 and 2.068.1) compiler: ``` auto ls = File("../languages.json","r").byLineCopy().joiner.parseJSON(); ``` It should. Right? https://issues.dlang.org/show_bug.cgi?id=15423
Re: Regression?
On Wednesday, 9 September 2015 at 01:35:26 UTC, Sebastiaan Koppe wrote: Thanks for your advice. But that is not what I asked for. The question was, why doesn't this work anymore with the latest (2.068.0 and 2.068.1) compiler: ``` auto ls = File("../languages.json","r").byLineCopy().joiner.parseJSON(); ``` It should. Right? I just ran into this as well. This seems like a regression.
Re: Purity of std.conv.to!string
On Saturday, 26 September 2015 at 17:08:00 UTC, Nordlöw wrote: Why is the following code not pure: float x = 3.14; import std.conv : to; auto y = x.to!string; ??? Is there a reason for it not being pure? If not, this is a serious problem as this is such a fundamental function. Please make an issue on https://issues.dlang.org and I'll take a look a this later. Most of the functions in std.conv are templated so it must be some internal function that's not properly annotated, or it's using manual memory management.
Re: Why are static arrays not ranges?
On Monday, 21 September 2015 at 20:39:55 UTC, Jesse Phillips wrote: A static array has a constant length, so it is not possible to popFront on a static array. Making a dynamic array from it is easy, just slice it with []: pragma(msg, isInputRange!(typeof(a[]))); pragma(msg, isForwardRange!(typeof(a[]))); pragma(msg, isRandomAccessRange!(typeof(a[]))); Thanks for all of the replies. I was under the impression that the slicer allocated GC, but some tests show that's not true.
Why are static arrays not ranges?
import std.range; void main() { int[6] a = [1, 2, 3, 4, 5, 6]; pragma(msg, isInputRange!(typeof(a))); pragma(msg, isForwardRange!(typeof(a))); pragma(msg, isRandomAccessRange!(typeof(a))); } $ dmd -run test.d false false false That's ridiculous. Do I have to wrap my static arrays in structs to get range primitives? Is there an actual reason for this?
Re: OS minimum version
On Monday, 21 September 2015 at 12:47:39 UTC, ponce wrote: 3. What is the minimum OS X version required by programs created with LDC? Tiger x86 version, I believe.
Re: Why is sort allocating in this case?
On Friday, 18 September 2015 at 02:29:55 UTC, Jack Stouffer wrote: On Friday, 18 September 2015 at 02:24:44 UTC, Adam D. Ruppe wrote: Works for me. What version are you using? Might be the old one wasn't actually marked nogc yet. I'm using the git head, must be a regression. Well apparently it's not, as I just used digger to check, and the digger version of dmd compiles it just fine. I'm not quite sure how a mis-build or something like that would manifest itself as a @nogc error though.
Re: Why is sort allocating in this case?
On Friday, 18 September 2015 at 02:24:44 UTC, Adam D. Ruppe wrote: Works for me. What version are you using? Might be the old one wasn't actually marked nogc yet. I'm using the git head, must be a regression.
Why is sort allocating in this case?
The docs explicitly say that SwapStrategy.unstable is non-allocating, but this code (which is for finding the statistical mode of a range) will fail to compile. auto mode(alias pred = "a == b", R)(R r) @nogc if (is(ElementType!R : real) && isInputRange!R && !isInfinite!R) { import core.stdc.stdlib : malloc; import std.algorithm.iteration : group; import std.algorithm.sorting : sort, SwapStrategy; import std.algorithm.mutation : copy; import std.typecons : Tuple; alias LT = Tuple!(Unqual!(ElementType!R), size_t); if (r.empty) { return real.nan; } auto grouping = r.group!pred; // Because the struct Group does not have swappable elements, it cannot be // sorted, so copy it to another array auto buffer = (cast(LT*) malloc(r.length * LT.sizeof))[0 .. r.length]; copy(grouping, buffer); sort!("a[1] > b[1]", SwapStrategy.unstable)(buffer); return buffer[0][0]; } $ dmd/src/dmd -unittest test.d test.d(439): Error: @nogc function 'test.mode!("a == b", int[]).mode' cannot call non-@nogc function 'std.algorithm.sorting.sort!("a[1] > b[1]", cast(SwapStrategy)0, Tuple!(int, ulong)[]).sort'
Why isn't int[] automatically convertible to long[]?
pragma(msg, is(int[] : long[])); false Why?
Re: observation: D getting a bit complex
On Sunday, 30 August 2015 at 02:42:30 UTC, Spacen Jasset wrote: immutable(ElementEncodingType!(ElementType!Range))[] buildPath(Range)(Range segments) if (isInputRange!Range && isSomeString!(ElementType!Range)); pure nothrow @safe immutable(C)[] buildPath(C)(const(C)[][] paths...) if (isSomeChar!C); I understand how you feel. When I was learning D, the docs where almost impenetrable because of this. But when I got into some of the more advanced features of D, I found these explicit function signatures invaluable. This essentially tells you that the function takes either a range of strings, or it can take indefinite number of strings as different arguments. Also, examples underneath the function signature help new comers understand how to call the function without having to parse it.
GDB for D debugging on OS X seems to be broken
For reference: OSX 10.10.5 GDB 7.9.1 (non apple; from homebrew) yes, it is code signed Compiling with dub: "dflags": ["-gc", "-gs"] I would also like to preface this post by saying that everything works fine in GDB on linux. When finding that a bug in my program was a null pointer bug, I decided to drop into GDB to try to figure out what was happening. But I quickly realized that trying to set a breakpoint in a file other than the one where the main function is, and stepping into functions in a file other than the one where the main function is, don't work. GDB will return something like: Cannot insert breakpoint 2. Cannot access memory at address 0x9bc06 when trying to insert a breakpoint in another file. GDB also treats the aforementioned step command as a continue because it can't read the file where the function is defined. Nothing changes when running the command as sudo either. Two more pain points: `info locals` doesn't work. It responds with "No symbol table info available." And `info variables` returns the mangled D names for variables and not their real name, despite the language being set to D and doing `demangle [some_name]` returns the correct names.
Re: How do I find the actual types of the elements in a list of classes?
On Friday, 14 August 2015 at 00:06:33 UTC, Adam D. Ruppe wrote: On Thursday, 13 August 2015 at 23:48:08 UTC, Jack Stouffer wrote: In my code, the list can have 20-30 different types of classes in it all inheriting from the same interface, and it doesn't make sense for all of those classes to implement a method that is very specific to one of the classes. I don't want to get too far into this since I haven't seen your code, but the function that uses this list might itself be a candidate for addition to the interface, or a second interface with that method that all the classes also inherit from (remember you can only inherit from one class in D, but you can implement as many interfaces as you want). The code in question is a collision resolver in a 2D game that I am making. The list is a list of all of the drawable objects that the object could be colliding with. After collision is checked on each of the possible collisions, the object is placed at the last position where it was not colliding. I am using the cast in the enemy resolver where each collision is then checked to see if the collision was with the player, and if it was, the player is then given damage. - class Blob : Enemy { ... final override void resolveCollisions() { import player : Player; //check for collision Entity[] possible_collisions = this.state_object.getPossibleCollisions(this); Entity[] collisions = []; foreach (ref entity; possible_collisions) { // discount any Rect that is equal to the player's, as it's probably // the players bounding box if (this.boundingBox != entity.boundingBox && this.boundingBox.intersects(entity.boundingBox)) { collisions ~= entity; } } if (collisions.length > 0) { // If we collided with something, then put position back to its // original spot this.position = this.previous_position; // If we collided with the player, give the player damage foreach (collision; collisions) { // Check to see if the object collided was a player by testing the // result of the cast, which will return null if unsuccessful if (auto player = cast(Player) collision) { player.damagePlayer(5, this.position, this.mass); } } } } }
Re: How do I find the actual types of the elements in a list of classes?
On Thursday, 13 August 2015 at 22:49:15 UTC, Adam D. Ruppe wrote: On Thursday, 13 August 2015 at 21:42:54 UTC, Jack Stouffer wrote: dynamically calling different methods on each object in the list based on its type. The cleanest OO way of doing that is to put the methods you need in the interface and always call it through that. Then there's no need to cast and each child class can implement it their own way. This really doesn't make sense in the context that I am using this code in. The above code is a very reduced test case. In my code, the list can have 20-30 different types of classes in it all inheriting from the same interface, and it doesn't make sense for all of those classes to implement a method that is very specific to one of the classes.
Re: How do I find the actual types of the elements in a list of classes?
On Thursday, 13 August 2015 at 22:20:35 UTC, Justin Whear wrote: foreach (item; parent_list) { if (auto asA = cast(A)item) { asA.method(); } else if (auto asB = cast(B)item) { asB.method2(); } } On Thursday, 13 August 2015 at 22:20:35 UTC, Justin Whear wrote: Thanks Justin and rumbu, that makes the code a lot more readable.
Re: How do I find the actual types of the elements in a list of classes?
On Thursday, 13 August 2015 at 20:28:33 UTC, Adam D. Ruppe wrote: On Thursday, 13 August 2015 at 20:23:56 UTC, Jack Stouffer wrote: As far as I can tell, there is no way to know the actual type of each of the objects in the list to be able to print: Cast it to Object first, then do the typeid and it will get the dynamic class type. Since Parent is an interface, typeid works differently. I wrote about this in more detail recently here: http://stackoverflow.com/questions/31563999/how-to-get-classinfo-of-object-declared-as-an-interface-type/31564253#31564253 Thanks, that worked, and based on your answer, I was able to fix my real problem: dynamically calling different methods on each object in the list based on its type. So, using the above code as an example, I am able to call method if the object is of type A and method2 if the object is of type B: interface Parent { void method(); } class A : Parent { void method() {} this() {} } class B : Parent { void method() {} void method2() {} this() {} } void main() { import std.stdio; import std.string; Parent[] parent_list = []; parent_list ~= new A(); parent_list ~= new B(); foreach (item; parent_list) { string class_name = (cast(Object) item).classinfo.name; if (class_name == "test.A") { (cast(A) item).method(); } else if (class_name == "test.B") { (cast(B) item).method2(); } } } This is a dirty hack, but I don't care, it works :)
How do I find the actual types of the elements in a list of classes?
Given: interface Parent { void method(); } class A : Parent { void method() {} this() {} } class B : Parent { void method() {} void method2() {} this() {} } void main() { import std.stdio; Parent[] parent_list = []; parent_list ~= new A(); parent_list ~= new B(); foreach (item; parent_list) { writeln(typeid(item)); } } With 2.068, it will output: test.Parent test.Parent As far as I can tell, there is no way to know the actual type of each of the objects in the list to be able to print: test.A test.B Are there any workarounds for this? Also, this fails to compile when it doesn't look like it should: interface Parent { void method(); } class A : Parent { void method() {} this() {} } class B : Parent { void method() {} void method2() {} this() {} } void main() { import std.stdio; Parent[] parent_list = [new A(), new B()]; foreach (item; parent_list) { writeln(typeid(item)); } } Thanks.
Re: Can't Compile Global Semaphores?
On Monday, 27 July 2015 at 20:12:10 UTC, John Colvin wrote: Yes, but then core.sync.semaphore doesn't support being shared, so... Ok, so I made the code run by using __gshared instead of shared. It seems really odd that a semaphore object doesn't support being shared, this that a bug? Here is the modified code: import core.sync.semaphore; import core.thread; import std.string; import std.stdio; __gshared string data; __gshared Semaphore sem; void read() { data = "From Thread"; sem.notify(); } void write() { sem.wait(); data.writeln; } void main() { sem = new Semaphore(); Thread reader = new Thread(&read); Thread writer = new Thread(&write); reader.start(); writer.start(); }
Can't Compile Global Semaphores?
Hi, I am currently working through a book on the fundamentals of computer concurrency and I wanted to do all of the exercises in D. But I ran into a problem when I tried to have a global semaphore: /usr/local/Cellar/dmd/2.067.1/include/d2/core/sync/semaphore.di(35): Error: constructor core.sync.semaphore.Semaphore.this core.sync.semaphore.Semaphore cannot be constructed at compile time, because the constructor has no available source code Here is my code: import core.sync.semaphore; import core.thread; import std.string; import std.stdio; shared string data; shared Semaphore sem = new Semaphore(); void read() { data = "From Thread"; sem.notify(); } void write() { sem.wait(); data.writeln; } void main() { Thread reader = new Thread(&read); Thread writer = new Thread(&write); reader.start(); writer.start(); }
Re: Why aren't Ranges Interfaces?
On Friday, 26 June 2015 at 19:40:41 UTC, rsw0x wrote: On Friday, 26 June 2015 at 19:26:57 UTC, Jack Stouffer wrote: Thanks for the reply! I understand the reasoning now. On Friday, 26 June 2015 at 18:46:03 UTC, Adam D. Ruppe wrote: 2) interfaces have an associated runtime cost, which ranges wanted to avoid. They come with hidden function pointers and if you actually use it through them, you can get a performance hit. How much of a performance hit are we talking about? Is the difference between using an interface and not using one noticeable? It can be in a tight loop. http://eli.thegreenplace.net/2013/12/05/the-cost-of-dynamic-virtual-calls-vs-static-crtp-dispatch-in-c this is for C++, but it applies directly to D. Interestingly, CRTP is a gigantic C++ hack that D gets for free with alias this. In my code I need to use polymorphism. But, if I replace the code for my interface inheritance with an inherit of an class that implements empty methods and my methods just override the empty ones I get an essentially free performance boost 0_0? Good to know; thanks for the link.
Re: Why aren't Ranges Interfaces?
Thanks for the reply! I understand the reasoning now. On Friday, 26 June 2015 at 18:46:03 UTC, Adam D. Ruppe wrote: 2) interfaces have an associated runtime cost, which ranges wanted to avoid. They come with hidden function pointers and if you actually use it through them, you can get a performance hit. How much of a performance hit are we talking about? Is the difference between using an interface and not using one noticeable?
Why aren't Ranges Interfaces?
I have been learning D over the past three weeks and I came to the chapter in "Programming in D" on Ranges. And I am a little confused on the choice to make Ranges based on the methods you have in the struct, but not use a interface. With all of the isInputRange!R you have to write everywhere, it just seems like it would have made a lot more sense and made everyone's jobs easier if the different types of Ranges where just interfaces that you could inherit from. The only reason I can think of to not do it this way is the weird distinction between structs and classes in D.