Re: Why does not my program is not running?
On Thursday 20 August 2015 23:11, anonymous wrote: 2) *integer++ doesn't do what you think it does. The increment is done before the dereference. You could fix this, but: I got that one wrong. Steven Schveighoffer has it right. The pointer is incremented after the currently pointed-to value is returned. Still not what was expected, of course.
Re: How to provide this arg or functor for algorithm?
On Sunday, 16 August 2015 at 23:05:42 UTC, Ali Çehreli wrote: // Now the type of d is a template parameter @nogc auto func(Func)(uint[] arr, Func d) { return arr.map!(d); } Huh. I think func being a template is the key here. When the original code is put in a template, it works too (with 2.068): void func()() @nogc { import std.algorithm; uint[3] arr = [1,2,3]; uint context = 2; auto r = arr[].map!(delegate(value) { return value * context; }); } void main() { func(); }
Re: std.net.curl
On Monday, 17 August 2015 at 13:13:48 UTC, anonymous wrote: and figured out that the linker is invoked (on my machine) with gcc a.o -o a -m64 -lcurl -L/usr/lib/x86_64-linux-gnu -Xlinker correct (I named the example programm a.d instead of app.d): gcc app.o -o app -m64 -lcurl -L/usr/lib/x86_64-linux-gnu -Xlinker This issue is already known: https://issues.dlang.org/show_bug.cgi?id=12572 and https://issues.dlang.org/show_bug.cgi?id=7044
Re: How to provide this arg or functor for algorithm?
On Monday, 17 August 2015 at 10:28:33 UTC, thedeemon wrote: Nope, it works only because r is unreferenced and gets thrown out. Just try using r.front there, for example, and the error returns. You're right, it falls short. But I think r not being referenced is not exactly it. Using front in Ali's func breaks it in the same way. And returning r from func works. Wait, returning r from func works? Yes: auto func()(uint[] arr, uint context) @nogc { import std.algorithm; auto r = arr[].map!(delegate(value) { return value * context; }); return r; } void main() @nogc { uint[3] arr = [1,2,3]; uint context = 2; auto r = func(arr[], context); import std.algorithm: equal; import std.range: only; assert(equal(r, only(2, 4, 6))); } Is that supposed to compile? A closure is needed for the delegate, isn't it? With @nogc, where is the closure stored? This looks like an accepts-invalid bug to me. It doesn't compile when func is not a template. So maybe the check is broken for templates. It also doesn't compile with 2.067, so this may be a regression. Coming back to Ali's code, here's a version that shows that func doesn't need template parameters, but it needs to be a template: import std.stdio; import std.algorithm; struct Caller { uint method(uint value) pure @nogc { return _context * value; } uint _context; } auto func()(uint[] arr, uint delegate(uint) pure @nogc d) @nogc { return arr.map!(d); } void main() @nogc { uint[3] arr = [1,2,3]; uint context = 2; auto c = Caller(context); auto d = c.method; auto r = func(arr[], d); import std.algorithm: equal; import std.range: only; assert(equal(r, only(2, 4, 6))); } I think this relies on the same discrepancy as the problematic code above.
Re: std.net.curl
On Monday, 17 August 2015 at 12:58:54 UTC, Adam D. Ruppe wrote: On Monday, 17 August 2015 at 12:52:37 UTC, tired_eyes wrote: Hovewer, dmd app.d spits a whole bunch of strange error messages: try dmd -lcurl app.d and see if that helps. DMD does not accept -lcurl. From dmd --help: -Llinkerflag pass linkerflag to link ergo dmd -L-lcurl app.d on my machine (64Bit linux mint 17.2 with libcurl4-openssl-dev installed) -L-lcurl reduces the number of linker errors but the example still fails. I run dmd -c app.d dmd -L-lcurl app.o -v and figured out that the linker is invoked (on my machine) with gcc a.o -o a -m64 -lcurl -L/usr/lib/x86_64-linux-gnu -Xlinker --export-dynamic -l:libphobos2.a -lpthread -lm -lrt If I change the order of the libraries (move -lcurl to the end), it links. Used commands: dmd -c app.d gcc app.o -o app -m64 -L/usr/lib/x86_64-linux-gnu -Xlinker --export-dynamic -l:libphobos2.a -lpthread -lm -lrt -lcurl (the later may be different on OpenSUSE (?) - better check with dmd -v ...)
Re: How to provide this arg or functor for algorithm?
On Monday, 17 August 2015 at 16:21:16 UTC, thedeemon wrote: On Monday, 17 August 2015 at 16:18:50 UTC, thedeemon wrote: I've just checked with my runtime GC hook. Here the call to func() allocates 12 bytes via gc_malloc, and it's the same for a 4-elements array, so it's not for the array itself, it's for a closure, I think. Also, compiling with -vgc says nothing, compiler (2.068) seems to miss this allocation. Thanks for confirming. It seems to be a known issue that the compiler doesn't recognize the @nogc violation by the closure: https://issues.dlang.org/show_bug.cgi?id=14771 That's not a regression, though. 2.067 rejecting the code has something to do with this assert: https://github.com/D-Programming-Language/phobos/blob/v2.067.1/std/algorithm/iteration.d#L453 (code is the same for 2.068). I don't know if that assert should trigger a @nogc violation or not. But anyway, the real issue is 14771, as far as I can tell.
Re: 2.068 Regression in EnumMembers?
On Sunday, 16 August 2015 at 11:25:48 UTC, Nordlöw wrote: I tried rebuilding my knowledge graph project at https://github.com/nordlow/justd/tree/master/knet with DMD 2.068 and it seems like we have a regression in std.traits: EnumMembers: [...] It builds without errors nor warnings on 2.067. Help, please. Did it still work in 2.068a ? If so then it's possible that the resolution of issue 14844, which changed the traits allMembers, is the cause. Because if you look at std.traits 'blame' on GH (https://github.com/D-Programming-Language/phobos/blame/master/std/traits.d , around line 3412) that's clear that the template EnumMembers hasn't changed since February 2014. So it must be one of the call inside... Just an idea.
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 19:50:56 UTC, Temtaime wrote: There's a problem with « dst[0 .. n] = val; ». It should be « dst[0 .. n][] = val; » No, you don't need the `[]`.
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 18:04:30 UTC, D_Learner wrote: memcpy(skip[0], skip[0]+shift, (m-shift)*(int.sizeof)); memset(skip[0]+(m-shift),0, shift*(int.sizeof)) I was thinking conversion would be :- skip[0 .. size-1] = skip[shift .. size-1 ]; //For the memcpy(); Those two slices have different lengths (when shift != 0). They must have equal lengths, and they must not overlap. skip[0 .. size-1] = 0;//For memset() But this doesn't seem to work for me as dmd(v2.066.1) gives the error slice [8..7] exceeds array bounds [0..8] .Sure am missing something. You can just do mechanical translations. memcpy(dst, src, n * T.sizeof); becomes dst[0 .. n] = src[0 .. n]; Then simplify. Original: memcpy(skip[0], skip[0]+shift, (m-shift)*(int.sizeof)); Identify the pieces: dst = skip[0] src = skip[0]+shift n = m-shift Substitute: (skip[0])[0 .. m-shift] = (skip[0]+shift)[0 .. m-shift]; Simplify: skip[0 .. m-shift] = skip[shift .. $][0 .. m-shift]; skip[0 .. m-shift] = skip[shift .. shift + m-shift]; skip[0 .. m-shift] = skip[shift .. m]; I sure hope I didn't mess anyting up. memset is very similar. memset(dst, val, n * T.sizeof); becomes dst[0 .. n] = val; Then simplify.
Re: Associative array literal. Why doesn't it compile?
On Friday, 14 August 2015 at 07:04:53 UTC, BBasile wrote: It's because of the key type (string is a library type). This is not true. It's not because of the key type. And string is not a library type.
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 02:21:46 UTC, D_Learner wrote: Well, the actual error I got is : Error: memset cannot be interpreted at compile time, because it has no available source code . I seems to suggest I miss the actual code. I guess I gave you a wrong impression of how pure relates to CTFE over here: http://forum.dlang.org/post/hdzhkxqgcpsuovcif...@forum.dlang.org. Sorry 'bout that. There, your function wasn't pure which made CTFE impossible. But being pure is not enough for a function to be CTFEable. The source code needs to be available, too. And then there are things that are ok in pure functions but simply don't work in CTFE.
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 02:21:46 UTC, D_Learner wrote: On Saturday, 15 August 2015 at 01:13:02 UTC, Adam D. Ruppe wrote: On Saturday, 15 August 2015 at 01:09:15 UTC, D_Learner wrote: When writting a pure fucntion involving C non pure functions like memcpy() and memset() Those functions are pure already, and marked so in the newest dmd (and I think older ones too, though I haven't confirmed. Your code compiled out of the box for me. BTW D also has some syntax sugar for them: arr[start .. end] = 0; // memset those bounds to 0 arr[start .. end] = arr2[start .. end]; // memcpy Well, the actual error I got is : Error: memset cannot be interpreted at compile time, because it has no available source code . I seems to suggest I miss the actual code. this is another thing. Here you reach the CTFE limits.
Re: SList container problem
https://issues.dlang.org/show_bug.cgi?id=14920
Re: complete win headers for 32/64 bit
On Thursday, 13 August 2015 at 16:28:15 UTC, learn wrote: unfortunately i can't find a complete set of windows header files. maybe one should add a link for those headers if they exist - life is not linux or osx only. https://github.com/etcimon/windows-headers
Re: Compiletime Table
On Thursday, 13 August 2015 at 19:13:55 UTC, D_Learner wrote: I was wondering how I could change the code below such the `bmBc` is computed at compile time . The one below works for runtime but it is not ideal since I need to know the `bmBc` table at compile-time . I could appreciate advice on how I could improve on this. import std.conv:to; import std.stdio; int [string] bmBc; immutable string pattern = GCAGAGAG; const int size = to!int(pattern.length); struct king { void calculatebmBc(int i)() { static if ( i size -1 ) bmBc[to!string(pattern[i])]=to!int(size-i-1); //bmBc[pattern[i]] ~= i-1; calculatebmBc!(i+1)(); } void calculatebmBc(int i: size-1)() { } } void main(){ king myKing; const int start = 0; myKing.calculatebmBc!(start)(); //1. enum bmBcTable = bmBc; } I think you may have some fundamental misunderstandings regarding CTFE, templates, etc. Your code seems to be half-way between a template-based and a CTFE-based solution. The simple way to do compile-time computation in D is CTFE (Compile Time Function Evaluation). That is, you write a pure function that can be evaluated both at run-time and at compile-time. CTFE doesn't need template parameters. Here's some code that should do the same as yours and is compatible with CTFE: import std.conv: to; import std.stdio; int[char] calculatebmBc(string pattern) pure { const int size = to!int(pattern.length); int[char] result; foreach(i; 0 .. size - 1) { result[pattern[i]] = to!int(size - i - 1); } return result; } void main() { auto bmBc = calculatebmBc(GCAGAGAG); enum bmBcTable = calculatebmBc(GCAGAGAG); } The key is that calculatebmBc is pure, i.e. it doesn't read or write any module-level mutables. I touched some things here and here I didn't like that are not related to purity/CTFE. Adam D. Ruppe already mentioned an issue with associative arrays: This doesn't work: static foo = calculatebmBc(GCAGAGAG); It's annoying, but if you need that you have to use some other data structure. See Adam's post.
Should these aliases kind be illegal ?
The following alias declaration is totally legal but actually it's not usable --- class Foo { void something(size_t param){} } class Bar { private Foo foo; this(){foo = new Foo;} alias somethingelse = foo.something; } void main(string[] args) { auto bar = new Bar; //bar.somethingelse(0u); } --- The call doesn't work but the declaration is fine. What is possible to make with this declaration ?
Re: Infinity loop with dates comparison
On Tuesday, 11 August 2015 at 19:56:02 UTC, Suliman wrote: Date startDate = Date.fromISOExtString(2014-08-01); [...] Date nextday; while (nextday currentDate) { nextday = startDate + 1.days; writeln(nextday); } startDate doesn't change, so every iteration just sets nextday to 2014-08-01 + 1 day = 2014-08-02.
Re: Removing elements from dynamic array
On Sunday, 9 August 2015 at 20:23:00 UTC, Reflexive wrote: I see that remove() removes the value of the element but keeps the same size of the array, and replace the value by a new one at the end. The method : class sabot{ card[] sabotarray ; (...) card getCard(){ card returncard = this.sabotarray[0] ; this.sabotarray.remove(0) ; return returncard ; } `remove` doesn't update the passed array, but it returns a slice of it that doesn't include the removed element. To update the original array, assign the result of `remove` to it: this.sabotarray = this.sabotarray.remove(0);
Re: std.array: array, ulong and Win32
On Sunday, 9 August 2015 at 20:13:38 UTC, ixid wrote: This seems like a reasonable use but errors, obviously I can do it in many other ways: ulong[] result = iota(1UL, 10UL).array; Error: static assert Argument types in (ulong) are not all convertible to size_t: (ulong) C:\D\dmd2\src\phobos\std\array.d 516 Yup, bug. Please file an issue at http://issues.dlang.org/. And while I'm here why do arrays not implicitly cast? ulong is happy to accept uint values but ulong[] will not accept uint[]. That's because the offsets of the elements are different. Reading a ulong means reading 8 bytes. But in a uint[] every element only takes up 4 bytes. So every 2 uint elements would be combined into one ulong. And if the uint[] doesn't have an even number of elements, you'd read beyond array bounds. You can do that conversion explicitly, but for an implicit conversion that would be too surprising.
Re: Concurrency Confusion
On Sunday, 9 August 2015 at 17:43:59 UTC, 岩倉 澪 wrote: Afaict it is the best way to do what I'm trying to do, and since the data is mutable and cast to immutable with assumeUnique, casting it back to mutable shouldn't be a problem. Technically casting away immutable might be undefined behaviour and it might be an ugly hack, but I don't see a more idiomatic solution. I think casting to shared and back would be better. Unfortunately, it looks like std.concurrency.send doesn't like shared arrays. I filed an issue: https://issues.dlang.org/show_bug.cgi?id=14893
Re: std.stream.MemoryStream deprecated, range is the alternative?
On Thursday, 6 August 2015 at 17:01:32 UTC, chris wrote: since memorystream is deprecated how do i do something like this with Input and Output ranges? How can i fill up an array with ranges like you can do with streams? Thanks. The InputRange primitives already exist for arrays, they are located in std.array, as well as the functions to insert elements. To achieve more advanced mutations use std.algorithm. --- import std.stdio; import std.array; import std.algorithm; byte B(T)(T t){return cast(byte) t;} struct FillerDemo { private byte cnt; byte front(){return cnt;} void popFront(){++cnt;} @property bool empty(){return cnt == 8;} } void main(string[] args) { auto rng = [0.B, 2.B, 4.B, 6.B, 8.B, 10.B, 12.B]; // reads then advances, destructively byte val = rng.front; writeln(val); rng.popFront; // fills with an array insertInPlace(rng, 0, [-4.B, -2.B, 0.B]); writeln(rng); rng = rng.init; // fills with a compatible range insertInPlace(rng, 0, *new FillerDemo); writeln(rng); // std.algorithm reverse(rng); } --- Note, if you don't know yet, that ranges are consumed. The front is lost each time popFront() is called.
Re: trouble compiling Fiber example code from docs dmd linux v2.067.1
On Thursday, 6 August 2015 at 20:21:38 UTC, Carl Sturtivant wrote: I took the example code from here, http://dlang.org/phobos/core_thread.html#.Fiber and wrapped the statements at the bottom inside main() and put import core.thread and std.stdio at the top, and the compiler gave me the following. /usr/include/dmd/druntime/import/core/thread.d(3894): Error: static variable PAGESIZE cannot be read at compile time fiberexample.d(8):called from here: super.this(this.run, PAGESIZE * 4LU) /usr/include/dmd/druntime/import/core/thread.d(3871): Error: static variable PAGESIZE cannot be read at compile time Help anyone? This isn't really clear from the example, but you need to put the bottom part in a function (e.g. main), including the variable initializations. I.e.: void main() { // create instances of each type Fiber derived = new DerivedFiber(); Fiber composed = new Fiber( fiberFunc ); // call both fibers once derived.call(); composed.call(); printf( Execution returned to calling context.\n ); composed.call(); // since each fiber has run to completion, each should have state TERM assert( derived.state == Fiber.State.TERM ); assert( composed.state == Fiber.State.TERM ); }
Re: What is the order of resolution for super() calls?
On Wednesday, 5 August 2015 at 12:32:48 UTC, cym13 wrote: For reference, as the diagram was unreadable, I'll describe it here: class Adam ; class Eve ; class Abel:Adam,Eve ; class Cain:Adam,Eve ; class David:Abel,Cain ; This is illegal D. You must use interfaces to simulate multiple inheritance: D classes support the single inheritance paradigm, extended by adding support for interfaces. see more here: http://dlang.org/class.html
Re: D Wiki: Windows programming examples are missing
On Wednesday, 5 August 2015 at 21:02:49 UTC, Andre Polykanine wrote: Hi everyone, I'm fairly new to D and am really excited about it. I would like to see more examples of Windows programming in D, but the repository indicated on the D wiki seems to be moved or deleted. More info is here: http://wiki.dlang.org/talk:D_for_Win32 Thanks! I've recently bookmarked this one: https://github.com/etcimon/windows-headers However it's not usable out of the box. See repository readme.
Re: Trouble with template parameter matching
On Sunday, 2 August 2015 at 08:08:05 UTC, tcak wrote: [code] void func1(N)( const N name ) if( is(N: string) || is(N: char[]) ) { func2( name ); } void func2(N)( const N name ) if( is(N: string) || is(N: char[]) ) {} void main(){ char[] blah = ['b', 'l', 'a', 'h']; func1( blah ); //func1( blah );// this works } [/code] [result] test.d(4): Error: template test.func2 cannot deduce function from argument types !()(const(char[])), candidates are: test.d(7):test.func2(N)(const N name) if (is(N : string) || is(N : char[])) [/result] When func1 is called with blah variable, I assume that N is char[]. Yup. From there, when func2 is called by func1, name should be const(char[]). Yup. But since func2 defined name parameter with const, shouldn't the compiler accept const part of const(char[]) as func2's const, and accept N as char[] still? Nope. When removing the top level const of `const(char[])`, it becomes `const(char)[]`. Test for that in your template constraint and it works.
Re: alias overloading strange error
On Friday, 31 July 2015 at 11:09:39 UTC, anonymous wrote: Definitely a bug. Please file an issue at https://issues.dlang.org/. https://issues.dlang.org/show_bug.cgi?id=14858
Re: alias overloading strange error
On Friday, 31 July 2015 at 10:56:33 UTC, vitus wrote: //Why expression 'foobar(1);' doesn't work? void foo()(){} void bar(int){} alias foobar = foo; alias foobar = bar; void main(){ .foobar(1); //OK foobar(1); //Error: overload alias 'foo' is not a variable } It works when you switch the aliases around: void foo()(){} void bar(int){} alias foobar = bar; alias foobar = foo; void main(){ foobar(1); } Definitely a bug. Please file an issue at https://issues.dlang.org/.
Re: Type inference of a function parameter
On Wednesday, 29 July 2015 at 20:20:47 UTC, Adel Mamin wrote: void my_func(auto arr) { writeln(arr); } There are no `auto` parameters in D. You have to make it a template explicitly: void my_func(A)(A arr) { writeln(arr); }
Re: Error: 'this' is only defined in non-static member functions, not main
On Wednesday, 29 July 2015 at 21:33:16 UTC, remi thebault wrote: Hello I have this weird error trying to achieve something simple: That's far from simple. Here's a reduction: template wl_container_of(alias member) { size_t get() {return member.offsetof;} } struct item { int link; } void main() { wl_container_of!(item.link).get(); /* Error: 'this' is only defined in non-static member functions, not main */ } I'm not sure what's going on here, if this should or shouldn't work. The error message isn't exactly good. Slapping `static` on `get` seems to make it work: static size_t get() {return member.offsetof;} I guess the compiler thinks that since `item.link` is an instance member, it needs a `this`. And then `get` would need a `this` too as it's using `item.link` via `member`. When the compiler sees that there is no `this`, it errors out. An explicit `static` forces the compiler to assume no `this`. And it would error out if you actually tried to make use of it. Naively, I'd think the compiler should be able to figure that out itself.
Re: extern(C) with function returning user type
On Wednesday, 29 July 2015 at 17:59:26 UTC, Kyoji Klyden wrote: How would I use a C function that's returning a struct? auto doesn't work here, and from what I can tell D can't import C headers. (If it really can't then, that would be a very welcome feature) I do have the required libs but I can't create my D obj file so I can't really get there. I know that there htod but, is there anyway I can avoid using that? I'm using GDC, and GCC on Win7 D can't import C header files. And I don't think such a feature is planned right now. You have to translate the C declarations to D, both struct and function. You can do that either manually or using some tool. If you go the manual route, there's a page on that: http://dlang.org/ctod.html For tools, if you're not happy with htod, maybe DStep works better: https://github.com/jacob-carlborg/dstep
Re: Dynamic memory
On Tuesday, 28 July 2015 at 22:52:31 UTC, Binarydepth wrote: I'm reading the reference : http://dlang.org/arrays.html And I'm declaring two dynamic arrays as I understand. What I had in mind was declaring a dynamic array of two elements each. int[2][] is exactly an dynamic array of (arrays with the length 2), the logic behind this notation is: 1. Array of 2 int - int[2] 2. a dynamic array of 1. - int[2][] (like SomeType[] is an array of SomeType) If you define SomeType e.g. as struct SomeType { int firstElement; int secondElement; } you get something similar. Yes, this is different from e.g. Java, where new int[2][42] creates an array of 2 arrays with 42 elements each. Accessing int[2][] nums : 1. nums[5] is the 5th element of nums which is of type int[2] 2. nums[5][0] is the zeroth element of 5th element of nums int[2] tmp = nums[5]; int value = tmp[0]; does the same...
Re: Dynamic memory
On Tuesday, 28 July 2015 at 16:41:40 UTC, Binarydepth wrote: It works with 2 as input but shows error when number is 3 :( I can't reproduce that or I misunderstood something: $ cat a.d import std.stdio : readf, writef; void main(){ int[2][] nam; int num; readf( %d, num); nam.length = num; foreach(nim; 0..num){ readf( %d %d, nam[nim][0], nam[nim][1]); } foreach(nim; 0..num){ writef( %d %d\n, nam[nim][0], nam[nim][1]); } } $ dmd a.d $ ./a 3 1 2 3 4 5 6 1 2 3 4 5 6
Re: Dynamic memory
On Tuesday, 28 July 2015 at 16:09:46 UTC, Binarydepth wrote: Here is what I'm trying to do : import std.stdio : readf, writef; void main() { int[2][] nam; int num; readf( %d, num); nam.length = num; foreach(nim; 0..num){ readf( %d %d, nam[0][num], nam[1][num]); } foreach(nim; 0..num){ writef( %d %d\n, nam[0][num], nam[1][num]); } } In addition to Adam: there are typos (num instead of nim) - since num is the array length and the indices are 0-based, num is out of bounds... foreach(nim; 0..num){ readf( %d %d, nam[nim][0], nam[nim][1]); } foreach(nim; 0..num){ writef( %d %d\n, nam[nim][0], nam[nim][1]); } works fine.
Re: Select value from list, indexed by a type
On Tuesday, 28 July 2015 at 21:12:13 UTC, Johan Engelen wrote: Hi all, I am wondering if there is any Phobos functionality for indexing into a list using a type. What I mean is something like: assert( somethingie!(float, float, double, real)(1, 22, 333) == 1 ); assert( somethingie!(double, float, double, real)(1, 22, 333) == 22 ); assert( somethingie!(real, float, double, real)(1, 22, 333) == 333 ); std.typetuple.staticIndexOf (going to be moved to std.meta in 2.068) can do this together with std.typecons.tuple: void main() { import std.typetuple: staticIndexOf; import std.typecons: tuple; assert(tuple(1, 22, 333)[staticIndexOf!(float, float, double, real)] == 1); assert(tuple(1, 22, 333)[staticIndexOf!(double, float, double, real)] == 22); assert(tuple(1, 22, 333)[staticIndexOf!(real, float, double, real)] == 333); } Or if you think that's worth encapsulating in somethingie: template somethingie(T, TList...) { auto somethingie(A...)(A args) { import std.typetuple: staticIndexOf; import std.typecons: tuple; return tuple(args)[staticIndexOf!(T, TList)]; } } void main() { assert( somethingie!(float, float, double, real)(1, 22, 333) == 1 ); assert( somethingie!(double, float, double, real)(1, 22, 333) == 22 ); assert( somethingie!(real, float, double, real)(1, 22, 333) == 333 ); }
Re: Problem with casting instance reference to void* and back.
On Monday, 27 July 2015 at 12:03:06 UTC, Vlad Leberstein wrote: Hi! My use case requires interaction with C API which in turn implies storing object instance reference as void *. I'm using gdc 4.9.2 and everything worked fine with object - void * - object conversion, but object - void * - interface failed. The stripped-down example is something like this: interface TestInterface { void testMethod(); } class TestImpl : TestInterface { void testMethod() { writefln(TestImpl::testMethod\n); } }; void testDispathcer(void *rawSelf) { auto self = cast(TestInterface) rawSelf; // nothing happens self.testMethod(); } int main(string[] args) { auto t = new TestImpl(); testDispathcer(cast(void *) t); return 0; } However this works: void testDispathcer(TestImpl rawSelf) { auto self = cast(TestInterface) rawSelf; // TestImpl::testMethod is printed to stdout self.testMethod(); } int main(string[] args) { auto t = new TestImpl(); testDispathcer(t); return 0; } Is there any way to handle such situation without resorting to templating dispatcher with every *Impl type? As second example works as expected I presume that runtime loses some type information to perform downcast and maybe it's possible to extract it and store externally and merge back later? I'm quite new to D and sorry if the question is dumb. Any help would be greatly appreciated! Thanks in advance! In the first example, you pass a pointer to a class instance. You cannot get the vtbl entry for the interface like this. Instead try to do this in 2 steps: --- import std.stdio; interface TestInterface { void testMethod(); } class TestImpl : TestInterface { void testMethod() { writefln(TestImpl::testMethod\n); } }; void testDispathcer(void *rawSelf) { auto obj = cast(Object) rawSelf; auto self = cast(TestInterface) obj; // nothing happens self.testMethod(); } int main(string[] args) { auto t = new TestImpl(); testDispathcer(cast(void *) t); return 0; } ---
Re: Problem with casting instance reference to void* and back.
On Monday, 27 July 2015 at 13:11:33 UTC, anonymous wrote: In the first example, you pass a pointer to a class instance. You cannot get the vtbl entry for the interface like this. Instead try to do this in 2 steps: actually i meant you pass an untyped pointer, so when you cast as interface it's not like if the vtbl of an object is queried. So you have to upcast to an Object then cast to the interface, which is not a simple cast (it get something in the virtual table. void testDispathcer(void *rawSelf) { auto obj = cast(Object) rawSelf; // reinterpret auto self = cast(TestInterface) obj; // get vtbl entry , it's not a simple cast // works self.testMethod(); }
Re: Yes or No Options
On Monday, 27 July 2015 at 16:48:00 UTC, Alex wrote: Okay. By pure trying I found out what I did wrong: Apparently by typing Y I entered the shift key. Could that have been the problem? I changed it to a small y and it at least jumped back to the commandline instead of just being stuck. And by changing: writeln(Do you want to play again? Y/N?); readln(yesno); if (yesno == y) { writeln(Yeah!); } to: writeln(Do you want to play again? Y/N?); readln(yesno); if (yesno != y) { writeln(Yeah!); } So instead of == I used != Now it works. But I still do not know why.. Check out what is the length of yesno after you do your readln. Ex. writeln(yesno.length) std.string.chomp may help.
Re: Why hide a trusted function as safe?
On Sunday, 26 July 2015 at 11:38:31 UTC, simendsjo wrote: Is there a reason why you would hide the fact that a function is trusted rather than safe? Technically it doesn't matter, right? To me, it seems like this would give wrong assumptions to the caller. The reason I ask is because I found the following in std.concurrency: @property Tid thisTid() @safe { // TODO: remove when concurrency is safe auto trus = delegate() @trusted { if( thisInfo.ident != Tid.init ) return thisInfo.ident; thisInfo.ident = Tid( new MessageBox ); return thisInfo.ident; }; return trus(); } As far as I know, it doesn't matter. Both @safe and @trusted functions must be memory safe. So I don't see a point in doing that delegate dance. But it doesn't make a difference to the caller either. They can't assume any more or less about an @safe function than about an @trusted one.
Re: Sending an immutable object to a thread
On Friday, 24 July 2015 at 18:55:26 UTC, Frank Pagliughi wrote: So then, of course, I hope/wonder/assume that the pointer to the heap is sufficient to keep the heap memory alive, and that this would be OK from the GC perspective to do something like this: B* make_b_thing(int i) { cast(B*) new B(i); } (You missed a return there.) I haven't followed the discussion, so I may be missing the point here. But if you're doing this so that the GC is aware of the `new`ed B, then you really don't need to. The GC has no problems with class types. Class references do keep objects alive. That is, the above will not keep the created object any more alive than the following: B make_b_thing(int i) { return new B(i); } That seems to work, but I guess I should try to force the garbage collector to run to see if I can crash the program. ***BUT***: The really, really weird thing is that even though you *think* that you have a pointer to a B object, you don't really. Dereferencing is accepted by the compiler, but it plays a nasty trick on you: A B* is not a pointer to the memory of the object. It's a pointer to a class reference. The class reference itself, B, is a pointer to the memory of the object, under the hood. Casting a B to B* makes as little sense as casting it to float* or char*. B* p = make_b_thing(42); writefln(Address of pointer: %s, p); writefln(Value of i: %s, p.i); p really is a pointer to the memory of the object. But by typing it B* you're stating that it's a pointer to a class reference, which is wrong. p.i does two dereferences where one would be correct. First, p is dereferenced. The resulting data is really that of the object. But it's typed B, so the compiler thinks it's a class reference. So it takes first bytes of the actual object data, interprets it as a pointer, dereferences it, and assumes to see the object data there (wherever that is). Getting the i field of that garbage location results in some garbage data, of course. writefln(Value of i: %s, (*p).i); Same as above. When p is a pointer, then p.i becomes (*p).i automatically in D. writefln(Value of i: %s, (cast(B)p).i); Here the type has only one level of indirection, as it should be. And everything's fine. This compiles and runs fine, but produces: Address of pointer: 7F7EE77CF020 Value of i: 4445040 Value of i: 4445040 Value of i: 42 Maybe it's my C++ background talking, but that seems a bit counter-intuitive. I'd say it's your C++ background talking.
Re: Sending an immutable object to a thread
On Friday, 24 July 2015 at 21:51:44 UTC, Frank Pagliughi wrote: So then: is there a pointer notation to which you can cast the B reference, which thus points to the heap, but retains type identity of the heap object? There's no straight forward way to do that. D has no types for the actual objects of classes. You'd have to generate a new struct type from B that you can point at. And the reason I ask if I wanted to declare a type which is a mutable pointer to an immutable object that is on the GC heap, keeping type info? Or is the answer, no, just use Rebindable when necessary? We only have Rebindable because there is no nice way in the language to do it. So, just use Rebindable, yes. You could look at what Rebindable does, and then do that, of course. But be sure that you understand all the nasty details.
Re: monitoring variable evaluation time
On Monday, 20 July 2015 at 08:53:52 UTC, Clayton wrote: What could be the best-tool for monitoring the evaluation time of a variable . What I usually do is run the command :- - dmd -J. program.d Then I inspect the program.o file using vi for presence of compile-time constants and enums. I am wondering if this is the right way to do this. Am a bit skeptical about this as am working on pushing everything that the compiler can do to the compiler for faster run-time. You mean you want to know if some value is pre-computed during compilation? There are various places where the compiler is required to compute at compile time: * initializers of module level variables * initializers of static variables * enum values * dimensions of static arrays * template value arguments * probably a couple more I can't of right now In these places where pre-computation is guaranteed, it's called CTFE. Compilers are free to pre-compute other constants (constant folding). It's pretty safe to assume that simple, constant arithmetic expressions are evaluated at compile-time, maybe it's even guaranteed. Beyond that, things vary between compilers. Instead of checking if the compiler recognizes your constants and pre-computes them, I'd suggest to force it by using a CTFE context. To force CTFE in an otherwise non-CTFE context, you can use a little helper: enum ctEval(alias expr) = expr; void main() { auto x = ctEval!(/* some complex expression that would possibly not be constant folded otherwise */); } I'm not sure if this the best way to define ctEval. I thought it had found its way into phobos by now, but I can't find it anywhere. This very simple version here may have issues.
Re: String Metaprogramming
On Saturday, 18 July 2015 at 16:18:30 UTC, Clayton wrote: Thanks , you were right . It seems there are some key words though which one has to use so that the code gets executed on compile-time .For example I had to change the second forloop to a foreach loop, `for` loops work just fine in CTFE. `foreach` is usually nicer, though (regardless of CTFE or not). and then put and enum to ensure that TableFromCompiler gets evaluated at compiletime. Having written the code this way though gives rise to some other question, D supports 2 approches to compiletime metaprogramming i.e. CTFE and Templates, it seems am not very sure which paradigm my code falls in. Your computeAtCompileTime is a template that results in a function when instantiated. You're calling such a generated function and you're assigning the result to an enum, which makes it a CTFE call. So there's both CTFE and a template in your code. You could probably do the whole pre-computation without CTFE, using only templates. But (here) CTFE is more straight forward as you can just write normal run time D.
Re: Infinite range of nullable elements
On Friday, 17 July 2015 at 07:42:09 UTC, Roland Hadinger wrote: Here's how I would implement the basic behaviour (could be extended to also forward bidirectional and random access functions): --- auto cushion(R)(R r) if (isInputRange!R) { static if (isInfinite!R) { return r; } else { struct _Cushion(R) { R r; alias E = ElementType!R; alias NE = Nullable!E; @property bool empty() { return false; } @property NE front() { return !r.empty ? NE(r.front) : NE(); } void popFront() { if (!r.empty) r.popFront(); } } return _Cushion!R(r); } } --- I didn't find anything like this Phobos. Did I miss something? The building blocks are there. You're `map`ping the original range to `Nullable`, and then you're `chain`ing an infinite range (`cycle`) of nulls behind. import std.range: isInputRange; auto cushion(R)(R r) if (isInputRange!R) { import std.algorithm: map; import std.range: chain, cycle, ElementType, only; import std.typecons: Nullable; alias E = ElementType!R; alias NE = Nullable!E; return chain(r.map!NE, NE().only.cycle); }
Re: Environment variable for application storage under OSX ?
On Friday, 17 July 2015 at 07:54:43 UTC, FreeSlave wrote: On Friday, 17 July 2015 at 07:33:43 UTC, Anonymous wrote: On Friday, 17 July 2015 at 07:14:24 UTC, FreeSlave wrote: On Thursday, 16 July 2015 at 21:12:05 UTC, anonymous wrote: I have the following code, working under Win and Linux: --- import std.process: environment; immutable string p; static this() { version(Win32) p = environment.get(APPDATA); version(linux) p = /home/ ~ environment.get(USER); version(OSX) p = ?; } --- what would be the OSX equivalent (to get the path where the applications data are commonmly stored)? Hello. You may take a look at this library https://github.com/MyLittleRobo/standardpaths OSX version uses Carbon though. You may want to use Cocoa API (which is newer), but it's Objective-C. Also you may consider standard path for data storage without using any api or spec. It's usually $HOME/Library/Application Support/ on OSX. So for a software named 'SuperDownloader2015' it would be $HOME/Library/Application Support/SuperDownloader2015 right ? so it's not user-specific and it's writable for the current user ? sorry but it looks a bit strange, anyone can confirm ? It is user specific obviously since it's in user home. Can you elaborate on what do you want exactly? From Windows and Linux examples you provided I assumed you need user-specific paths (APPDATA is defined per user on Windows). System-wide application data path is different. Ok so my sample can be rewritten static this() { version(Win32) p = environment.get(APPDATA); version(linux) p = /home/ ~ environment.get(USER); version(OSX) p = environment.get(HOME) ~ /Library/Application Support/; } --- I really wish it could be possible to buy and setup OSX on any hardware...I will never buy a mac just to test the portability of a couple of projects 1 hour per week... Anyway thx all for your answers.
Re: Environment variable for application storage under OSX ?
On Friday, 17 July 2015 at 07:14:24 UTC, FreeSlave wrote: On Thursday, 16 July 2015 at 21:12:05 UTC, anonymous wrote: I have the following code, working under Win and Linux: --- import std.process: environment; immutable string p; static this() { version(Win32) p = environment.get(APPDATA); version(linux) p = /home/ ~ environment.get(USER); version(OSX) p = ?; } --- what would be the OSX equivalent (to get the path where the applications data are commonmly stored)? Hello. You may take a look at this library https://github.com/MyLittleRobo/standardpaths OSX version uses Carbon though. You may want to use Cocoa API (which is newer), but it's Objective-C. Also you may consider standard path for data storage without using any api or spec. It's usually $HOME/Library/Application Support/ on OSX. So for a software named 'SuperDownloader2015' it would be $HOME/Library/Application Support/SuperDownloader2015 right ? so it's not user-specific and it's writable for the current user ? sorry but it looks a bit strange, anyone can confirm ?
Re: Comparison of struct with Nullable member
On Friday, 17 July 2015 at 12:18:56 UTC, TC wrote: Hello, I came around a strange behavior and I'm not sure if it is a bug or feature. import std.typecons : Nullable; struct Foo { string bar; Nullable!int baz; } auto a = Foo(bb); auto b = Foo(bb); assert(a == b); This ends up with: Called `get' on null Nullable!int But if I change bar to be an int for example, than it passes ok. I would expect this to pass ok. Tested on dmd 2.067.1 win64 Bug. I reported a reduced version as https://issues.dlang.org/show_bug.cgi?id=14806.
Environment variable for application storage under OSX ?
I have the following code, working under Win and Linux: --- import std.process: environment; immutable string p; static this() { version(Win32) p = environment.get(APPDATA); version(linux) p = /home/ ~ environment.get(USER); version(OSX) p = ?; } --- what would be the OSX equivalent (to get the path where the applications data are commonmly stored)?
Re: Understanding Safety of Function Pointers vs. Addresses of Functions
On Tuesday, 14 July 2015 at 01:05:21 UTC, jmh530 wrote: Note: some of the above seemed to only work when I kept the std.math.cos, std.math.sin text in there. When I take it out, I get warnings about recursive aliases. Yeah, you can't do `alias cos = givemeabettername!cos;`. That would define the new cos in terms of itself. But, I can't seem to use a foreach loop. The recursive mixin template seems to be required. You can only use the implicitly static foreach where the normal, dynamic foreach is allowed, i.e. in function bodies. This is a syntactic restriction. If we had `static foreach` (like we have `static if`), that would presumably work everywhere. So this is the last thing I did (that didn't work). Adding foo back to the alias works. mixin template callThemAll(functions...) { mixin(alias ~__traits(identifier, functions[0]) ~ = givemeabettername!(std.math.~__traits(identifier, functions[0]) ~ );); static if(functions.length 1) mixin callThemAll!(functions[1..$]); } mixin callThemAll!(cos, sin); Works for me. Please show the complete code and the error message you get. Here's what works for me: import std.algorithm: map; import std.math; import std.array: array; template givemeabettername(alias fun) { T givemeabettername(T : U[], U)(T x) { return x.map!fun.array; } } mixin template callThemAll(functions...) { mixin(alias ~__traits(identifier, functions[0]) ~ = givemeabettername!(std.math.~__traits(identifier, functions[0]) ~ );); static if(functions.length 1) mixin callThemAll!(functions[1..$]); } mixin callThemAll!(cos, sin); void main() { real[] a = [1, 2, 3]; auto c = cos(a); auto s = sin(a); }
Re: Understanding Safety of Function Pointers vs. Addresses of Functions
On Tuesday, 14 July 2015 at 14:02:46 UTC, jmh530 wrote: Thanks for posting that. I figured out the issue. Before you had recommended that I use alias cos = std.math.cos; I had kept that text in. When I removed it, everything worked just fine. I'm still not sure I grasp the subtleties of alias when used with templates. Oh that's another goodie. So you had a situation like this: import std.math; alias cos = std.math.cos; mixin template t() { void cos(real[] arr) {/* ... */} } mixin t!(); void main() { cos([1, 2, 3]); } This fails with Error: None of the overloads of 'cos' are callable using argument types (int[]). The problem is that template mixins cannot add to existing overload sets. The spec says: If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one [1]. That means, the `cos` from `alias cos = std.math.cos;` completely overrides the one from `mixin t!();`. I guess this is a measure against function hijacking again. I'm not sure if it's supposed to work like it does when the alias is removed, two implicitly imported/generated symbols forming an overload set. But I can't immediately see a problem with it either. [1] http://dlang.org/template-mixin.html - see Mixin Scope
Re: Understanding Safety of Function Pointers vs. Addresses of Functions
On Sunday, 12 July 2015 at 21:07:34 UTC, jmh530 wrote: private template givemeabettername(alias fun) { T givemeabettername(T : U[], U)(T x) if (isArray!(T)) { return x.map!(a = fun(a)).array; You don't need the lambda, do you? - return x.map!fun.array; } } Very cool. I guess I'm still left with the issue that I don't know how to loop through a bunch of different functions at compile time, but this is so elegant that it doesn't seem like that big a deal. I don't know what exactly you're after, but you can use foreach on a whatever-they're-called-now tuple (there's been a discussion about the name which I haven't followed; I mean the kind you get from a TemplateTupleParameter): void f1() {} void f2() {} void callThemAll(functions ...)() { foreach(f; functions) /* The loop is unrolled at compile time. */ { f(); } } void main() { callThemAll!(f1, f2)(); } As usual, recursion is an alternative: void callThemAll(functions ...)() { static if(functions.length 0) { functions[0](); callThemAll!(functions[1 .. $])(); } }
Re: Understanding Safety of Function Pointers vs. Addresses of Functions
On Sunday, 12 July 2015 at 16:34:17 UTC, jmh530 wrote: I've been playing around with this a little more. I wrote this function to encapsulate a simple operation on arrays. U array_fun(T, U)(T fp, U x) if (isFunctionPointer!(T) isArray!(U)) { return x.map!(a = fp(a)).array; } Then I wrote a cos function that calls it on using a function pointer. T cos(T : U[], U)(T x) if (isArray!(T)) { auto fp = (U a) = cos(a); return array_fun(fp, x); } This seems to work just fine, but for some reason this only seems to work when I import std.math : cos. It doesn't work when I just do import std.math. Bug? Your function is called cos, too. So you need your local cos and std.math.cos to form an overload set. This isn't automatically done with implicitly imported functions to avoid hijacking [1] (accidentally calling the wrong function). Selectively imported functions are added to the overload set, as you (the programmer) are obviously aware of them and want them in the overload set. An alternative would be to use an alias: import std.math; alias cos = std.math.cos; Nevertheless, if I want to implement it for another function, then I have to write it all over again. So I wrote a mixin that would encapsulate that idea (I put in the \n, \t for formatting purposes because I like to be able to writeln it out and see that it matches the original). template mixin_builder(string function_name) { const char[] mixin_builder = T ~ function_name ~ (T : U[], U)(T x)\n ~ \tif (isArray!(T))\n ~ {\n ~ \tauto fp = (U a) = ~ function_name ~ (a);\n ~ \treturn array_fun(fp, x);\n ~ }; } Then I can just call mixin(mixin_builder!(cos)); mixin(mixin_builder!(sin)); While it works, it feels a bit hackish. I'm not sure I can think of a generic way to do this without mixins. Take the function via an alias parameter: template givemeabettername(alias fun) { T givemeabettername(T : U[], U)(T x) if (isArray!(T)) { auto fp = (U a) = fun(a); return array_fun(fp, x); } } alias cos = givemeabettername!(std.math.cos); alias sin = givemeabettername!(std.math.sin); But turning a statically known function to a function pointer only to pass it to `map` seems pointless to me. So: template givemeabettername(alias fun) { T givemeabettername(T : U[], U)(T x) if (isArray!(T)) /* With the specialization above, this is redundant, isn't it? */ { return x.map!fun.array; } } And personally, I'd probably just type out `x.map!fun.array` every time. [1] http://dlang.org/hijack.html
Re: opApply compilation woes
On Sunday, 12 July 2015 at 17:25:17 UTC, Gary Willoughby wrote: Why does the following code fail to compile if the `writeln(value);` line is present? The error message (formatted to be a little more readable): Error: function test2.__unittestL6_1.Foo.opApply (int delegate(ref string) nothrow dg) is not callable using argument types (int delegate(ref string __applyArg0) @system) Note that the parameter has nothrow, but the argument doesn't. And that's it: writeln isn't nothrow.
Re: Array operations with array of structs
On Saturday, 11 July 2015 at 13:31:12 UTC, Peter wrote: The postblit can only not take @nogc due to the array duplication which is understandable. I think the postblit might be redundant anyway since the struct is built on a static array so there is no possibility of two different Vect3s pointing to the same data. Can someone confirm or does the postblit do anything else? The postblit is pointless, yes. The `.dup` copies from one location to another, only for the assignment to copy everything back to the original location; and then the new array is discarded.
Re: Import module
On Friday, 10 July 2015 at 03:11:25 UTC, Mike Parker wrote: On Friday, 10 July 2015 at 00:53:38 UTC, codenstuff wrote: The path is ${HOME}/d_apps/steering/steering/game_object.d [...] First, because you are importing sterring.game_object, then you can't pass -I/home/real/d_apps/steering to the compiler -- this will cause it to look for /home/real/d_apps/steering/sterring/game_object.d. You have to pass the parent of the steering directory, i.e. -I/home real/d_apps. Then it will be able to find the import. He said The path is ${HOME}/d_apps/steering/steering/game_object.d, so -I/home/real/d_apps/steering should be correct.
Re: Import module
On Friday, 10 July 2015 at 00:53:38 UTC, codenstuff wrote: On Friday, 10 July 2015 at 00:24:44 UTC, anonymous wrote: On Thursday, 9 July 2015 at 22:05:23 UTC, codenstuff wrote: I am trying to import module and compile. The compiler produces message map/map.d(9): Error: module game_object is in file 'steering/game_object.d' which cannot be read import path[0] = /usr/include/dmd/phobos import path[1] = /usr/include/dmd/druntime/import make: *** [main] Error 1 [...] The path is ${HOME}/d_apps/steering/steering/game_object.d Compile command is dmd map/map.d main_visual.d -ofmain_visual -H -gc -unittest -L-lDgame -L-lDerelictUtil -L-lDerelictGL3 -L-lDerelictSDL2 -L-ldl -I/home/real/d_apps/dgame/source -I/home/real/d_apps/derelict_util/source -I/home/real/d_apps/derelict_gl3/source -I/home/real/d_apps/derelict_sdl2/source -I/home/real/d_apps/steering Compiler message is same The error message doesn't list any of your import paths. So I still think that the message doesn't belong to that command. Maybe try reducing things to a smaller, self-contained test case.
Re: Import module
On Thursday, 9 July 2015 at 22:05:23 UTC, codenstuff wrote: I am trying to import module and compile. The compiler produces message map/map.d(9): Error: module game_object is in file 'steering/game_object.d' which cannot be read import path[0] = /usr/include/dmd/phobos import path[1] = /usr/include/dmd/druntime/import make: *** [main] Error 1 This error message doesn't mention the import path you add below with -I${HOME}/d_apps/steering. It should. Looks like you copied the output of a different command. How can I compile? Is it possible to modify import path? Modules are set up as ${HOME}/d_apps/steering (contains steering/game_object.d) Is that ${HOME}/d_apps/steering/steering/game_object.d or is it ${HOME}/d_apps/steering/game_object.d? ${HOME}/d_apps/path_find (contains map/map.d) In map.d I import as import steering.game_object; The compile command dmd map/map.d main_visual.d -I${HOME}/d_apps/steering If the file is ${HOME}/d_apps/steering/steering/game_object.d, then this import path should be ok. If the file is ${HOME}/d_apps/steering/game_object.d, then that import is wrong, and you'd have to pass the import path as -I${HOME}/d_apps instead. (Adam D. Ruppe already said the following, but maybe he wasn't verbose enough.) Even when the import path is fixed, this can't compile because you're not passing game_object.d to the compiler. You have multiple options: You can pass all source files to dmd. You don't need to tinker with the import paths then. Or you can use rdmd instead of dmd (or rather on top of it). rdmd takes a single source file, discovers the imported modules, and passes everything to dmd. It needs proper import paths to work its magic, of course.
Re: Understanding Safety of Function Pointers vs. Addresses of Functions
On Tuesday, 7 July 2015 at 19:54:19 UTC, jmh530 wrote: I'm not sure I understand the safety of function pointers vs. the addresses of functions. The code below illustrates the issue. I was under the impression that pointers are not allowed in safe code. No, pointers are fine. It's pointer arithmetic that's considered unsafe. Naturally, I took that to also mean that function pointers are not allowed in safe code. Indeed, I haven't been able to pass a function pointer to a safe function. However, I am able to take the address of a function and pass that as a parameter. It seems to work fine for taking the address of functions and templates (so long as I !) So long as you exclamation mark? Huh? import std.stdio : writeln; import std.traits; import std.math; void function_safety(T)(T fp) { if (functionAttributes!fp FunctionAttribute.safe) writeln(fp is safe); else if (functionAttributes!fp FunctionAttribute.trusted) writeln(fp is trusted); else if (functionAttributes!fp FunctionAttribute.system) writeln(fp is system); else writeln(fp is neither safe nor trusted nor system); } void main() { function_safety(cbrt); //prints fp is trusted real function(real) fp = cbrt; You're explicitly typing that as `real function(real)` which is not an @safe type. Add @safe and you're good to go: real function(real) @safe fp = cbrt; function_safety(fp); /* prints fp is safe */ Or let the compiler infer things: auto fp = cbrt; function_safety(fp); /* prints fp is trusted */ function_safety(fp); //prints fp is system }
Re: Understanding Safety of Function Pointers vs. Addresses of Functions
On Tuesday, 7 July 2015 at 20:32:49 UTC, jmh530 wrote: Thanks for the detailed answer. All I meant here is that if I have some T foo(T)(T x), then to take the address, sometimes I've needed to foo!int or foo!real, etc. Ah, sure. Templates don't have addresses. Function templates are not exempt from that. I think you always have to instantiate them in order take an address, not just sometimes.
Re: incorrect data when returning static array in place of dynamic
On Monday, 6 July 2015 at 07:48:17 UTC, sigod wrote: Aren't compiler smart enough to prevent it? ``` ubyte[] test1() { auto b = sha1Of(); return b; // Error: escaping reference to local b } ubyte[] test2() { return sha1Of(); // works, but returns incorrect data } ``` Looks more like a bug to me. dmd 2.068.0 catches this. You can get the beta here: http://downloads.dlang.org/pre-releases/2.x/2.068.0/
Re: Array operations with array of structs
On Monday, 6 July 2015 at 01:16:54 UTC, Peter wrote: Hi, I have a struct with arithmetic operations defined using opBinary but array operations with arrays of it don't work. struct Vector3 { public double[3] _p; ... Vector3 opBinary(string op)(in Vector3 rhs) const if (op == +){ Vector3 result; result._p[] = this._p[] + rhs._p[]; return result; } ... } unittest{ auto a = Vector3([2.0, 2.0, 0.0]); auto b = Vector3([1.0, 2.0, 1.0]); Vector3[] c = [a]; Vector3[] d = [b]; Vector3 e = a + b; // works Vector3[] f; f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations } how can I get this to work? Thanks Works for me with various versions of dmd on linux. What compiler are you using, what version of it, what operating system, etc?
Re: Array operations with array of structs
On Monday, 6 July 2015 at 03:02:59 UTC, Nicholas Wilson wrote: On Monday, 6 July 2015 at 01:16:54 UTC, Peter wrote: [...] unittest{ auto a = Vector3([2.0, 2.0, 0.0]); auto b = Vector3([1.0, 2.0, 1.0]); Vector3[] c = [a]; Vector3[] d = [b]; Vector3 e = a + b; // works Vector3[] f; f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations } how can I get this to work? Thanks you need to define the slice operators. e.g. auto opSlice() // no parameters to get whole slice eg. a[] // can also define with opSlice(size_t i, size_t j) // for access like a[ i .. j] { return _p; } `f`, `c`, and `d` are arrays though, not `Vector3`s. The code doesn't try to slice a Vector3. So as far as I can see, there's no point in adding opSlice to it.
Re: Array operations with array of structs
On Monday, 6 July 2015 at 12:15:22 UTC, Peter wrote: dmd 2.066.1, windows 7 64bit Tested it on Windows 7, using dmd 2.066.1: works for me. The exact code I tested (just commented those ... out): struct Vector3 { public double[3] _p; //... Vector3 opBinary(string op)(in Vector3 rhs) const if (op == +){ Vector3 result; result._p[] = this._p[] + rhs._p[]; return result; } //... } unittest{ auto a = Vector3([2.0, 2.0, 0.0]); auto b = Vector3([1.0, 2.0, 1.0]); Vector3[] c = [a]; Vector3[] d = [b]; Vector3 e = a + b; Vector3[] f; f[] = c[] + d[]; } And the command line: dmd -main -unittest test.d
Re: Correctly implementing a bidirectional range on a linked list?
On Monday, 6 July 2015 at 20:50:19 UTC, Gary Willoughby wrote: How do you correctly implement a bidirectional range on a linked list? I have a linked list implementation and I've added a range interface to it but after a while I've realized it not quite right. The problem is when I call the save method of the forward range interface I don't get a copy I only get another view to the same state. So when i remove nodes from the original list the range becomes invalid. How can you implement such a range over a type whose state is accessed via pointers? Here's my implementation: https://github.com/nomad-software/etcetera/blob/master/source/etcetera/collection/linkedlist.d#L533 There's no requirement for a range to stay valid when the underlying container changes. std.container defines stable variants of the various insertion and removal operations. They promise not to invalidate any ranges. When the unstable variants are used, it's to be expected that ranges are invalidated. To make your removal methods stable, it may be enough to not free the removed node. That is, don't do this: https://github.com/nomad-software/etcetera/blob/master/source/etcetera/collection There's a doubly linked list in phobos: std.container.dlist; maybe look how things are done there: https://github.com/D-Programming-Language/phobos/blob/master/std/container/dlist.d Off topic: I think `@trusted:` is horrible. It's easy to forget that you're in a @trusted environment when editing things later. And even worse, you're trusting everything that's passed through template parameters.
Re: Correctly implementing a bidirectional range on a linked list?
On Monday, 6 July 2015 at 21:58:31 UTC, anonymous wrote: To make your removal methods stable, it may be enough to not free the removed node. That is, don't do this: https://github.com/nomad-software/etcetera/blob/master/source/etcetera/collection Looks like I messed up the URL. Here's the right one: https://github.com/nomad-software/etcetera/blob/master/source/etcetera/collection/linkedlist.d#L205-L206
Re: lovely compiler error message - incompatible types
On Thursday, 2 July 2015 at 17:33:29 UTC, Laeeth Isharc wrote: Any thoughts on what could be leading to the following: ./../../marketdata/source/pricebar.d(397): Error: incompatible types for ((bar.high) + (bar.low)): 'FixedDecimal!(int, 8)' and 'FixedDecimal!(int, 8)' ../../../marketdata/source/pricebar.d(399): Error: incompatible types for ((bar.high) + (bar.low)): 'FixedDecimal!(int, 8)' and 'FixedDecimal!(int, 8)' ../../../marketdata/source/pricebar.d(547): Error: incompatible types for ((trueHigh(bars)) - (trueLow(bars))): 'FixedDecimal!(int, 8)' and 'FixedDecimal!(int, 8)' FixedDecimal is a fixed decimal point struct that stores values as an int or long and takes number of decimal places as the second compile term argument. It's possible, if not likely I have made a mistake in implementing operator overloads. Any thoughts on whether this is the likely cause, and if so which ones are likely to be the problem? From the error messages it looks you didn't implement the operator overloads properly. You get the same message when FixedDecimal doesn't overload anything at all: struct FixedDecimal(T, uint n) {} void main() { FixedDecimal!(int, 8) a, b; auto c = a + b; /* line 5 */ } test.d(5): Error: incompatible types for ((a) + (b)): 'FixedDecimal!(int, 8u)' and 'FixedDecimal!(int, 8u)' You can get a more specific error by instantiating/calling things explicitly. For example, here I messed up the parameter type: struct FixedDecimal(T, uint n) { FixedDecimal opBinary(string op)(FixedDecimal!(T, 0)) { return FixedDecimal.init; } } void main() { FixedDecimal!(int, 8) a, b; auto c = a + b; /* line 11 */ auto d = a.opBinary!+(b); /* line 12 */ } test.d(11): Error: incompatible types for ((a) + (b)): 'FixedDecimal!(int, 8u)' and 'FixedDecimal!(int, 8u)' test.d(12): Error: function test.FixedDecimal!(int, 8u).FixedDecimal.opBinary!+.opBinary (FixedDecimal!(int, 0u) _param_0) is not callable using argument types (FixedDecimal!(int, 8u)) The error for line 11 just says that something went wrong. The one for line 12 is a little more helpful.
Re: time difference - beautify my code
On Thursday, 2 July 2015 at 19:03:49 UTC, dd0s wrote: i got a date t described in seconds from 1.1.1970, I.e., you have a unix timestamp. and i want to check if the current time is further than 12 hours from the given time t. the following code works but it's super ugly =S please give me some ideas how to make this code nicer :) private static bool sessionIsCurrent(long t) { DateTime dateTime = DateTime(1970, 1, 1) + dur!msecs(t*1000); dur!msecs(t*1000) - dur!seconds(t) - t.seconds Better yet (`to` from std.conv): auto dateTime = SysTime(unixTimeToStdTime(t)).to!DateTime; Or just go with SysTime instead of DateTime: auto dateTime = SysTime(unixTimeToStdTime(t)); DateTime curTime = DateTime() + dur!hnsecs(Clock.currStdTime()); Like above, use `to` to convert from SysTime to DateTime: auto curTime = Clock.currTime.to!DateTime; or just use a SysTime: SysTime curTime = Clock.currTime; return (curTime - dateTime) dur!msecs(1000*60*60*12); Like above, dur!msecs(1000*60*60*12) - dur!seconds(60*60*12) - dur!minutes(60*12) - dur!hours(12) - 12.hours } Putting it all together, removing the now pointless variable curTime, adding a pinch of immutable for the taste: private static bool sessionIsCurrent(long t) { immutable dateTime = SysTime(unixTimeToStdTime(t)); return (Clock.currTime - dateTime) 12.hours; } Final thoughts: You may want to check that t is not in the future. I'm not 100% sure if switching from DateTime to SysTime fixes a bug, introduces a bug, or doesn't make any difference. As far as I can tell, it doesn't change anything, because you're not dealing with different time zones.
Re: wrong struct alignment
On Wednesday, 1 July 2015 at 20:01:08 UTC, dd0s wrote: i have the following struct, and i expect it to have 30 bytes but sizeof tells me it has 32 bytes. dmd seems to still use 4byte alignment altough i specified to align 2bytes. struct netadr_t { align(2): inttype; // 0 intscope_id; // 4 short port; // 8 // -- this is 4 bytes instead of 2 intsock; // 10 union { ubyte[4]ip; // 14 ubyte[10] ipx; ubyte[16] ip6; } } since i'm interfacing with a c library the struct layout has to be equal :( Disclaimer: My understanding of all things alignment is limited. `pragma(msg, netadr_t.sock.offsetof);` prints 10LU, so port seems to really only take 2 bytes. The struct itself has padding at the end. You can eliminate that with an `align(1)` on the struct: align(1) struct netadr_t { align(2): ... }
Re: Same process to different results?
On Wednesday, 1 July 2015 at 17:13:03 UTC, Taylor Hillegeist wrote: string q = cast(string) (A.cycle.take(seg1len).array ~B.cycle.take(seg2len).array ~C.cycle.take(seg3len).array); q.writeln; I was wondering if it might be the cast? Yes, the cast is wrong. You're reinterpreting (not converting) an array of `dchar`s (UTF-32 code units) as an array of `char`s (UTF-8 code units). If you print the numeric values of the string, e.g. via std.string.representation, you can see that every actual character has three null bytes following it: import std.string: representation; writeln(q.representation); [65, 0, 0, 0, 97, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 97, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 97, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 98, 0, 0, 0, 66, 0, 0, 0, 98, 0, 0, 0, 67, 0, 0, 0, 99, 0, 0, 0, 67, 0, 0, 0, 99, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 99, 0, 0, 0, 67, 0, 0, 0, 99, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0] Use std.conv.to for less surprising conversions. And don't use casts unless you know exactly what you're doing.
Re: Map Purity
On Sunday, 28 June 2015 at 16:28:20 UTC, jmh530 wrote: Thanks for the reply. Two follow ups: 1) Does labeling a template as pure matter if the compiler infers it anyway? 2) Does the compiler also infer anything for @safe/nothrow in templates? 1) It means you can't instantiate the template function with arguments that would make it non-pure. 2) Yes, pure, nothrow, @safe, @nogc are all inferred.
Re: goroutines vs vibe.d tasks
On Tuesday, 30 June 2015 at 15:18:36 UTC, Jack Applegame wrote: Just creating a bunch (10k) of sleeping (for 100 msecs) goroutines/tasks. Compilers go: go version go1.4.2 linux/amd64 vibe.d: DMD64 D Compiler v2.067.1 linux/amd64, vibe.d 0.7.23 Code go: http://pastebin.com/2zBnGBpt vibe.d: http://pastebin.com/JkpwSe47 go version build with go build test.go vibe.d version built with dub build --build=release test.d Results on my machine: go: 168.736462ms (overhead ~ 68ms) vibe.d: 1944ms (overhead ~ 1844ms) Why creating of vibe.d tasks is so slow (more then 10 times)??? I think this might be a problem with vibe.d's `sleep`. Putting a `writeln(...);` there is a lot faster than `sleep`ing even the tiniest amount of time.
Re: Bug or feature?
On Monday, 29 June 2015 at 12:04:46 UTC, Jonathan M Davis wrote: You haven't declared an immutable constructor, so you can't construct an immutable Foo. That's not what's happening. Constructing an immutable Foo works just fine.
Re: Why D doesn't have an equivalent to C#'s readonly?
On Monday, 29 June 2015 at 22:11:16 UTC, sigod wrote: `new immutable(MyClass)()` is invalid code. It's perfectly fine, actually.
Re: Pure delegate not quite pure?
On Sunday, 28 June 2015 at 09:19:16 UTC, Tofu Ninja wrote: module main; import std.stdio; void main(string[] args) { auto d = foo(); writeln(d()); // prints 25 } auto foo() { int x = 4; pure int delegate() d = delegate() { return x*x; }; writeln(d()); // prints 16 x = 5; writeln(d()); // prints 25 return d; } I can see that after foo returns, then d will truly be pure as x will no longer be modifiable, but just before that, it seems d is not actually pure. Is this the intended behavior? Here's a similar example where it's a bit clearer what's going on: struct S { int x = 0; int d() pure {return ++this.x;} } void main() { S s; int delegate() pure d = s.d; import std.stdio; writeln(d()); /* prints 1 */ writeln(d()); /* prints 2 */ writeln(d()); /* prints 3 */ } `d` isn't all that pure, right? You're seeing the concept of weak purity in action. In D, the attribute `pure` really just means doesn't access global mutable state. The function is still allowed to mutate any arguments it gets, including hidden ones. Here the method `d` has a hidden `this` parameter, and it can mutate data through it. With a nested function, the enclosing context is passed via a hidden parameter. Properly/mathematically/strongly pure functions have additional requirements on top of being marked `pure`. Read more here: http://klickverbot.at/blog/2012/05/purity-in-d/
Re: how to string → uint* ?
On Sunday, 28 June 2015 at 01:57:46 UTC, xky wrote: hello. :-) when i was using DerelictSFML2( http://code.dlang.org/packages/derelict-sfml2 ), i got this problem. CSFML doc had 'setUnicodeString': CSFML_GRAPHICS_API void sfText_setUnicodeString ( sfText * text, const sfUint32 * string ) *'sfUint32' same 'unsigned int'. how to convert string → uint? i just try that, but not work. string test = 안녕, こんにちは; string* test_p = test; sfUint32* uintObject = cast(sfUint32*)test_p; sfText_setUnicodeString( , uintObject ); thanks, :) Don't try casting just because you guess it could maybe work. The best documentation for setUnicodeString I could find is this: https://github.com/SFML/CSFML/blob/master/include/SFML/Graphics/Text.h#L243 which is pretty bad. It doesn't say if unicode is UTF8/16/32. `sfUint32` hints at UTF32, so I'll go with that. A D `string` is in UTF8, so you'll have to convert it to a `dstring` which is in UTF32 (UTF16 would be `wstring`). You can use std.conv.to for that: string test = 안녕, こんにちは; dstring test32 = test.to!dstring; Alternatively, you can simply make `test` a dstring from the start: dstring test = 안녕, こんにちは; The documentation also doesn't say if the string has to be null-terminated. Since the function doesn't take a length, I'm assuming that it has to be. D strings (of all varieties) are generally not null-terminated. String literals are, though. So if you're passing a hard-coded string, you're fine. But if the string is user input or otherwise generated at run time, you have to add a null character at the end. There's std.string.toStringz for that, but I'm afraid it's for UTF8 only. So you'd have to go into the details yourself. I'm continuing with `test` as above, which is null-terminated, because it's from a literal. Alright, the data is properly set up (hopefully). Now we need to get a `const sfUint32*` out of the `dstring`. I'm assuming `sfUint32` is just an alias for `uint`. So we need a `const uint*`. By convention, when a function takes a pointer and says it's a string, the pointer points to the first character of the string. `dstring` is an alias for `immutable(dchar)[]`, i.e. a dynamic array of `immutable dchar`s. Dynamic arrays have the `.ptr` property which is a pointer to the first element; exactly what we need. `test.ptr` is an `immutable(dchar)*` though, not a `const uint*`. `dchar` and `uint` have the same size. And any bit-pattern is valid for a `uint`, so `dchar`s can be reinterpreted as `uints` without problem. There's std.string.representation which does just that. Combining `representation` with `.ptr` you get an `immutable(uint)*` which implicitly converts to `const uint*`: dstring test = 안녕, こんにちは; sfText_setUnicodeString( , test.representation.ptr); That's it. Another gripe about the documentation, though: It also doesn't say if the pointer has to be persistent or not. The string data may be garbage collected once it goes out of scope, so I'm betting on the pointer not having to be persistent, here.
Re: Program exited with code -11
On Tuesday, 23 June 2015 at 07:57:26 UTC, Charles Hawkins wrote: Sigh. I'm probably doing something stupid. I tried full paths: dmd -I+/home/charles/projects/d/mylib/source/mylib/ myprog.d What's that plus sign doing there? Looks wrong. /home/charles/projects/d/mylib/build/libmylib.a Same result. myprog.d(4) Error: module mylib is in file 'mylib.d' which cannot be read Statement in myprog is: import mylib;
Re: core.exception.InvalidMemoryOperationError@(0) on File Reading.
On Monday, 22 June 2015 at 20:30:40 UTC, David DeWitt wrote: I am getting an core.exception.InvalidMemoryOperationError@(0) auto recs = f // Open for reading .byLineCopy(); .array; //Here is where is appears to be happening. I have narrowed it down to the .array. I am wondering if there is some common issue I may be experiencing or if there is a better solution? You may be hitting issue 14005/14578 with the underlying issue 13856. https://issues.dlang.org/show_bug.cgi?id=14005 https://issues.dlang.org/show_bug.cgi?id=14578 https://issues.dlang.org/show_bug.cgi?id=13856 You can try using the current development version of phobos from git. I think the InvalidMemoryOperationError shouldn't happen with that anymore. If it still happens with git head phobos, it's probably not 14005/14578. Alternatively, you can use std.stdio.readln directly, but be aware of issue 13856.
Re: How do I make my class iterable?
On Monday, 22 June 2015 at 18:44:22 UTC, Assembly wrote: I'm using this, thanks for all. Can someone clarify how does opApply() works? I assume it's called every iteration and as opApply() has a loop does it means the number of iteration ran actually is the ones from foreach() is 2*n where n is the number of elements in the array, is this right? opApply is called only once. The body of the foreach is passed to opApply as a delegate. The opApply implementation runs the supplied foreach body, possibly in a loop. Every such call is an iteration of the foreach loop. With opApply this: foreach(x; iterable) {/* do something with x */} gets rewritten to this: iterable.opApply((x) {/* do something with x */});
Re: Defining constant values in struct
On Tuesday, 16 June 2015 at 21:17:37 UTC, tcak wrote: As far as I known, when I define a string with enum and it is used at different parts of code, that string is repeated again and again in executable file instead of passing a pointer to string. So, using enum with string doesn't seem like a good idea. I'm not sure how true that is. For example, this prints the same address twice: import std.stdio; enum e = foo; void main() { auto a = e; auto b = e; writeln(a.ptr); writeln(b.ptr); } In contrast, it prints two different addresses when e is defined as `[1, 2, 3]` instead. [...] [code] struct TableSchema{ const string TABLE = users; struct FieldTypes{ const string ID = BIGINT; } const string CREATESQL = ... id ~ FieldTypes.ID ~ ...; } [/code] But compiler doesn't allow me to access FieldTypes.ID. It says that it needs `this`. I tried with `static shared`, used `class` instead of `struct` etc. But couldn't have come up with a nice solution. `static immutable` is where it's at.
Re: Casting MapResult
On Monday, 15 June 2015 at 15:10:24 UTC, jmh530 wrote: float[] exp(float[] x) { auto y = x.map!(a = exp(a)); cast(float[]) y; return y; } But I get an error that I can't convert MapResult!(__lambda2, float[]) to float[]. So I suppose I have two questions: 1) am I screwing up the cast, or is there no way to convert the MapResult to float[], 2) should I just not bother with map (I wrote an alternate, longer, version that doesn't use map but returns float[] properly). First off: Don't cast unless you know exactly what you're doing. It's easy to stumble into undefined behaviour land with casts. To answer the question: You can convert from from MapResult to float[], but not with a cast. Instead, use std.array.array: import std.array: array; return x.map!(std.math.exp).array;
Re: __traits getMember is context sensetive?
On Sunday, 14 June 2015 at 10:10:51 UTC, ketmar wrote: i.e. when it need a value in compile time. the interpreter is invoked, it evaluates (interprets) the given code (function or template instantiation), and then it returns result (or raises an error). One important thing I didn't see stated clearly by anyone in here: CTFE may run at compile time but it follows the same rules as run time evaluation (plus some restrictions). This means, you can't use dynamic values (e.g. function parameters) in static contexts (e.g. __traits). Example: int f(int x) { if (__ctfe) { enum e = x; /* nope, not even during CTFE */ alias t = some_template!x; /* nope */ pragma(msg, x); /* nope */ } return x; } enum result = f(1); /* CTFE-ing f */
Re: __traits getMember is context sensetive?
On Sunday, 14 June 2015 at 10:41:24 UTC, JDemler wrote: So if i want to use parameters in a static context at compile time i have to pass them as template parameters? Yes, template parameters are fine.
Re: Qualified destructors / immutable objects
To come back to destructors and immutable objects: Even without the default initialized variables issue it is possible to modify immutable data: struct S { int[] bar; ~this() { bar[0] = 123; } } void foo(immutable(int[]) i) { immutable(S) s = immutable S(i); } void main() { immutable array = [42, 42]; foo(array); // fails assert(array == [42, 42]); } I'm not sure whether ~this() should be forbidden to modify immutable data. Consider e.g. some fields need to be free'd. If someone else is using references to such a field after ~this() - segfault, but it could be seen as analogon to the list of undefined operations on pointer to GC memory. Additionally the same happens already for stack allocated fields like int[4] inside a (mutable/const/immutable) struct.
Re: Conditional Compilation Multiple Versions
On Saturday, 13 June 2015 at 00:47:37 UTC, Mike Parker wrote: // config.d version(One) enum One = true; else enum One = false; version(Two) enum Two = true; else enum Two = false; // other.d import config; static if(One || Two) { ... } Taking it one step further: template Version(string name) { mixin( version(~name~) enum Version = true; else enum Version = false; ); } static if(Version!One || Version!Two) { ... }
Re: char[][] to std::vectorstd::string - DIP or dmd-issue?
On Saturday, 13 June 2015 at 15:21:19 UTC, Dennis Ritchie wrote: Hello, everyone! I like to work with arrays of strings like `string[] strArray`, but unfortunately, they are immutable. I do not like to work with arrays of strings such as `char[][] strArray`, because it is necessary to apply the method .dup each substring to make them work :) Huh? You mean with string literals? That would be a rather silly reason to avoid `char[]`. Please show an example of .dup you'd like to avoid. I understand that the type of `string[]` to D is a simple data type than `char[][]`, Are you saying that `string[]` is simpler than `char[][]`? That's not true: `string` is an alias for `immutable(char)[]`, so `string[]` is the same as `immutable(char)[][]`. but it seems to me that the problem is solved in C++: std::vectorstd::string stdArray; I wish to propose the creation of new types of data D: str, wstr, dstr, which will be the analogs of C++ `std::vectorstd::string`. Before jumping to a solution, please elaborate on the perceived problem. I have a feeling that there is none.
Re: char[][] to std::vectorstd::string - DIP or dmd-issue?
On Saturday, 13 June 2015 at 17:02:06 UTC, Dennis Ritchie wrote: On Saturday, 13 June 2015 at 16:20:46 UTC, anonymous wrote: [...] Yeah, that would be neat. But typing out .dup isn't that bad, and converting a `string[]` to a `char[][]` is simple: import std.conv: to; auto a = [foo].to!(char[][]); Yes, but it is not suitable for multidimensional array of strings. Please show how it is not. Seems to work just fine. [...] And why in C++ is running `std::vectorstd::string` ? Really in D can not do something like that? Maybe a new type will not solve anything, but there should be other ways to do in D analogue strings of C++. Your definitions of something like that and other ways are unreasonably narrow, in my opinion. Typing out .dup is D's way to do mutable strings. You just don't like it.
Re: char[][] to std::vectorstd::string - DIP or dmd-issue?
On Saturday, 13 June 2015 at 15:58:44 UTC, Dennis Ritchie wrote: On Saturday, 13 June 2015 at 15:45:34 UTC, anonymous wrote: Before jumping to a solution, please elaborate on the perceived problem. I have a feeling that there is none. Do you like to write? char[][] strArray = [foo.dup, bar.dup, baz.dup]; Ok. That's all you're on about? Basically you'd like this: char[] s = foo; and this: char[][] a = [[foo]]; etc. Yeah, that would be neat. But typing out .dup isn't that bad, and converting a `string[]` to a `char[][]` is simple: import std.conv: to; auto a = [foo].to!(char[][]); I suggest that such an option: str[] strArray = [foo, bar, baz]; I don't see how adding a new builtin type `str` would solve anything.
Re: char[][] to std::vectorstd::string - DIP or dmd-issue?
On Saturday, 13 June 2015 at 16:09:58 UTC, Dennis Ritchie wrote: On Saturday, 13 June 2015 at 15:45:34 UTC, anonymous wrote: [...] Are you saying that `string[]` is simpler than `char[][]`? That's not true: `string` is an alias for `immutable(char)[]`, so `string[]` is the same as `immutable(char)[][]`. On Monday, 18 May 2015 at 13:14:38 UTC, Steven Schveighoffer wrote: But really, a string is immutable. There's not a way around that. A string is the most basic level of array primitive, not even mutable arrays of non-char types have that, and it's an annoyance. From there, you have to build the data out of ROM into the heap. http://forum.dlang.org/post/mjctql$j19$1...@digitalmars.com I don't understand what you're trying to say with that quote.
Re: Qualified destructors / immutable objects
Is there an existing issue on issue.dlang.org? If not can you report it https://issues.dlang.org/show_bug.cgi?id=10376
Re: Qualified destructors / immutable objects
no need for ~this() to modify immutable data: class C { int a; this(int a) { this.a = a; } } struct S { C elem = new C(42); } void main() { import std.stdio; immutable(S) s1; // Error: cannot modify immutable expression s1.elem.a // s1.elem.a = 43; writeln(s1.elem.a); S s2; s2.elem.a = 123; writeln(s1.elem.a); } Prints: 42 123
Re: Qualified destructors / immutable objects
I cannot find a way to actually modify immutable memory with it... a.d: class C { int a; this(int a) { this.a = a; } } struct S { int x; C elem = new C(42); ~this() { import std.stdio; writeln(mutable ~this()); x = 1; elem.a = 123; } } void foo() { S s2; } void main() { import std.stdio; immutable(S) s1; // Error: cannot modify immutable expression s1.elem.a // s1.elem.a = 43; writeln(s1.elem.a); foo(); writeln(s1.elem.a); } dmd a.d ./a prints: 42 mutable ~this() 123 mutable ~this() Is it a bug? I'll wait with a bug report, but I think this should be forbidden.
Re: Reading array of integers readln performance issues
On Thursday, 11 June 2015 at 19:56:00 UTC, kerdemdemir wrote: Can I achieve something faster than code below? auto peopleMoney = stdin.readln().split().map!(a = to!int(a)).array(); if (peopleMoney.length == 20) writeln(:(); `std.array.split` is eager. It may be faster if you use the lazy `std.algorithm.splitter`: auto peopleMoney = stdin.readln().splitter().map!(to!int).array(); [...] Ps: I do not want to bore you with long code, but I am sending link to whole program anyway if anyone need. http://codeforces.com/contest/549/submission/11537206 Seeing that you get the number of elements beforehand, you can preallocate the array, avoiding relocations of the data as elements are appended: peopleMoney = new int[peopleCount]; copy(stdin.readln().splitter().map!(to!int), peopleMoney); But these are tweaks. They may improve performance a little, but it won't be drastic. And anyway, I find it hard to believe that the original version takes more than a second to parse the input. Maybe try returning from the function in addition to printing :(. Otherwise the program goes on, and the site may not show the output if the program as a whole took too long.
Re: Is it possible to add items to the arrays and hashes at compile time?
On Wednesday, 10 June 2015 at 17:00:34 UTC, Dennis Ritchie wrote: Isnt it possible to come up with the interpreter compile-time, which will determine the operating time of the program at runtime at compile time. Sounds like the halting problem. So, no, generally this is not possible.
Re: Replacing nested loops foreach using map/each/etc
On Monday, 25 May 2015 at 17:52:09 UTC, Dennis Ritchie wrote: But why is the solution breaks down when `s = 1` ? :) import std.stdio, std.algorithm, std.range; int c; const x = 12, y = 65, z = 50, s = 10; Which is it, now? 4 or 5 zeros? void solve(Range)(Range r) { cartesianProduct(r, r, r).filter!(i = i[0] * (y + 3 * z) + i[1] * (y + 2 * z) + i[2] * (y + z) == s).each!dout; } void main() { auto a = iota(0, x + 1).array; solve(a); writefln(`%s total`, c); } void dout(Tuple)(Tuple idx) { ++c; } - http://rextester.com/XGDL26042 What do you mean it breaks down? Your original code doesn't print anything for s = 10_000 or s = 100_000, either.
Re: ctfe and static arrays
On Sunday, 24 May 2015 at 17:35:39 UTC, Jay Norwood wrote: I'm a bit confused by the documentation of the ctfe limitations wrt static arrays due to these seemingly conflicting statements, and the examples didn't seem to clear anything up. I was wondering if anyone has examples of clever things that might be done with static arrays and pointers using ctfe. 2.Executed expressions may not reference any global or local static variables. C-style semantics on pointer arithmetic are strictly enforced. Pointer arithmetic is permitted only on pointers which point to static or dynamic array elements. Static array has a special meaning. It does not mean static variable with an array type. Static arrays are those of the form Type[size]. That is, the size is known statically. Examples: 1) static int[5] x; -- x is a static variable with a static array type 2) static int[] x; -- static variable, dynamic array 3) int[5] x; -- non-static variable, static array 4) int[] x; -- non-static variable, dynamic array So, CTFE can't handle examples 1 and 2, because they're static variables. 3 and 4 are fine.
Re: ctfe and static arrays
On Sunday, 24 May 2015 at 18:14:19 UTC, anonymous wrote: Static array has a special meaning. It does not mean static variable with an array type. Static arrays are those of the form Type[size]. That is, the size is known statically. PS: You may also see the term fixed-size array which means the same as static array but avoids the confusion with static variables.
Re: ctfe and static arrays
On Sunday, 24 May 2015 at 20:53:03 UTC, Jay Norwood wrote: On Sunday, 24 May 2015 at 18:14:19 UTC, anonymous wrote: [...] 1) static int[5] x; -- x is a static variable with a static array type 2) static int[] x; -- static variable, dynamic array 3) int[5] x; -- non-static variable, static array 4) int[] x; -- non-static variable, dynamic array So, CTFE can't handle examples 1 and 2, because they're static variables. 3 and 4 are fine. From your description, I would expect this to fail since I would expect it to be included in 2 above, but it builds and prints ok. import std.stdio; struct A { int me; int next; int prev;} A[] initA(int n) { if (!__ctfe){ assert(false); } A[] v = new A[n]; foreach (i; 0..n){ v[i].me = i; v[i].prev = i-1; v[i].next = i+1; } return v; } int main(string[] argv) { enum int N = 100; static A[] linkedA = initA(N); I'm guessing you mean that this line would fall under case 2. Only the right hand side, i.e. initA(N), is done in CTFE here. The result is then used to initialize linkedA -- that step is not CTFE anymore. You're not referencing any static variable in initA, so everything's fine.
Re: Python's features, which requires D
On Saturday, 23 May 2015 at 20:25:18 UTC, Dennis Ritchie wrote: This does not work! enum n1 = 5; writeln(stdin.byLine .map!(line = line.split( ).map!(x = to!int(x))) ); - http://rextester.com/VGHZF81178 The code itself is ok. That site has broken newlines. You can see here that std.ascii.newline is different from what the site actually feeds to the program: http://rextester.com/IIT33098. You can work around that by passing the correct line terminator to byLine: http://rextester.com/SOW95508.
Re: Python's features, which requires D
On Saturday, 23 May 2015 at 21:08:19 UTC, Dennis Ritchie wrote: Perhaps that's not the site, and in Windows. That's what gives me in CMD: 456 4 4 8 99 456 [[456, 4, 4, 8, 99, 456]13 546 std.conv.ConvException@C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(2013): Unexpected end of input when converting from type char[] to type int That's a different issue. Works fine for me in wine. You may be typing spaces before/after the numbers. That would result in empty items from `split`. You can `filter` empty items out, or you can use the unary version of `split` (not passing the delimiter) which, as per documentation, splits at whitespace and produces no empty words.
Re: -vgc Info ok?
On Monday, 18 May 2015 at 14:34:38 UTC, ketmar wrote: it can throw out of range error, which is `new`ed. Array access can also throw RangeError, but -vgc and @nogc don't mind that: void main() @nogc { int[] a; auto b = a[0]; }
Re: Const is already there. It cannot deduce it
On Sunday, 17 May 2015 at 21:34:21 UTC, tcak wrote: [code] void test(D)( const D data ) if( is(D: shared(char[]) ) ) { } void main() { char[] text = new char[4]; text[0] = 'a'; text[1] = 'b'; text[2] = 'c'; text[3] = 'd'; auto t = cast( shared(const(char[])) )text[1..2]; test( t ); } [/code] Error Message: template main.test cannot deduce function from argument types !()(shared(const(char[]))) `t` is already shared(const(char[])), and `test` is expecting const shared(char[]). Aren't they already same? Per the template constraint, test needs a type D that implicitly converts to shared(char[]). Even when the top const is removed from typeof(t), there's still const in there: shared(const(char)[]). That isn't implicitly convertible to shared(char[]). Add const in the constraint and it works: if( is(D: shared(const char[])) ) -- Together with this question, I want to ask whether there is a way to check only being `shared`, is(T == shared) only being `const`, is(T == const) or only being `char[]` I guess you mean to ignore any qualifiers of the array itself and the element type. We have std.traits.Unqual, but that only removes qualifiers from the top level. As far as I know, we don't have anything like a DeepUnqual which would allow you to write is(DeepUnqual!T == char[]). You could write one. Or you can get into the more advanced versions of the IsExpression: is(T == E[], E) is(Unqual!E == char) of a template variable (D of `test` in this case)?