Re: string to wchar*?
On Sun, Jun 04, 2017 at 12:45:23AM +, Stanislav Blinov via Digitalmars-d-learn wrote: [...] > No, it shouldn't. char* et al. are not string types in D. > to!(char*)(string) just doesn't make sense. If you need to convert between D strings and char*, wchar*, etc., e.g., for interfacing with C/C++ APIs, take a look at std.string.toStringz and std.string.fromStringz. Do not use casts or std.conv.to because D does not treat character pointers as string, unlike C/C++. T -- Leather is waterproof. Ever see a cow with an umbrella?
Re: How to Compare 2 objects of the same class
On Sat, Jun 03, 2017 at 10:38:31PM +, Mark via Digitalmars-d-learn wrote: [...] > Ok. So by using '==' it should compare the addresses of the objects? [...] No, `==` is for comparing the *contents* of the objects. You need to implement opEquals() for the objects being compared in order to define how the contents will be compared. If you want to compare *addresses*, use `is`: Object a = new Object(...); Object b = a; // b is a reference to the same object as a assert(b is a); In this case there is no need to implement anything else, since comparing addresses is simple. T -- "No, John. I want formats that are actually useful, rather than over-featured megaliths that address all questions by piling on ridiculous internal links in forms which are hideously over-complex." -- Simon St. Laurent on xml-dev
Re: std.path.buildPath
On Saturday, 3 June 2017 at 14:12:03 UTC, Russel Winder wrote: From the manual page on std.path.buildPath: writeln(buildPath("foo", "bar", "baz")); // "foo/bar/baz" writeln(buildPath("/foo/", "bar/baz")); // "/foo/bar/baz" writeln(buildPath("/foo", "/bar")); // "/bar" I have no idea what drugs the person who chose that last one to be correct semantics was on at the time, but it was some seriously bad stuff. "If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped." I cannot find any excuse for this to be even remotely reasonable. What is your expected behavior? Throw an exception? You can't really append an absolute path to another.
Re: string to wchar*?
On Saturday, 3 June 2017 at 23:36:18 UTC, Mike B Johnson wrote: https://dlang.org/phobos/std_utf.html#toUTF16z This didn't work. More errors than the first. Works for me: void main() { import std.conv; import std.stdio; import core.stdc.wchar_; import core.stdc.stdio; auto f = fopen("hello.bin", "w,ccs=UTF16LE"); scope (exit) fclose(f); import std.utf; string hello = "Привет"; wchar bom = '\ufeff'; auto str = hello.toUTF16z; fputwc(bom, f); while (str && *str) { fputwc(*str, f); ++str; } } $ rdmd wchartest.d $ file hello.bin hello.bin: Little-endian UTF-16 Unicode text, with no line terminators $ hexdump hello.bin 000 feff 041f 0440 0438 0432 0435 0442 $ iconv -f UTF-16LE hello.bin Привет In any case, it conv should work. No, it shouldn't. char* et al. are not string types in D. to!(char*)(string) just doesn't make sense.
Re: string to wchar*?
On 06/03/2017 04:36 PM, Mike B Johnson wrote: On Saturday, 3 June 2017 at 23:09:56 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 22:54:22 UTC, Mike B Johnson wrote: How to convert a string to wchar*? C-style null-terminated wchar*? https://dlang.org/phobos/std_utf.html#toUTF16z This didn't work. More errors than the first. In any case, it conv should work. Worked for me: import std.stdio; import std.utf; void main() { string s = "hello"; s ~= " world"; auto w = s.toUTF16z; // Rough length estimate (assuming that all characters in this // UFT-16 encoded string are 2-byte long) // And +1 is for the "null char" auto bytes = (cast(ubyte*)w)[0 .. s.length * 2 + 1]; writefln("%(%02x %)", bytes); } Output: 68 00 65 00 6c 00 6c 00 6f 00 20 00 77 00 6f 00 72 00 6c 00 64 00 00 Ali
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 23:32:44 UTC, Ali Çehreli wrote: ... Ali Awesome, that might be handy in the near future. Thanks.
Re: string to wchar*?
On Saturday, 3 June 2017 at 23:09:56 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 22:54:22 UTC, Mike B Johnson wrote: How to convert a string to wchar*? C-style null-terminated wchar*? https://dlang.org/phobos/std_utf.html#toUTF16z This didn't work. More errors than the first. In any case, it conv should work.
Re: How to Compare 2 objects of the same class
On 06/03/2017 03:38 PM, Mark wrote: > Ok. So by using '==' it should compare the addresses of the objects? That's the default behavior. You can change it with opEquals: http://ddili.org/ders/d.en/object.html#ix_object.opEquals I think you want to use the 'is' operator: http://ddili.org/ders/d.en/class.html#ix_class.is,%20operator It's better because 'is' can be used with null variables. > about 45 lines, that might be a lot of code > for a post. Yeah. Minimal is good. :) > how Can I obtain the actual memory address of a class? You mean the memory address of a class object. ;) It's achieved with the special semantics of casting the class variable to void*: class C { int i; } void info(C o) { import std.stdio; writefln(" Object at %s,\n" ~ "i member at %s\n", cast(void*)o, &o.i); } void main() { auto a = new C(); auto b = new C(); a.info(); b.info(); } Sample output on my system: Object at 7F810AA53060, i member at 7F810AA53070 Object at 7F810AA53080, i member at 7F810AA53090 The difference of 16 bytes are from vtbl pointer and the monitor. (I think the latter is a kind of a lizard, which nobody actually uses. :p) Ali
Re: string to wchar*?
On Saturday, 3 June 2017 at 22:54:22 UTC, Mike B Johnson wrote: How to convert a string to wchar*? C-style null-terminated wchar*? https://dlang.org/phobos/std_utf.html#toUTF16z
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 22:53:51 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 22:38:31 UTC, Mark wrote: In the future I'll include a compilable example. I was having problems with a class I made which is about 45 lines, that might be a lot of code for a post. You can use external resources such as: https://d.godbolt.org/ https://dpaste.dzfl.pl to paste code there and then just post a link to a paste here. I'll keep that in mind, thanks.
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 22:52:42 UTC, Mark wrote: Thanks again. Nevermind, I got it.
string to wchar*?
How to convert a string to wchar*? string s; to!(wchar*)(s) gives phobo's deduction problems. \dmd2\windows\bin\..\..\src\phobos\std\conv.d(194): Error: template std.conv.toImpl cannot deduce function from argument types !(wchar*)(string), candidates are: \dmd2\windows\bin\..\..\src\phobos\std\conv.d(435): std.conv.toImpl(T, S)(S value) if (isImplicitlyConvertible!(S, T) && !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) \dmd2\windows\bin\..\..\src\phobos\std\conv.d(549): std.conv.toImpl(T, S)(ref S s) if (isStaticArray!S) \dmd2\windows\bin\..\..\src\phobos\std\conv.d(565): std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(typeof(S.init.opCast!T()) : T) && !isExactSomeString!T && !is(typeof(T(value \dmd2\windows\bin\..\..\src\phobos\std\conv.d(616): std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == struct) && is(typeof(T(value \dmd2\windows\bin\..\..\src\phobos\std\conv.d(665): std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == class) && is(typeof(new T(value
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 22:38:31 UTC, Mark wrote: In the future I'll include a compilable example. I was having problems with a class I made which is about 45 lines, that might be a lot of code for a post. You can use external resources such as: https://d.godbolt.org/ https://dpaste.dzfl.pl to paste code there and then just post a link to a paste here.
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 22:38:31 UTC, Mark wrote: ... Thanks. Actually, I got another question, how Can I obtain the actual memory address of a class? I'll still need to solve the problem of taking ints/floats/reals etc., as well as structs and classes and sending them right/left in the BST. :/ Thanks again.
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 20:24:44 UTC, ag0aep6g wrote: By default, they act the same. But you can change how `==` behaves by overriding `opEquals`. You cannot override `is`. Ok. So by using '==' it should compare the addresses of the objects? I think I didn't include the other file as an argument on the command line (Oops!) I'm using dmd v2.074.0. In the future I'll include a compilable example. I was having problems with a class I made which is about 45 lines, that might be a lot of code for a post. But it seems to work now. This is good, I can have the comparisons work for any type without doing backflips. Thanks.
OT: RAII pointers
On Saturday, 3 June 2017 at 21:46:45 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 21:39:54 UTC, Moritz Maxeiner wrote: It's always true, because I explicitly wrote *might*, not *will*, to indicate that it depends on your use case. Your example is a common use case where you can't skip the check. Programmers and their tight-binding logic... - Honey, please buy a loaf of bread. If there are eggs, buy a dozen. ... - Hello, do you have eggs? - Yes. - Dozen loaves of bread, please. ;) That usually happens when two sides interpret an ambiguous statement ;)
Re: RAII pointers
On Saturday, 3 June 2017 at 21:39:54 UTC, Moritz Maxeiner wrote: On Saturday, 3 June 2017 at 21:16:08 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 20:53:05 UTC, Moritz Maxeiner wrote: Quite, but if you backtrack to my initial statement, it was about ptr not being/becoming null (implicitly) in the first place, which *might* allow you to skip the check (if you don't set it to null via external means, such as memcpy, move, etc). It's only true as long as you have full control of the source. Once you're using libraries and generic code, it's possible that it's out of your hands: It's always true, because I explicitly wrote *might*, not *will*, to indicate that it depends on your use case. Your example is a common use case where you can't skip the check. Programmers and their tight-binding logic... - Honey, please buy a loaf of bread. If there are eggs, buy a dozen. ... - Hello, do you have eggs? - Yes. - Dozen loaves of bread, please. ;)
Re: RAII pointers
On Saturday, 3 June 2017 at 21:16:08 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 20:53:05 UTC, Moritz Maxeiner wrote: Quite, but if you backtrack to my initial statement, it was about ptr not being/becoming null (implicitly) in the first place, which *might* allow you to skip the check (if you don't set it to null via external means, such as memcpy, move, etc). It's only true as long as you have full control of the source. Once you're using libraries and generic code, it's possible that it's out of your hands: It's always true, because I explicitly wrote *might*, not *will*, to indicate that it depends on your use case. Your example is a common use case where you can't skip the check.
Re: RAII pointers
On Saturday, 3 June 2017 at 20:53:05 UTC, Moritz Maxeiner wrote: On Saturday, 3 June 2017 at 20:25:22 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 20:13:30 UTC, Moritz Maxeiner wrote: Calling std.algorithm.move is explicit programmer intent, I consider that about as accidental as calling memcpy with a source full of zeroes. In any case, having that check in the destructor is fairly cheap, so better safe than sorry (and include it). Yes, it's explicit. Destructor call is still implicit though, and it better not be performing null dereference or something equally nasty :) Quite, but if you backtrack to my initial statement, it was about ptr not being/becoming null (implicitly) in the first place, which *might* allow you to skip the check (if you don't set it to null via external means, such as memcpy, move, etc). It's only true as long as you have full control of the source. Once you're using libraries and generic code, it's possible that it's out of your hands: import core.stdc.stdio; import std.exception; // external library struct RingBuffer(T,size_t size) { T[size] values = T.init; // the culprit // interface snipped... } // own code struct FileWrapper { FILE* file; @disable this(); @disable this(this); this(FILE* file) { enforce(file); this.file = file; } ~this() { fclose(file); } } void main() { // whoops, segfault RingBuffer!(FileWrapper,8) container; }
Re: RAII pointers
On Saturday, 3 June 2017 at 20:25:22 UTC, Stanislav Blinov wrote: On Saturday, 3 June 2017 at 20:13:30 UTC, Moritz Maxeiner wrote: Calling std.algorithm.move is explicit programmer intent, I consider that about as accidental as calling memcpy with a source full of zeroes. In any case, having that check in the destructor is fairly cheap, so better safe than sorry (and include it). Yes, it's explicit. Destructor call is still implicit though, and it better not be performing null dereference or something equally nasty :) Quite, but if you backtrack to my initial statement, it was about ptr not being/becoming null (implicitly) in the first place, which *might* allow you to skip the check (if you don't set it to null via external means, such as memcpy, move, etc).
Re: RAII pointers
On Saturday, 3 June 2017 at 20:13:30 UTC, Moritz Maxeiner wrote: Calling std.algorithm.move is explicit programmer intent, I consider that about as accidental as calling memcpy with a source full of zeroes. In any case, having that check in the destructor is fairly cheap, so better safe than sorry (and include it). Yes, it's explicit. Destructor call is still implicit though, and it better not be performing null dereference or something equally nasty :)
Re: How to Compare 2 objects of the same class
On 06/03/2017 10:02 PM, Mark wrote: auto A = new Box(); auto B = new Box(); if(A.opEquals(B)) {} gives the error test.o:(.data.rel.ro+0x18): undefined reference to `_D5Stack12__ModuleInfoZ' collect2: error: ld returned 1 exit status Error: linker exited with status 1 Your code works for me (when adding `class Box {}` and a `main` function). An "undefined reference" error can mean that you forgot to include a module on the command line. if(Object.opEquals(A,B) gives test.d(10): Error: function object.Object.opEquals (Object o) is not callable using argument types (Box, Box) Yeah, that's not how you do it. How do I got about comparing two objects then?? Thanks. Just use the usual equality operator: `==`. Or if you want to check for identity, use the binary `is` operator. class Box {} void main() { auto A = new Box(); auto B = new Box(); if (A == B) {} if (A is B) {} } By default, they act the same. But you can change how `==` behaves by overriding `opEquals`. You cannot override `is`.
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 20:02:13 UTC, Mark wrote: On Saturday, 3 June 2017 at 19:57:47 UTC, Mark wrote: Hello again. I'm designing a template version of a BST. Because of this, I want to be able to compare if two objects of the same class type are references to the same anonymous class on the heap somewhere. Example: Not sure what happened there. Anyways, example: auto A = new Box(); auto B = new Box(); if(A.opEquals(B)) {} gives the error test.o:(.data.rel.ro+0x18): undefined reference to `_D5Stack12__ModuleInfoZ' collect2: error: ld returned 1 exit status Error: linker exited with status 1 if(Object.opEquals(A,B) gives test.d(10): Error: function object.Object.opEquals (Object o) is not callable using argument types (Box, Box) How do I got about comparing two objects then?? Thanks. Could you please systematically post compilable code? It is very hard to say anything without even seeing what you're struggling with.
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 20:02:13 UTC, Mark wrote: On Saturday, 3 June 2017 at 19:57:47 UTC, Mark wrote: Hello again. I'm designing a template version of a BST. Because of this, I want to be able to compare if two objects of the same class type are references to the same anonymous class on the heap somewhere. Example: Not sure what happened there. Anyways, example: auto A = new Box(); auto B = new Box(); if(A.opEquals(B)) {} gives the error test.o:(.data.rel.ro+0x18): undefined reference to `_D5Stack12__ModuleInfoZ' collect2: error: ld returned 1 exit status Error: linker exited with status 1 if(Object.opEquals(A,B) gives test.d(10): Error: function object.Object.opEquals (Object o) is not callable using argument types (Box, Box) How do I got about comparing two objects then?? Thanks. I think that the error is unrelated. Which dmd do you use ? Otherwise, opEquals (or just == ) is well the way to follow. By default Object.opEquals just compare the Objects addresses. If you want to perform a deep comparison (i.e the members) you have to override opEquals.
Re: RAII pointers
On Saturday, 3 June 2017 at 19:55:30 UTC, ag0aep6g wrote: On 06/03/2017 09:37 PM, Moritz Maxeiner wrote: Of course, but AFAIK you'd need to explicitly assign it to an object, so `ptr` won't null by accident, but only by explicit programmer intent (same as overwriting the memory the object lives in via things like `memcpy`); and you can always screw things intentionally (you could also assign some invalid value to the pointer via `memcpy`). I'd say `.init` can easily happen accidentally. Especially when `@disable this(this);` is involved. When you can't copy, you may have to move sometimes. But std.algorithm.move overwrites the old location with `.init`, assuming that `.init` can safely be destroyed. Calling std.algorithm.move is explicit programmer intent, I consider that about as accidental as calling memcpy with a source full of zeroes. In any case, having that check in the destructor is fairly cheap, so better safe than sorry (and include it).
Re: Guide - Migrating from std.experimental.ndslice to mir-algorithm
On Saturday, 3 June 2017 at 05:21:13 UTC, 9il wrote: On Friday, 2 June 2017 at 16:08:20 UTC, Zz wrote: Hi, Just tried migrating from std.experimental.ndslice to mir-algorithm. Is there a guide on how migrate old code? I used the following imports before and using then with ndslice. import std.experimental.ndslice; import std.algorithm : each, max, sort; import std.range : iota, repeat; simplified example of how it was used. auto a = cr.iota.sliced(r, c); auto b = a.reshape(c, r).transposed!1; auto c = a.reversed!1; auto d = a.reshape(c, r).transposed!1.reversed!1; auto f = new int[cr].sliced(r, c); auto h = f.transposed(1); how can I do the following in mir-algorithm. Note: I will be going through the documentation. Zz Hello Zz, std.experimental.ndslice -> mir.ndslice std.range : iota, repeat -> mir.ndslice.topology: iota, repeat; std.algorithm : each; -> mir.ndslice.algorithm: each; std.algorithm : max; -> mir.utility: max; std.algorithm : sort; -> mir.ndslice.sorting: sort; Note, that Mir functions has different semantics compared with Phobos! For example, each iterates deep elements, so should be combined with `pack` to iterates rows instead of elements. Ndslices work with Phobos functions but it is suggested to use Mir analogs if any. // Mir's iota! It is already 2D ndslice :-) auto a = [r, c].iota; auto b = a // returns flattened iota, a has Contiguous kind, // so the result type would be equal to `iota(r*c)` .flattened // convert 1D iota ndslice to 2D iota ndslice .sliced(c, r) // It is required to use transposed // Convert ndslice kind from Contiguous to Universal. .universal // Transpose the Universal ndslice .transposed; auto c = a.universal.reversed!1; auto d = a.flattened.sliced(c, r).universal.transposed!1.reversed!1; // see also `rotated` auto f = slice!int(c, r); // new int[cr].sliced(r, c); works too. auto h = f.universal.transposed(1); --- Mir ndslices have three kinds: http://docs.algorithm.dlang.io/latest/mir_ndslice_slice.html#.SliceKind If you have any questions feel free to ask at the Gitter: https://gitter.im/libmir/public Best, Ilya Best, Ilya Thanks
Re: RAII pointers
On Saturday, 3 June 2017 at 19:55:30 UTC, ag0aep6g wrote: On 06/03/2017 09:37 PM, Moritz Maxeiner wrote: Of course, but AFAIK you'd need to explicitly assign it to an object, so `ptr` won't null by accident, but only by explicit programmer intent (same as overwriting the memory the object lives in via things like `memcpy`); and you can always screw things intentionally (you could also assign some invalid value to the pointer via `memcpy`). I'd say `.init` can easily happen accidentally. Especially when `@disable this(this);` is involved. When you can't copy, you may have to move sometimes. But std.algorithm.move overwrites the old location with `.init`, assuming that `.init` can safely be destroyed. struct S { void* ptr; @disable this(this); ~this() { assert(ptr !is null); /* fails */ } } void f(S s) {} void main() { auto a = S(new int); import std.algorithm: move; f(move(a)); /* overwrites `a` with `S.init` */ } Yep, that's exactly why I added the null check in the example. If the struct has a postblit or a destructor, `move` will be destructive, and will overwrite the source with .init. Sometimes it doesn't matter (i.e. free() is allowed to take a null pointer), but in general, for things like smart pointers where you'd do arbitrary access in destructor, it's a good habit to check for .init values first, in case the object has been moved.
Re: How to Compare 2 objects of the same class
On Saturday, 3 June 2017 at 19:57:47 UTC, Mark wrote: Hello again. I'm designing a template version of a BST. Because of this, I want to be able to compare if two objects of the same class type are references to the same anonymous class on the heap somewhere. Example: Not sure what happened there. Anyways, example: auto A = new Box(); auto B = new Box(); if(A.opEquals(B)) {} gives the error test.o:(.data.rel.ro+0x18): undefined reference to `_D5Stack12__ModuleInfoZ' collect2: error: ld returned 1 exit status Error: linker exited with status 1 if(Object.opEquals(A,B) gives test.d(10): Error: function object.Object.opEquals (Object o) is not callable using argument types (Box, Box) How do I got about comparing two objects then?? Thanks.
How to Compare 2 objects of the same class
Hello again. I'm designing a template version of a BST. Because of this, I want to be able to compare if two objects of the same class type are references to the same anonymous class on the heap somewhere. Example:
Re: RAII pointers
On 06/03/2017 09:37 PM, Moritz Maxeiner wrote: Of course, but AFAIK you'd need to explicitly assign it to an object, so `ptr` won't null by accident, but only by explicit programmer intent (same as overwriting the memory the object lives in via things like `memcpy`); and you can always screw things intentionally (you could also assign some invalid value to the pointer via `memcpy`). I'd say `.init` can easily happen accidentally. Especially when `@disable this(this);` is involved. When you can't copy, you may have to move sometimes. But std.algorithm.move overwrites the old location with `.init`, assuming that `.init` can safely be destroyed. struct S { void* ptr; @disable this(this); ~this() { assert(ptr !is null); /* fails */ } } void f(S s) {} void main() { auto a = S(new int); import std.algorithm: move; f(move(a)); /* overwrites `a` with `S.init` */ }
Re: RAII pointers
On Saturday, 3 June 2017 at 19:21:58 UTC, ag0aep6g wrote: On 06/03/2017 09:06 PM, Moritz Maxeiner wrote: - null check in destructor: That's just because I forgot to add it. If you add `@disable(this)` (disable the default constructor), all elaborate constructors ensure it is not null, and no members can set it to null, you might be able to skip the check, but I may have missed some corner cases, so better be safe. `.init` is the corner case. `.init` is always there, even with `@disable this();`. Of course, but AFAIK you'd need to explicitly assign it to an object, so `ptr` won't null by accident, but only by explicit programmer intent (same as overwriting the memory the object lives in via things like `memcpy`); and you can always screw things intentionally (you could also assign some invalid value to the pointer via `memcpy`). Are there any accidental corner cases?
Re: RAII pointers
On 06/03/2017 09:06 PM, Moritz Maxeiner wrote: - null check in destructor: That's just because I forgot to add it. If you add `@disable(this)` (disable the default constructor), all elaborate constructors ensure it is not null, and no members can set it to null, you might be able to skip the check, but I may have missed some corner cases, so better be safe. `.init` is the corner case. `.init` is always there, even with `@disable this();`.
Re: RAII pointers
On Saturday, 3 June 2017 at 17:40:32 UTC, Russel Winder wrote: Would one be considered more idiomatic D, or is it a question of different circumstances different approaches. The differences are mainly in construction I believe. Well, the differences I spot are: - null check in destructor: That's just because I forgot to add it. If you add `@disable(this)` (disable the default constructor), all elaborate constructors ensure it is not null, and no members can set it to null, you might be able to skip the check, but I may have missed some corner cases, so better be safe. - factory functions (Stanislav) vs. elaborate constructors (me): + If you don't need to be able to construct the object without arguments, it's a stylistic choice and I consider the elaborate constructors to be more idiomatic. + otherwise (i.e. you need to be able to construct the object without arguments), you need the factory functions, because elaborate constructors for structs cannot have zero arguments, as that would clash with the default constructor that must be computable at compile time (for the struct's `.init` value) - inout: You can use that in what I wrote, as well; that's just a shorthand way to write several functions that do the same thing: one for `const T`, one for `immutable T`, and one for `T`
Re: RAII pointers
Thanks to Moritz and Stanislav for their examples, most useful. There are similarities (which I have just taken :-) but also some differences. Would one be considered more idiomatic D, or is it a question of different circumstances different approaches. The differences are mainly in construction I believe. On Tue, 2017-05-30 at 00:31 +, Moritz Maxeiner via Digitalmars-d- learn wrote: > […] > > struct FrontendParameters_Ptr { > private: > dvb_v5_fe_parms* ptr; > public: > @disable this(this); > this(ref const FrontendId fei, const uint verbose = 0, const > uint legacy = 0) { ... } > ~this() { dvb_fe_close(ptr); } > auto c_ptr() const { return ptr; } > alias c_ptr this; > } > --- On Tue, 2017-05-30 at 00:32 +, Stanislav Blinov via Digitalmars-d- learn wrote: […] > > struct FrontendParametersPtr > { > // No constructors, initialization with parameters > // is done via the frontendParametersPtr function > @disable this(this); > > ~this() > { > // null check is often useful to detect e.g. > // if this object has been `move`d > if (_ptr) dvb_fe_close(_ptr); > } > > // with DIP1000, could also return `scope` > inout(dvb_v5_fe_parms)* ptr() inout { return _ptr; } > alias ptr this; > package: > > void construct(/*your args here*/) { /*...*/ } > > private: > dvb_v5_fe_parms* _ptr; > } > > /// Replaces constructor, i.e. can be called with no arguments for > /// replacing "default" construction of C++ > auto frontendParametersPtr(Args...)(auto ref Args args) > { > import std.functional : forward; > FrontendParametersPtr result = void; > result.construct(forward!args); > return result; // moves result, no copy is made > } > […] -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: D scripting in D
On Saturday, 3 June 2017 at 17:24:08 UTC, Russel Winder wrote: So why isn't rdmd shipped as a separate thing if it can wrap any of the three compilers? it is... the link above is all there is to it, you simply compile it. The docs also call it a download: http://dlang.org/rdmd.html dmd just happens to bundle it. The others prolly should too.
Re: D scripting in D
On Sat, 2017-06-03 at 17:08 +, Adam D. Ruppe via Digitalmars-d- learn wrote: > On Saturday, 3 June 2017 at 05:04:24 UTC, Russel Winder wrote: > > Not enough is made of rdmd. rdmd needs to be separated from dmd > > so it works with gdc and ldc2. > > rdmd has always worked with them, at least with their gdmd and > ldmd wrappers > > https://github.com/dlang/tools/blob/master/rdmd.d#L46 > So why isn't rdmd shipped as a separate thing if it can wrap any of the three compilers? -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: D scripting in D
On Saturday, 3 June 2017 at 05:04:24 UTC, Russel Winder wrote: Not enough is made of rdmd. rdmd needs to be separated from dmd so it works with gdc and ldc2. rdmd has always worked with them, at least with their gdmd and ldmd wrappers https://github.com/dlang/tools/blob/master/rdmd.d#L46
Re: Strange expression found in std.variant
On Saturday, 3 June 2017 at 16:22:33 UTC, Francis Nixon wrote: When looking at std.variant I found the following line: return q{ static if (allowed!%1$s && T.allowed!%1$s) if (convertsTo!%1$s && other.convertsTo!%1$s) return VariantN(get!%1$s %2$s other.get!%1$s); }.format(tp, op); I was wondering what exactly the % signs where doing/what they are for? - q{} is a string that cmust contains D tokens. They allow highlightning in the editors, that's why you missed the point. - % is a format specifier - q{}.format() is format() called in the UFCS fashion
Re: Strange expression found in std.variant
On Saturday, 3 June 2017 at 16:22:33 UTC, Francis Nixon wrote: When looking at std.variant I found the following line: return q{ static if (allowed!%1$s && T.allowed!%1$s) if (convertsTo!%1$s && other.convertsTo!%1$s) return VariantN(get!%1$s %2$s other.get!%1$s); }.format(tp, op); I was wondering what exactly the % signs where doing/what they are for? https://tour.dlang.org/tour/en/basics/alias-strings
Re: Strange expression found in std.variant
On Saturday, 3 June 2017 at 16:22:33 UTC, Francis Nixon wrote: When looking at std.variant I found the following line: return q{ static if (allowed!%1$s && T.allowed!%1$s) if (convertsTo!%1$s && other.convertsTo!%1$s) return VariantN(get!%1$s %2$s other.get!%1$s); }.format(tp, op); I was wondering what exactly the % signs where doing/what they are for? Those are positional arguments to format. %1$s refers to the first argument (in this case tp) while %2$s refers to the second (op)
Strange expression found in std.variant
When looking at std.variant I found the following line: return q{ static if (allowed!%1$s && T.allowed!%1$s) if (convertsTo!%1$s && other.convertsTo!%1$s) return VariantN(get!%1$s %2$s other.get!%1$s); }.format(tp, op); I was wondering what exactly the % signs where doing/what they are for?
Re: D scripting in D
On 03/06/2017 4:43 PM, Lewis wrote: On Saturday, 3 June 2017 at 09:28:03 UTC, rikki cattermole wrote: A lot of this can be done by simply implementing shared libraries fully on Windows. There is a reason why TypeInfo doesn't cross the dll boundary right now. Sadly it isn't a high priority (and it really really needs to be "just done already"). Its fine for Linux. Is the D DLL situation different between Windows and Linux right now? If so, in what ways? I'm curious, I'm not set up for development on Linux currently so I wouldn't be up-to-date on these things. It is yes, all I know off the top of my head is that Windows is definitely broken and Linux should just work out of the box.
Re: D scripting in D
On Saturday, 3 June 2017 at 09:28:03 UTC, rikki cattermole wrote: A lot of this can be done by simply implementing shared libraries fully on Windows. There is a reason why TypeInfo doesn't cross the dll boundary right now. Sadly it isn't a high priority (and it really really needs to be "just done already"). Its fine for Linux. Is the D DLL situation different between Windows and Linux right now? If so, in what ways? I'm curious, I'm not set up for development on Linux currently so I wouldn't be up-to-date on these things.
Re: std.path.buildPath
On Saturday, 3 June 2017 at 14:12:03 UTC, Russel Winder wrote: I have no idea what drugs the person who chose that last one to be correct semantics was on at the time, but it was some seriously bad stuff. Of all people, I certainly didn't expect you to stray so far from the tone appropriate here. Please keep it civil. I cannot find any excuse for this to be even remotely reasonable. I suspect the original author had applications in mind where you want to resolve user-specified file system paths that might be relative or absolute. One could just use buildPath to prepend the root path if necessary. (Whether this is useful or just unnecessarily error-prone is another question, of course.) — David
Re: Lazy evaluation and @nogc code
On Saturday, 3 June 2017 at 14:34:41 UTC, Nick Vitsas wrote: In any case, do you think that `scope` should allow for such code to compile? Since you can get the desired result using the verbose version, I think you should also be able to using the `lazy` construct. I think so. There's even a pull request that modifies lazy so that other functions attributes (incl. @nogc) are inferred. https://github.com/dlang/dmd/pull/6348 The problem is that it seems to be out of scope / interest now (last activity was on 24 of Feb), almost 6 months.
Lazy evaluation and @nogc code
Hello, I've been playing around with the idea of lazy evaluation for function arguments [1] and I really like how it can be used to simplify deep nested loops operating on structured data. It also seems that you can get quite far without invoking the GC using the `scope` keyword. I’ve been experimenting on some code and I’ve reached an interesting situation. A similar thing has been filed as a bug [2] but it seems that `scope` was not available in its current form back then. Here’s some code to present the case. @nogc lazy evaluation using scoped delegates: Compiles fine in DMD v2.074.0, import std.stdio; int DoTimes(int count, scope int delegate() @nogc nothrow Dg) @nogc nothrow { foreach (i ; 0 .. count) Dg(); return 1; } int DoAgain() @nogc nothrow { int x = 0, y = 10; return DoTimes(2, { return DoTimes(4, { return printf("x:%d, y:%d\n", x++, y++); }); } ); } void foo() @nogc nothrow { DoTimes(2, { return DoTimes(4, { return DoAgain(); }); } ); } void main(string[] args) { auto Lambda = () => foo(); Lambda(); } @nogc lazy evaluation using `lazy` arguments: Exits with Error: @nogc function 'app.DoTimes' cannot call non-@nogc delegate 'Dg' in DMD v2.074.0. import std.stdio; int DoTimes(int count, scope lazy int Dg) @nogc nothrow { foreach (i ; 0 .. count) Dg(); return 1; } int DoAgain() @nogc nothrow { int x = 0, y = 10; return DoTimes(2, DoTimes(4, printf("x:%d, y:%d\n", x++, y++) ) ); } void foo() @nogc nothrow { DoTimes(2, DoTimes(4, DoAgain() ) ); } void main(string[] args) { auto Lambda = () => foo(); Lambda(); } typeof(Dg) returns `int` and not some kind of delegate. It seems that the conversion happens at a later stage and so we do not get the expected type. In any case, do you think that `scope` should allow for such code to compile? Since you can get the desired result using the verbose version, I think you should also be able to using the `lazy` construct. Thank you for any suggestions. [1] https://dlang.org/lazy-evaluation.html [2] https://issues.dlang.org/show_bug.cgi?id=12664
Re: C macros vs D can't do the right thing
On 2017-06-03 16:22, David Nadlinger wrote: We could also finally fix the frontend to get around this. At DConf 2015, Walter officially agreed that this is a bug that needs fixing. ;) That would be nice. -- /Jacob Carlborg
Re: difference between x = Nullable.init and x.nullify
On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote: Assigning Nullable!Test.init is equivalent to setting the internal value to Test.init and setting _isNull to false. Eh? Does it mean Nullable is default initialized to some non-null default value?
Re: std.path.buildPath
On 2017-06-03 16:12, Russel Winder via Digitalmars-d-learn wrote: From the manual page on std.path.buildPath: writeln(buildPath("foo", "bar", "baz")); // "foo/bar/baz" writeln(buildPath("/foo/", "bar/baz")); // "/foo/bar/baz" writeln(buildPath("/foo", "/bar")); // "/bar" I have no idea what drugs the person who chose that last one to be correct semantics was on at the time, but it was some seriously bad stuff. "If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped." I cannot find any excuse for this to be even remotely reasonable. Unfortunately it's been like this since forever. I mean, I checked the git history, it's been like this for as long as we have history, including when it was called "join". -- /Jacob Carlborg
Re: C macros vs D can't do the right thing
On Saturday, 3 June 2017 at 14:19:00 UTC, Jacob Carlborg wrote: Perhaps using the variadic template with a constraint on one element trick will work. Ugly, but I think that will work. We could also finally fix the frontend to get around this. At DConf 2015, Walter officially agreed that this is a bug that needs fixing. ;) — David
Re: C macros vs D can't do the right thing
Jacob Carlborg wrote: Perhaps using the variadic template with a constraint on one element trick will work. Ugly, but I think that will work. yeah. that's what Phobos does, for example.
Re: C macros vs D can't do the right thing
On 2017-06-03 16:03, Nicholas Wilson wrote: I think an alias template parameter will work here as aliases take anything(types, literals, symbols). No, it doesn't work for types: void foo(alias a)() {} void main() { foo!(int)(); } Results in: Error: template instance foo!int does not match template declaration foo(alias a)() Perhaps using the variadic template with a constraint on one element trick will work. Ugly, but I think that will work. -- /Jacob Carlborg
Re: difference between x = Nullable.init and x.nullify
On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote: [...] thanks
Re: C macros vs D can't do the right thing
On Saturday, 3 June 2017 at 13:17:46 UTC, Russel Winder wrote: Is this a problem in D or a problem in DStep? It's a limitation of DStep – for that use case, it would need to transform one of the macro arguments into a template argument rather than a runtime function parameter. If you need to make the code work as-is, I suppose you could create some aliases like `enum u32 = __u32.init;` and pass these instead of the types – using runtime values just to convey their type. — David
std.path.buildPath
From the manual page on std.path.buildPath: writeln(buildPath("foo", "bar", "baz")); // "foo/bar/baz" writeln(buildPath("/foo/", "bar/baz")); // "/foo/bar/baz" writeln(buildPath("/foo", "/bar")); // "/bar" I have no idea what drugs the person who chose that last one to be correct semantics was on at the time, but it was some seriously bad stuff. "If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped." I cannot find any excuse for this to be even remotely reasonable. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: C macros vs D can't do the right thing
On Saturday, 3 June 2017 at 13:17:46 UTC, Russel Winder wrote: A stripped down problem to avoid fluff. The C macro: #define FLOB(t) (sizeof(t)) Can be used in another macro: #define THINGY(a, b) (_THING(a, FLOB(b))) We can use this as in: THINGY(10, __u32) Now the D Way says use functions not macros. except that size_t FLOB(T)(auto ref T t) { return t.sizeof; } which is the result of DStep doesn't allow passing a type name as t. Is this a problem in D or a problem in DStep? I think an alias template parameter will work here as aliases take anything(types, literals, symbols).
Re: C macros vs D can't do the right thing
Russel Winder wrote: Now the D Way says... ..use templates! ;-) it is not really possible to guess what macro author means (to do that, dstep should be able to actually *understand* the code), so it tries to do what is used more often. that is, it's dstep failed guess.
C macros vs D can't do the right thing
A stripped down problem to avoid fluff. The C macro: #define FLOB(t) (sizeof(t)) Can be used in another macro: #define THINGY(a, b) (_THING(a, FLOB(b))) We can use this as in: THINGY(10, __u32) Now the D Way says use functions not macros. except that size_t FLOB(T)(auto ref T t) { return t.sizeof; } which is the result of DStep doesn't allow passing a type name as t. Is this a problem in D or a problem in DStep? -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: Creating and loading D plugins in D app
On Saturday, 3 June 2017 at 09:41:58 UTC, aberba wrote: On Friday, 2 June 2017 at 16:36:34 UTC, H. S. Teoh wrote: On Fri, Jun 02, 2017 at 12:19:48PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: On Friday, 2 June 2017 at 11:09:05 UTC, aberba wrote: > 1. Get shared libs to work in D (the best approach for all > D code) I have done very little with this myself but other people have so it is doable. [...] This is not directly related to the OP's question, but recently I wrote a program that, given a user-specified string, transforms it into D code using a code template, invokes dmd to compile it into a shared object, loads the shared object using dlopen(), and looks up the generated function with dlsym() to obtain a function pointer that can be used for calling the function. The shared object is unloaded after it's done. Will be of much use to me to see the brief instructions for this. I saw the C style on Wikipedia. Seems the functions loaded needs to be casted from void* to a type... before calling. Didn't quite understand that part. Yes, dlsym() returns the address of the object of the shared library you requested. The first parameter is the handle to the shared object that had been loaded by dlopen(). The second parameter is the name of the object one wants the address of. The address must then be casted to the type of the object. If the name was one of a function, one has to cast to a function pointer. That's something illegal in strict C (i.e. undefined behaviour.) but is something that is required by Posix. It's really not very difficult.
Re: Creating and loading D plugins in D app
On Friday, 2 June 2017 at 16:36:34 UTC, H. S. Teoh wrote: On Fri, Jun 02, 2017 at 12:19:48PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: On Friday, 2 June 2017 at 11:09:05 UTC, aberba wrote: > 1. Get shared libs to work in D (the best approach for all D > code) I have done very little with this myself but other people have so it is doable. [...] This is not directly related to the OP's question, but recently I wrote a program that, given a user-specified string, transforms it into D code using a code template, invokes dmd to compile it into a shared object, loads the shared object using dlopen(), and looks up the generated function with dlsym() to obtain a function pointer that can be used for calling the function. The shared object is unloaded after it's done. Will be of much use to me to see the brief instructions for this. I saw the C style on Wikipedia. Seems the functions loaded needs to be casted from void* to a type... before calling. Didn't quite understand that part. So it's definitely doable, in the sense that I've successfully generated D code, compiled it into a shared library, loaded it into the running executable, and can call the code. Of course, in my case, the code template is relatively simple so I don't have to worry about things like module ctors, shared data, non-TLS globals, or GC use. If you're planning to support those features, you might need to do a bit more work after calling dlopen(). At the very least you'd have to use dlsym() to look up module ctor symbols and run them before calling any other functions in the shared object, and you may have to initialize druntime in the shared object too, if it's statically linked. That seem like D with its features will be lot of work if I'm using loaded code that way. How about exposing standard interface/apis for loaded object's code to query info about the main app at runtime, similar to COM (if that's how if even works) I'm not sure what happens if it's dynamically linked, or if it uses its own copy of the GC. Does D work different from C in that regard? In any case, this is all possible, it just takes someone to dig into the details and write the code to make it all work. Then publish it on github or dub, and the rest of us can reap the benefits too. ;-) T
Re: D scripting in D
On 03/06/2017 10:03 AM, Mike B Johnson wrote: On Saturday, 3 June 2017 at 00:02:54 UTC, Lewis wrote: On Friday, 2 June 2017 at 20:47:31 UTC, Mike B Johnson wrote: [...] For sure. I actually want to post the source code at some point, but the changes I made are very much set up specifically for this project. I'll sift through at some point and see if I can gather together something worth posting. [...] Thanks. Maybe some of this could be overcome by a design pattern that removes them from being an issue(e.g., script can not use GC... only to demonstrate that if that were the case, then you wouldn't have to worry about GC issues ;)? I imagine that if "dll"'s were used that one would have all the power to debug and develop them as normal d code, which is nice and doesn't require a "script editor and debugger". A lot of this can be done by simply implementing shared libraries fully on Windows. There is a reason why TypeInfo doesn't cross the dll boundary right now. Sadly it isn't a high priority (and it really really needs to be "just done already"). Its fine for Linux.
Re: D scripting in D
On Saturday, 3 June 2017 at 00:02:54 UTC, Lewis wrote: On Friday, 2 June 2017 at 20:47:31 UTC, Mike B Johnson wrote: [...] For sure. I actually want to post the source code at some point, but the changes I made are very much set up specifically for this project. I'll sift through at some point and see if I can gather together something worth posting. [...] Thanks. Maybe some of this could be overcome by a design pattern that removes them from being an issue(e.g., script can not use GC... only to demonstrate that if that were the case, then you wouldn't have to worry about GC issues ;)? I imagine that if "dll"'s were used that one would have all the power to debug and develop them as normal d code, which is nice and doesn't require a "script editor and debugger".
Re: difference between x = Nullable.init and x.nullify
On Saturday, 3 June 2017 at 08:01:14 UTC, Jonathan M Davis wrote: On Saturday, June 03, 2017 06:41:44 Stanislav Blinov via Digitalmars-d-learn wrote: On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote: > looking at what rt_finalize does, I don't see why it > couldn't be nothrow. So, unless I'm missing something, it > seems like that would be a good enhancement. > > - Jonathan M Davis Presently, rt_finalize cannot be made nothrow, or un-made @system, because "reasons": http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org Fixing that would require significant changes to the runtime, and probably the compiler. I don't think it qualifies as a simple "enhancement" :) Well, as I said, I could be missing something, but all rt_finalize does is call rt_finalize2, and rt_finalize2 _is_ nothrow (it catches any Exceptions that are thrown by the destructor/finalizer). So, I have no idea why it would be the case that rt_finalize couldn't be nothrow, and I saw nothing in that thread which contradicts that, but I could have read it too quickly. Regardless, it's a perfectly valid enhancement request whether it's easy to implement or not. - Jonathan M Davis Whoops, my bad, I forgot it indeed swallows exceptions and does the onFinalizeError instead. So... yep, then it seems that rt_finalize probably should be marked nothrow too. Hmm... if throwing in a destructor is considered a runtime error, perhaps another valid enhancement would be to statically disallow throwing Exceptions in destructors, i.e. *require* them be nothrow?..
Re: difference between x = Nullable.init and x.nullify
On Saturday, June 03, 2017 06:41:44 Stanislav Blinov via Digitalmars-d-learn wrote: > On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote: > > looking at what rt_finalize does, I don't see why it couldn't > > be nothrow. So, unless I'm missing something, it seems like > > that would be a good enhancement. > > > > - Jonathan M Davis > > Presently, rt_finalize cannot be made nothrow, or un-made > @system, because "reasons": > http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org > > Fixing that would require significant changes to the runtime, and > probably the compiler. I don't think it qualifies as a simple > "enhancement" :) Well, as I said, I could be missing something, but all rt_finalize does is call rt_finalize2, and rt_finalize2 _is_ nothrow (it catches any Exceptions that are thrown by the destructor/finalizer). So, I have no idea why it would be the case that rt_finalize couldn't be nothrow, and I saw nothing in that thread which contradicts that, but I could have read it too quickly. Regardless, it's a perfectly valid enhancement request whether it's easy to implement or not. - Jonathan M Davis
Re: Creating and loading D plugins in D app
On Friday, 2 June 2017 at 16:36:34 UTC, H. S. Teoh wrote: On Fri, Jun 02, 2017 at 12:19:48PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: [...] [...] This is not directly related to the OP's question, but recently I wrote a program that, given a user-specified string, transforms it into D code using a code template, invokes dmd to compile it into a shared object, loads the shared object using dlopen(), and looks up the generated function with dlsym() to obtain a function pointer that can be used for calling the function. The shared object is unloaded after it's done. [...] Blog on it?