Re: auto ref and arrays
http://d.puremagic.com/issues/show_bug.cgi?id=9090
safety of move
I find myself using [abusing?] move lately: import std.algorithm; import std.stdio; struct A { const(int) i; int j; int k; } void main() { A* a = new A(); // pretend this is malloc or something // *a = A(1) A a2 = A(1); move(a2, *a); A[] arr = new A[](2); //arr[1] = *a; move(*a, arr[1]); } For the first part, I have a A* pointing to uninitialized memory and I need to initialize it somehow. move works I guess because it uses memcpy or something. Not complaining, but wondering. The second part violates D's const semantics and maybe shouldn't be permitted. But it is.
Re: path matching problem
You could replace the inner loop with somehting like: bool excl = exclude.any!(part => name.canFind(part)); std.algorithm seems to generally be running the match in the opposite direction, if I'm understanding it properly. (Dealing with D template is always confusing to me.) OTOH, I couldn't find the string any method, so I'm not really sure what you're proposing, though it does look attractive. I don't understand what you mean with running the match in the opposite direction, but I'll explain how my line of code works. First of all, it is equivalent to: any!(part => canFind(name, part))(exclude); The feature that that lets you write that in the way I did in my previous post is called uniform function call syntax (often abbreviated to UFCS) and is described at http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394. canFind(name, part) returns true if name contains part. (part => canFind(name, part)) is a short syntax for (part){ return canFind(name, part); } any!(condition)(range) returns true if condition is true for any element of range So the line of code in my previous post sets excl to true if name contains any of the strings in exclude. If you know all the strings you want to exclude in advance, it is easier to do that with a regex like Joshua did. If you want to learn about D templates, try this tutorial: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf?raw=true Still, though your basic approach sounds good, the suggestion of Joshua Niehus would let me filter out the strings that didn't fit before entering the loop. There's probably no real advantage to doing it that way, but it does seem more elegant. I agree, it is more elegant.
Re: What to use instead of array.join if RHS is not a range?
won't. You seem to be looking for a function which will insert an element between every element in a range rather than one that joins ranges, and I'm not aware of any function in Phobos which will do that. There may be a way to get one to do what you want, but I can't think of how at the moment. roundRobin can be used for that. I think this is suposed to work: auto r = roundRobin(arr, repeat(s).take(arr.length - 1)); This currently gives this error: Error: template instance std.range.roundRobin!(S[],Take!(Repeat!(S))) error instantiating I think this is due to the fact that roundRobin.front has multiple return statements, some of which return an lvalue and some of which return an rvalue when instantiated with one range with rvalue elements and one with lvalue elements. The return type of roundRobin is auto ref and it seems that this becomes ref in this case. Because I don't know exactly how auto ref is supposed to work, I don't know whether this is a bug in DMD or in roundRobin.front. This works: auto r = roundRobin(arr, repeat(s).take(arr.length - 1).array); And so does this: auto r2 = roundRobin(arr.map!"a", repeat(s).take(arr.length - 1));
Re: path matching problem
On 11/27/2012 01:34 PM, jerro wrote: On Tuesday, 27 November 2012 at 19:40:56 UTC, Charles Hixson wrote: Is there a better way to do this? (I want to find files that match any of some extensions and don't match any of several other strings, or are not in some directories.): import std.file; ... string exts = "*.{txt,utf8,utf-8,TXT,UTF8,UTF-8}"; string[] exclude = ["/template/", "biblio.txt", "categories.txt", "subjects.txt", "/toCDROM/"] int limit = 1 // Iterate a directory in depth foreach (string name; dirEntries(sDir, exts, SpanMode.depth)) { bool excl = false; foreach (string part; exclude) { if (part in name) { excl = true; break; } } if (excl) break; etc. You could replace the inner loop with somehting like: bool excl = exclude.any!(part => name.canFind(part)); There may be even some easier way to do it, take a look at std.algorithm. std.algorithm seems to generally be running the match in the opposite direction, if I'm understanding it properly. (Dealing with D template is always confusing to me.) OTOH, I couldn't find the string any method, so I'm not really sure what you're proposing, though it does look attractive. Still, though your basic approach sounds good, the suggestion of Joshua Niehus would let me filter out the strings that didn't fit before entering the loop. There's probably no real advantage to doing it that way, but it does seem more elegant. (You were right, though. That is in std.algorithms.)
Re: path matching problem
On Tuesday, 27 November 2012 at 23:43:43 UTC, Charles Hixson wrote: But why the chained filters, rather than using the option provided by dirEntries for one of them? Is it faster? Just the way you usually do things? (Which I accept as a legitimate answer. I can see that that approach would be more flexible.) Ignorance... Your right, I didn't realize that dirEntries had that filter option, you should use that. I doubt the double .filter would effect performance at all (might even slow it down for all i know :) //update: import std.algorithm, std.array, std.regex; import std.stdio, std.file; void main() { string exts = "*.{txt,utf8,utf-8,TXT,UTF8,UTF-8}"; enum string exclude = `r"/template/|biblio\.txt|categories\.txt|subjects\.txt|/toCDROM/"`; dirEntries("/path", exts, SpanMode.depth) .filter!(` std.regex.match(a.name,` ~ exclude ~ `).empty `) .writeln(); }
Re: path matching problem
On 11/27/2012 01:31 PM, Joshua Niehus wrote: On Tuesday, 27 November 2012 at 19:40:56 UTC, Charles Hixson wrote: Is there a better way to do this? (I want to find files that match any of some extensions and don't match any of several other strings, or are not in some directories.): import std.file; ... string exts = "*.{txt,utf8,utf-8,TXT,UTF8,UTF-8}"; string[] exclude = ["/template/", "biblio.txt", "categories.txt", "subjects.txt", "/toCDROM/"] int limit = 1 // Iterate a directory in depth foreach (string name; dirEntries(sDir, exts, SpanMode.depth)) { bool excl = false; foreach (string part; exclude) { if (part in name) { excl = true; break; } } if (excl) break; etc. maybe this:? import std.algorithm, std.array, std.regex; import std.stdio, std.file; void main() { enum string[] exts = [`".txt"`, `".utf8"`, `".utf-8"`, `".TXT"`, `".UTF8"`, `".UTF-8"`]; enum string exclude = `r"/template/|biblio\.txt|categories\.txt|subjects\.txt|/toCDROM/"`; auto x = dirEntries("/path", SpanMode.depth) .filter!(`endsWith(a.name,` ~ exts.join(",") ~ `)`) .filter!(`std.regex.match(a.name,` ~ exclude ~ `).empty`);; writeln(x); } That's a good approach, except that I want to step through the matching paths rather than accumulate them in a vector...though ... the filter documentation could mean that it would return an iterator. So I could replace writeln (x); by foreach (string name; x) { ... } and x wouldn't have to hold all the matching strings at the same time. But why the chained filters, rather than using the option provided by dirEntries for one of them? Is it faster? Just the way you usually do things? (Which I accept as a legitimate answer. I can see that that approach would be more flexible.)
Re: telnet and D
> IIRC, telnet is simple, so it shouldn't be too difficult.. Turns out it indeed was simple. My option negotiation had a bug :D my (primitive) telnet client works now :)
Re: auto ref and arrays
On 11/27/12 23:44, Ali Çehreli wrote: > On 11/27/2012 02:09 PM, Jack Applegame wrote: >> I don't understand why auto ref doesn't work with arrays. >> >> void test1(T)(auto ref const T[] val) {} >> void test2(T)(auto ref const T val) {} >> void main() { >> int b; >> test2(b); // OK >> string a; >> test1(a); // Error: cast(const(char[]))a is not an lvalue >> } >> >> Since a is mutable itself, compiler uses ref storage class. >> cast(const(char[]))a isn't an lvalue, so it's impossible to pass it by ref. >> >> But cast(const int)b isn't an lvalue too. Why it's no errors in this case? > > Sorry, I am not answering the question but is 'auto ref' is legal as a > parameter? It is not documented. It's legal and documented: http://dlang.org/template.html Whether the argument is mutable or not shouldn't matter -- compiler bug; both examples should compile (limiting auto-ref to only modifiable lvalues wouldn't make sense). artur
Re: auto ref and arrays
On Tuesday, November 27, 2012 14:44:51 Ali Çehreli wrote: > On 11/27/2012 02:09 PM, Jack Applegame wrote: > > I don't understand why auto ref doesn't work with arrays. > > > > void test1(T)(auto ref const T[] val) {} > > void test2(T)(auto ref const T val) {} > > void main() { > > int b; > > test2(b); // OK > > string a; > > test1(a); // Error: cast(const(char[]))a is not an lvalue > > } > > > > Since a is mutable itself, compiler uses ref storage class. > > cast(const(char[]))a isn't an lvalue, so it's impossible to pass it by > > ref. > > > > But cast(const int)b isn't an lvalue too. Why it's no errors in this case? > > Sorry, I am not answering the question but is 'auto ref' is legal as a > parameter? It is not documented. > > On the other hand, 'auto ref' is a legal return type. Yes, it's legal on function paramters - but only on templated functions. It was an attempt at solving the const& problem. It's supposed to take both lvalues and rvalues but not copy lvalues. I think that there's a decent chance that TDPL talks about it, but I'm not sure, though if it does, what it describes isn't quite what auto ref does at the moment, since the original idea for auto ref would have worked with non-templated functions, but Andrei and Walter miscommunicated on its intent, and it wasn't implemented that way (and would actually be problematic to implement that way). As for the OP's question, I'd say that it looks like a bug. My guess is that a cast is being inserted as part of the auto ref implementation, and a cast does _not_ result in an lvalue, so that's why it would fail. I don't know why it thinks it needs a cast though. - Jonathan M Davis
Re: What to use instead of array.join if RHS is not a range?
On Tuesday, November 27, 2012 23:35:55 Andrej Mitrovic wrote: > On 11/27/12, Jonathan M Davis wrote: > > Rather, you're asking it to insert an element > > between > > every element in range, which is similar but not the same. > > In that case, which function to use? Because it already behaves in > this way for strings. But it doesn't. It requires a range of ranges, and a string is a range of dchar. You need a range of strings to use join on strings. assert(join(["hello", "silly", "world"], " ") == "hello silly world"); will work. assert(join("hello world", " ") == "h e l l o w o r l d"); won't. You seem to be looking for a function which will insert an element between every element in a range rather than one that joins ranges, and I'm not aware of any function in Phobos which will do that. There may be a way to get one to do what you want, but I can't think of how at the moment. - Jonathan M Davis
Re: auto ref and arrays
On 11/27/2012 02:09 PM, Jack Applegame wrote: I don't understand why auto ref doesn't work with arrays. void test1(T)(auto ref const T[] val) {} void test2(T)(auto ref const T val) {} void main() { int b; test2(b); // OK string a; test1(a); // Error: cast(const(char[]))a is not an lvalue } Since a is mutable itself, compiler uses ref storage class. cast(const(char[]))a isn't an lvalue, so it's impossible to pass it by ref. But cast(const int)b isn't an lvalue too. Why it's no errors in this case? Sorry, I am not answering the question but is 'auto ref' is legal as a parameter? It is not documented. On the other hand, 'auto ref' is a legal return type. Ali
Re: What to use instead of array.join if RHS is not a range?
On 11/27/12, Jonathan M Davis wrote: > Rather, you're asking it to insert an element > between > every element in range, which is similar but not the same. In that case, which function to use? Because it already behaves in this way for strings.
auto ref and arrays
I don't understand why auto ref doesn't work with arrays. void test1(T)(auto ref const T[] val) {} void test2(T)(auto ref const T val) {} void main() { int b; test2(b); // OK string a; test1(a); // Error: cast(const(char[]))a is not an lvalue } Since a is mutable itself, compiler uses ref storage class. cast(const(char[]))a isn't an lvalue, so it's impossible to pass it by ref. But cast(const int)b isn't an lvalue too. Why it's no errors in this case?
Re: What to use instead of array.join if RHS is not a range?
On Tuesday, November 27, 2012 13:05:12 Andrej Mitrovic wrote: > On 11/27/12, Jonathan M Davis wrote: > > All you need to do is put it in an array. > > > > arr.join([s]); > > Still doesn't work. > > > S[1] s = void; > > s[0] = S(0); > > arr.join(s[]); > > Neither does that. > > http://d.puremagic.com/issues/show_bug.cgi?id=9082 Oh, wait. The problem is that you're calling join on something that isn't a range of ranges. It makes no sense to join an array which doesn't hold ranges. There's nothing to join. Rather, you're asking it to insert an element between every element in range, which is similar but not the same. - Jonathan M Davis
Re: path matching problem
On Tuesday, 27 November 2012 at 19:40:56 UTC, Charles Hixson wrote: Is there a better way to do this? (I want to find files that match any of some extensions and don't match any of several other strings, or are not in some directories.): import std.file; ... string exts = "*.{txt,utf8,utf-8,TXT,UTF8,UTF-8}"; string[] exclude = ["/template/", "biblio.txt", "categories.txt", "subjects.txt", "/toCDROM/"] int limit = 1 // Iterate a directory in depth foreach (string name; dirEntries(sDir, exts, SpanMode.depth)) { bool excl = false; foreach (string part; exclude) { if (part in name) { excl = true; break; } } if (excl) break; etc. You could replace the inner loop with somehting like: bool excl = exclude.any!(part => name.canFind(part)); There may be even some easier way to do it, take a look at std.algorithm.
Re: path matching problem
On Tuesday, 27 November 2012 at 19:40:56 UTC, Charles Hixson wrote: Is there a better way to do this? (I want to find files that match any of some extensions and don't match any of several other strings, or are not in some directories.): import std.file; ... string exts = "*.{txt,utf8,utf-8,TXT,UTF8,UTF-8}"; string[] exclude = ["/template/", "biblio.txt", "categories.txt", "subjects.txt", "/toCDROM/"] int limit = 1 // Iterate a directory in depth foreach (string name; dirEntries(sDir, exts, SpanMode.depth)) { bool excl = false; foreach (string part; exclude) { if (part in name) { excl = true; break; } } if (excl) break; etc. maybe this:? import std.algorithm, std.array, std.regex; import std.stdio, std.file; void main() { enum string[] exts = [`".txt"`, `".utf8"`, `".utf-8"`, `".TXT"`, `".UTF8"`, `".UTF-8"`]; enum string exclude = `r"/template/|biblio\.txt|categories\.txt|subjects\.txt|/toCDROM/"`; auto x = dirEntries("/path", SpanMode.depth) .filter!(`endsWith(a.name,` ~ exts.join(",") ~ `)`) .filter!(`std.regex.match(a.name,` ~ exclude ~ `).empty`);; writeln(x); }
Re: telnet and D
Haven't looked at vibe.d yet because it looked more like a library for writing web apps and normal sockets should be enough. Didn't know about Tango, I'll try deciphering the original d1 module.
path matching problem
Is there a better way to do this? (I want to find files that match any of some extensions and don't match any of several other strings, or are not in some directories.): import std.file; ... string exts = "*.{txt,utf8,utf-8,TXT,UTF8,UTF-8}"; string[] exclude = ["/template/", "biblio.txt", "categories.txt", "subjects.txt", "/toCDROM/"] int limit = 1 // Iterate a directory in depth foreach (string name; dirEntries(sDir, exts, SpanMode.depth)) { bool excl = false; foreach (string part; exclude) { if (part in name) { excl = true; break; } } if (excl) break; etc.
Re: SList/DList ranges
On Tuesday, 27 November 2012 at 07:51:16 UTC, Jonathan M Davis wrote: On Monday, November 26, 2012 19:49:51 Zhenya wrote: Hi! I read the spec,but I didn't find any function,that removes concrete element from list.I am not familiar with D's ranges,so could you help me please? What do you mean by removing concrete elements? How is that any different from any other element in the list? If you want to remove elements from the list, then use one of the *remove functions. [] on the list to get a range over all of the elements in the list, find to find the element that you want, and then take to get a range with just the elements from the front of the range that you want to remove. Hopefully this will enlighten you somewhat: import std.algorithm; import std.container; import std.range; import std.stdio; void main() { auto list = make!(SList!int)(4, 5, 6, 7, 22, 9, 5, 4); assert(equal(list[], [4, 5, 6, 7, 22, 9, 5, 4])); auto found = find(list[], 6); assert(equal(found.save, [6, 7, 22, 9, 5, 4])); list.linearRemove(take(found, 3)); assert(equal(list[], [4, 5, 9, 5, 4])); list.linearRemove(take(find(list[], 5), 1)); assert(equal(list[], [4, 9, 5, 4])); } Unfortunately, std.container needs a fair bit of work in terms of some of the details - particularly with its functions which accept and/or return ranges, so it doesn't always work like it should yet. It's very much a work in progress right now. But the above should give you the basic idea. As for ranges in general, the best resource on them at this point would be this chapter from an online book on D: http://ddili.org/ders/d.en/ranges.html If you're going to be using Phobos much (which is likely if you're using D), then you're going to need to understand ranges, because Phobos uses them quite heavily. - Jonathan M Davis Thank you,understood.I just want a container with fast insert/remove.Something like C++ std::list.But when I look at you example I understand that remove is linear,so maybe I need assosiative array or RedBlackTree. And thank you for a link,I will learn ranges surely.
Re: Segfault with std.container.Array but not regular dynamic array
On Tuesday, 27 November 2012 at 18:30:07 UTC, Ali Çehreli wrote: Same problem under Linux. Somebody, please file this bug! Thank you! :) Ali http://d.puremagic.com/issues/show_bug.cgi?id=9084
Re: Segfault with std.container.Array but not regular dynamic array
On 11/27/2012 10:04 AM, Maxim Fomin wrote: On Monday, 26 November 2012 at 22:42:53 UTC, Dan wrote: On Monday, 26 November 2012 at 19:14:09 UTC, Joseph Rushton Wakeling wrote: On 11/26/2012 04:07 PM, Joseph Rushton Wakeling wrote: Ok, now I really want to know why it crashes. I've narrowed it down to an example below. It seems there is a problem with RefCounted being used as value in a map. I think it crashes because of using associative array. Assignment to an absent aa member causes memory allocation without proper object construction, and immediately after compiler issues call to opAssign for not-constructed object - that is why "this" pointer is "bogus" on entering function. import std.stdio; struct S { int i = 42; struct SS { int ii = 41; this(this) { writeln("SS postblit"); } void opAssign(SS rhs) { writeln("SS opAssign"); } } SS ss; this(this) { writeln("S postblit"); } void opAssign(S rhs) { writeln("S opAssign"); } ~this() { writefln("i=%d, ii=%d", i, ss.ii); } } S[int] map ; // S[2] map; // S[] map = [S(), S()]; void main() { map[1] = S(); } AA version on windows 2.060 prints SS postblit S opAssign i=42, ii=41 i=4269990, ii=4269984 //garbage Switching to dynamic or static array fixes the program. Same problem under Linux. Somebody, please file this bug! Thank you! :) Ali
Re: Segfault with std.container.Array but not regular dynamic array
On Monday, 26 November 2012 at 22:42:53 UTC, Dan wrote: On Monday, 26 November 2012 at 19:14:09 UTC, Joseph Rushton Wakeling wrote: On 11/26/2012 04:07 PM, Joseph Rushton Wakeling wrote: Ok, now I really want to know why it crashes. I've narrowed it down to an example below. It seems there is a problem with RefCounted being used as value in a map. I think it crashes because of using associative array. Assignment to an absent aa member causes memory allocation without proper object construction, and immediately after compiler issues call to opAssign for not-constructed object - that is why "this" pointer is "bogus" on entering function. import std.stdio; struct S { int i = 42; struct SS { int ii = 41; this(this) { writeln("SS postblit"); } void opAssign(SS rhs) { writeln("SS opAssign"); } } SS ss; this(this) { writeln("S postblit"); } void opAssign(S rhs) { writeln("S opAssign"); } ~this() { writefln("i=%d, ii=%d", i, ss.ii); } } S[int] map ; // S[2] map; // S[] map = [S(), S()]; void main() { map[1] = S(); } AA version on windows 2.060 prints SS postblit S opAssign i=42, ii=41 i=4269990, ii=4269984 //garbage Switching to dynamic or static array fixes the program.
Re: Calls to struct methods and immutable
On Tuesday, 27 November 2012 at 14:05:37 UTC, Joseph Rushton Wakeling wrote: On 11/27/2012 01:16 PM, Joseph Rushton Wakeling wrote: ... so the real issue here seems to be that there's no canonical way (that I can find) to idup an _associative_ array. I'm using a custom gdup that recursively copies fields and requires no support from nested structs. If a dup is provided by a struct it will be called. No guarantees, but have a look. https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d The following runs: -- import std.stdio; import std.typecons; import std.conv; import std.exception; import opmix.mix; alias Tuple!(uint, "id") Link; struct Node { uint id; Link[] links; void addLink(uint l) { links ~= Link(l); } immutable(Node) idup() pure const @property { auto linkCopy = to!(Link[])(links); immutable ilinks = assumeUnique(linkCopy); return immutable(Node)(id, ilinks); } } struct Network { Node[uint] nodes; immutable(Network) idup() pure const @property { auto nodeCopy = nodes.gdup; immutable imnodes = assumeUnique(nodeCopy); return immutable(Network)(imnodes); } void add(uint i, uint j) { if((i in nodes) is null) nodes[i] = Node(i); if((j in nodes) is null) nodes[j] = Node(j); nodes[i].addLink(j); nodes[j].addLink(i); } void print() { foreach(k; nodes.keys) { write("[", k, "]"); foreach(l; nodes[k].links) write(" ", l.id); writeln(); } writeln(); } } unittest { auto n1 = Node(1); n1.addLink(5); n1.addLink(6); writeln(n1.links); immutable n2 = n1.idup; writeln(n2.links); Network net1; net1.add(1,2); immutable Network net2 = net1.idup; writeln(net1); writeln(net2); }
Re: Calls to struct methods and immutable
On 11/27/2012 01:16 PM, Joseph Rushton Wakeling wrote: immutable(Node) idup() pure const @property { auto linkCopy = to!(Link[])(links); immutable ilinks = assumeUnique(linkCopy); return immutable(Node)(id, ilinks); } Actually I'm being overly complicated here as with dynamic arrays I can simply do, immutable(Node) idup() pure const @property { return immutable(Node)(id, links.idup); } ... so the real issue here seems to be that there's no canonical way (that I can find) to idup an _associative_ array.
Re: Calls to struct methods and immutable
On 11/16/2012 05:51 AM, Ali Çehreli wrote: If makeFoo() were not pure, and in general, Foo may need to provide an .idup member function: I've been trying this out and ran into some problems with the to!()() conversion. Here's a concrete example. Suppose I have a couple of structs which are designed respectively to represent nodes in a network, and a collection of those nodes: /// alias Tuple!(uint, "id") Link; struct Node { uint id; Link[] links; void addLink(uint l) { links ~= Link(l); } immutable(Node) idup() pure const @property { auto linkCopy = to!(Link[])(links); immutable ilinks = assumeUnique(linkCopy); return immutable(Node)(id, ilinks); } } struct Network { Node[uint] nodes; void add(uint i, uint j) { if((i in nodes) is null) nodes[i] = Node(i); if((j in nodes) is null) nodes[j] = Node(j); nodes[i].addLink(j); nodes[j].addLink(i); } void print() { foreach(k; nodes.keys) { write("[", k, "]"); foreach(l; nodes[k].links) write(" ", l.id); writeln(); } writeln(); } } /// Now, the idup() command for Node works just fine: auto n1 = Node(1); n1.addLink(5); n1.addLink(6); writeln(n1.links); immutable n2 = n1.idup; writeln(n2.links); ... but if I try to introduce a similar function for the Network struct, immutable(Network) idup() pure const @property { auto nodeCopy = to!(Node[uint])(nodes); immutable imnodes = assumeUnique(nodeCopy); return immutable(Network)(imnodes); } it fails to compile with an error relating to the to!(Node[uint])() conversion: - /opt/dmd/include/d2/std/conv.d(269): Error: template std.conv.toImpl does not match any function template declaration. Candidates are: /opt/dmd/include/d2/std/conv.d(325):std.conv.toImpl(T, S)(S value) if (isImplicitlyConvertible!(S, T) && !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) /opt/dmd/include/d2/std/conv.d(431):std.conv.toImpl(T, S)(ref S s) if (isRawStaticArray!(S)) /opt/dmd/include/d2/std/conv.d(445):std.conv.toImpl(T, S)(S value) if (is(S : Object) && !is(T : Object) && !isSomeString!(T) && hasMember!(S, "to") && is(typeof(S.init.to!(T)()) : T)) /opt/dmd/include/d2/std/conv.d(466):std.conv.toImpl(T, S)(S value) if (is(typeof(S.init.opCast!(T)()) : T) && !(isSomeString!(T) && !is(T == enum) && !isAggregateType!(T))) /opt/dmd/include/d2/std/conv.d(497):std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == struct) && is(typeof(T(value /opt/dmd/include/d2/std/conv.d(269):... (16 more, -v to show) ... /opt/dmd/include/d2/std/conv.d(325): Error: template std.conv.toImpl cannot deduce template function from argument types !(Node)(const(Node)) /opt/dmd/include/d2/std/conv.d(269): Error: template instance toImpl!(Node) errors instantiating template /opt/dmd/include/d2/std/conv.d(1387): Error: template instance std.conv.to!(Node).to!(const(Node)) error instantiating /opt/dmd/include/d2/std/conv.d(269):instantiated from here: toImpl!(Node[uint], const(Node[uint])) inodes.d(41):instantiated from here: to!(const(Node[uint])) /opt/dmd/include/d2/std/conv.d(269): Error: template instance std.conv.toImpl!(Node[uint], const(Node[uint])) error instantiating inodes.d(41):instantiated from here: to!(const(Node[uint])) inodes.d(41): Error: template instance std.conv.to!(Node[uint]).to!(const(Node[uint])) error instantiating - I'm guessing this means I have to define a custom opCast (for Node, I guess) but the documentation on how to do so seems sparse -- can you advise? Full code example attached. Thanks & best wishes, -- Joe import std.conv, std.exception, std.stdio, std.typecons; alias Tuple!(uint, "id") Link; struct Node { uint id; Link[] links; void addLink(uint l) { links ~= Link(l); } immutable(Node) idup() pure const @property { auto linkCopy = to!(Link[])(links); immutable ilinks = assumeUnique(linkCopy); return immutable(Node)(id, ilinks); } } struct Network { Node[uint] nodes; void add(uint i, uint j) { if((i in nodes) is null) nodes[i] = Node(i); if((j in nodes) is null) nodes[j] = Node(j); nodes[i].addLink(j); nodes[j].addLink(i); } // Won't compile immutable(Network) idup() pure const @property { auto nodeCopy = to!(Node[uint])(nod
Re: What to use instead of array.join if RHS is not a range?
On 11/27/12, Jonathan M Davis wrote: > All you need to do is put it in an array. > > arr.join([s]); Still doesn't work. > S[1] s = void; > s[0] = S(0); > arr.join(s[]); Neither does that. http://d.puremagic.com/issues/show_bug.cgi?id=9082
Re: type determination
On Tuesday, 27 November 2012 at 10:45:19 UTC, Jonathan M Davis wrote: On Tuesday, November 27, 2012 11:30:31 dsmith wrote: Oh, the "static if" ... for compile time evaluation; seems unintuitive (no?) since data is encountered at run time. But the types are known at compile time. If you're doing anything with types, it has to be done at compile time. - Jonathan M Davis Indeed, based on the parameter in the function call.
Re: What to use instead of array.join if RHS is not a range?
On Tuesday, November 27, 2012 02:33:00 Andrej Mitrovic wrote: > This is what I want: > > struct S { int x; } > > void main() > { > S[] arr = [S(2), S(4), S(6)]; > S s = S(0); > arr.join(s); // fails here > assert(arr == [S(2), S(0), S(4), S(0), S(6)]); > } > > Calling join like that fails, specifically it fails because "s" is not > a forward range (I don't know why it's implemented like that..). Is > there some other function which can join with an element as a > separator? All you need to do is put it in an array. arr.join([s]); should work just fine. Or, if you don't want to allocate on the heap, you could do S[1] s = void; s[0] = S(0); arr.join(s[]); Granted, it _is_ a bit odd that join doesn't accept an element (and I don't think that it's the only range-based function with this problem), but it's easy enough to turn a single element into a range if you need to. - Jonathan M Davis
Re: What to use instead of array.join if RHS is not a range?
On 11/27/12, H. S. Teoh wrote: > What about std.algorithm.joiner? Same problem. Anyway here's a quick lazy (pun intended) implementation: import std.array; import std.stdio; struct MyJoiner(T) { T[] array; T sep; @property bool empty() { return array.empty; } void popFront() { if (!useSep) array.popFront(); useSep ^= 1; } bool useSep; @property T front() { if (useSep) return sep; else return array.front; } } auto myJoiner(T)(T[] array, T sep) { return MyJoiner!T(array, sep); } struct S { int x; } void main() { S[] arr = [S(2), S(4), S(6)]; S s = S(0); auto range = arr.myJoiner(s); assert(array(range) == [S(2), S(0), S(4), S(0), S(6)]); }
Re: type determination
On Tuesday, November 27, 2012 11:30:31 dsmith wrote: > Oh, the "static if" ... for compile time evaluation; seems > unintuitive (no?) since data is encountered at run time. But the types are known at compile time. If you're doing anything with types, it has to be done at compile time. - Jonathan M Davis
Re: type determination
On Tuesday, 27 November 2012 at 07:28:34 UTC, Jacob Carlborg wrote: On 2012-11-27 06:03, dsmith wrote: How can I make something like the following work without "Error: cannot append type double to type string[]" ? T[] some_function(T[] var) { T[] var2; double a = 12.34; string b = "hello"; if(typeof(var).stringof == "double") { var2 ~= a; } if(typeof(var).stringof == "string") { var2 ~= b; } ... } Use static-if, but you shouldn't use .stringof. Check the actual type and not the string of the type: static if(is(typeof(var) == double)) { var2 ~= a; } static if(is(typeof(var) == string)) { var2 ~= b; } Oh, the "static if" ... for compile time evaluation; seems unintuitive (no?) since data is encountered at run time.
Re: Segfault with std.container.Array but not regular dynamic array
On 11/26/2012 11:42 PM, Dan wrote: Ok, now I really want to know why it crashes. I've narrowed it down to an example below. It seems there is a problem with RefCounted being used as value in a map. I don't have the expertise to understand the assembly, but just to note that even with all the structs converted to classes, nodes.d only compiles with dmd. With ldmd2 or gdmd it exits with an error: container.d:2248: Error: cannot compare const(Tuple!(uint,"id")[]) and const(Tuple!(uint,"id")[]) ... regardless of whether Node1 and Node2 are declared as structs or classes.
Re: #define trouble
On Tuesday, 27 November 2012 at 06:27:49 UTC, Ali Çehreli wrote: On 11/26/2012 10:05 PM, dnewbie wrote: I have the following C struct from ldap.h typedef struct ldapmod { int mod_op; char *mod_type; union mod_vals_u { char **modv_strvals; struct berval **modv_bvals; } mod_vals; #define mod_values mod_vals.modv_strvals #define mod_bvalues mod_vals.modv_bvals } LDAPMod; It is used like this: LDAPMod title; title.mod_values = x; I wonder how can I write the line 'title.mod_values = x;' in D. Currently I do like this: struct ldapmod { int mod_op; char* mod_type; union mod_vals_u { char** modv_strvals; berval** modv_bvals; } mod_vals_u mod_vals; } alias ldapmod LDAPMod; LDAPMod title; title.mod_vals.modv_strvals = x; A pair of @property functions would work, one of which may be unnecessary: alias int berval; struct ldapmod { intmod_op; char* mod_type; union mod_vals_u { char** modv_strvals; berval** modv_bvals; } mod_vals_u mod_vals; char** mod_values() @property { return mod_vals.modv_strvals; } void mod_values(char** value) @property { mod_vals.modv_strvals = value; } // similarly for mod_bvalues... } alias ldapmod LDAPMod; void main() { LDAPMod title; char** x; // title.mod_vals.modv_strvals = x; title.mod_values = x; } Ali Perfect! Thank you.