Re: Error: Undefined identifier when moving import to another module
On Sunday, 19 October 2014 at 09:39:05 UTC, nrgyzer wrote: Hi guys, when I do the following: static if ( isCallable!(mixing(m) ) mixing ? void main() { /* do something here */ } What exactly are you doing here? ... I'm getting many error messages like these: myMain.d-mixin-11(11): Error: undefined identifier _D12TypeInfo_xAa6__initZ myMain.d-mixin-11(11): Error: undefined identifier _D49TypeInfo_xAS3std8typecons16__T5TupleTkTkTkZ5Tuple6__initZ myMain.d-mixin-11(11): Error: undefined identifier Sounds like your import was also import std.typecons which appears to have been required in your main.
Re: Error: Undefined identifier when moving import to another module
On Sunday, 19 October 2014 at 16:09:41 UTC, nrgyzer wrote: mixing should be replaced with mixin: static if ( isCallable!(mixin(m) ) My main is empty in both cases. So nothing done in my main (currently). Posting full code that actually compiles and reproduces the issue helps.
Re: Formatted output of range of tuples
On Wednesday, 8 October 2014 at 23:28:34 UTC, bearophile wrote: anonymous: You can turn the tuples into ranges with `only`: writef(%(%(%s %)\n%), zip(indexes, source).map!(t = only(t.expand))); This is a nice idea. Expand can probably be replaced by a []. I presume this works only if the types inside the tuple are the same. Expand creates returns a TypeTuple though, so it's arguably free. [] allocates a dynamic array, so is costly. On the flip side, only is *entirelly* by value, and carries all its arguments. If the tuple is big, then the range can become quite big.
Re: DList!int.remove(range.takeOne) - workarounds?
On Sunday, 12 October 2014 at 09:45:22 UTC, Algo wrote: DList seems to have an issue with remove: void main() { import std.container, std.range, std.algorithm; auto list = DList!int([1, 2, 4, 6]); auto res = find(list[], 2); list.remove(res); //ok /* list.remove(res.takeOne); Error: function std.container.dlist.DList!int.DList.remove (Range r) is not callable using argument types (Result) list.remove(res.take(1)); Error: function std.container.dlist.DList!int.DList.remove (Range r) is not callable using argument types (Take!(Range)) */ } Are there any known workarounds besides linearRemove? There is (unfortunatly) no support for takeOne in DList. However, linearRemove is not a workaround or worst than remove. It is just that it accepts a wider range of input, when O(1) cannot be guaranteed. If you are operating with a range of length 1, then linearRemove is still O(1).
Re: Splitting Ranges using Lambda Predicates
On Friday, 10 October 2014 at 05:55:00 UTC, Nordlöw wrote: On Thursday, 9 October 2014 at 22:01:31 UTC, monarch_dodra wrote: My quick guess is you are missing the *global* imports for the restraints. The compiler doesn't complain because the constraint is in a is(typeof(...)) test. The reason the typeof fails is simply cause the compiler has no idea what unaryFun is. I don't understand. The restraints are commented out at https://github.com/nordlow/justd/blob/master/slicer.d I made a couple of changes and now it works but I don't quite understand why... Thanks anyway. Sorry, I read your compile error wrong, and was on my phone. Anyways, I'm a bit worried, because it looks like an internal phobos compile error. May I request you attempt to re-create and potentially reduce the issue? I want to make sure you didn't uncover a bug...
Re: Splitting Ranges using Lambda Predicates
On Thursday, 9 October 2014 at 21:55:03 UTC, Nordlöw wrote: On Wednesday, 11 June 2014 at 08:58:58 UTC, monarch_dodra wrote: auto slicer(alias isTerminator, Range)(Range input) if (((isRandomAccessRange!Range hasSlicing!Range) || isSomeString!Range) is(typeof(unaryFun!isTerminator(input.front { return SlicerResult!(unaryFun!isTerminator, Range)(input); } ... Your solution copied here https://github.com/nordlow/justd/blob/master/slicer.d errors as /home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(5752,24): Error: template std.functional.not!(isUpper).not cannot deduce function from argument types !()(dchar), candidates are: /home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/functional.d(393,10): std.functional.not!(isUpper).not(T...)(T args) if (is(typeof(!unaryFun!pred(args))) || is(typeof(!binaryFun!pred(args slicer.d(29,31): Error: template instance std.algorithm.find!(not, string) error instantiating slicer.d(16,12):instantiated from here: Slicer!(isUpper, string) slicer.d(85,30):instantiated from here: slicer!(isUpper, string) What's wrong? My quick guess is you are missing the *global* imports for the restraints. The compiler doesn't complain because the constraint is in a is(typeof(...)) test. The reason the typeof fails is simply cause the compiler has no idea what unaryFun is.
Re: coding practices: include whole module or only the needed function
On Tuesday, 7 October 2014 at 07:33:24 UTC, Gary Willoughby wrote: On Monday, 6 October 2014 at 21:24:56 UTC, AsmMan wrote: Which practice do you use: if you need only one or two functions from a module: import myModule : func, func2; or (import whole module, assuming no function name conflits of course) import myModule; any words why one over the other are welcome. I like the first one why it explicitly show why I'm importing such a module and I think (personally) it make code more easy to read/understand/maitain. Also it's very useful inside functions (local imports) where we can overload the function like in: int f(int arg) { import foo : f; return f(somethingElse, arg); } I used it recently. Be mindful of this classic bug: https://issues.dlang.org/show_bug.cgi?id=314 Yeah. In the current state of affairs, please NEVER do selective imports in global scope. As a general rule, avoid imports in global scope anyways.
Re: coding practices: include whole module or only the needed function
On Tuesday, 7 October 2014 at 17:29:45 UTC, ketmar via Digitalmars-d-learn wrote: On Tue, 07 Oct 2014 17:24:40 + bachmeier via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Tuesday, 7 October 2014 at 08:37:59 UTC, monarch_dodra wrote: As a general rule, avoid imports in global scope anyways. Can you expand or provide a link to the issue? ahem... https://issues.dlang.org/show_bug.cgi?id=313 https://issues.dlang.org/show_bug.cgi?id=314 That's only relative to having selective imports. The idea of avoiding global imports is mostly to avoid polluting your own namespace, or to keep better track of who needs what. For example, if 1 function requires std.foo, and then you later remove that function. With global imports, chances are you'll forget to remove it.
Re: array append result type
On Monday, 6 October 2014 at 11:28:16 UTC, John Colvin wrote: string a; char[] b; pragma(msg, typeof(a ~ b)); // char[] why not string? What are the rules that determine this? *Ideally*, I'd have said it returns char[], so that you can chose via purity. However, it's not pure, so that argument doesn't hold. That said, casting to immutable is safe provided you never actually mutate. The reverse isn't true. To answer the question directly though, I don't know what the rules are. I'd guess they are mostly whatever druntime implemented though...
Re: array append result type
On Monday, 6 October 2014 at 16:38:37 UTC, Steven Schveighoffer wrote: I filed this ER ages ago: https://issues.dlang.org/show_bug.cgi?id=1654 Not sure if anyone has it on their radar at this point. -Steve I didn't read the whole thing, but wouldn't purity be a major game changer for 1654?
Re: slidingSplitter + retro
On Monday, 6 October 2014 at 20:06:41 UTC, Nordlöw wrote: I've almost satisfied with my new range slidingSplitter at https://github.com/nordlow/justd/blob/master/range_ex.d#L19 All unittest work as expected except my radial test https://github.com/nordlow/justd/blob/master/range_ex.d#L243 which, I believe, incorrectly prints Tuple!(int[], int[])([1, 2], [3]) Tuple!(int[], int[])([1, 2], [3]) Tuple!(int[], int[])([1], [2, 3]) Tuple!(int[], int[])([1, 2, 3], []) Tuple!(int[], int[])([], [1, 2, 3]) I cannot understand why the line Tuple!(int[], int[])([1, 2], [3]) is printed twice at the beginning. Have I done something wrong in my implementation of opIndex or opSlice? I don't have time to investigate tonight, and it's probably not it, but your save isn't saving _upper. I don't know how your radial works. Does the first back print ([1, 2, 3], []) as it should?
Re: How to detect start of Unicode symbol and count amount of graphemes
On Sunday, 5 October 2014 at 08:27:58 UTC, Uranuz wrote: I have struct StringStream that I use to go through and parse input string. String could be of string, wstring or dstring type. I implement function popChar that reads codeUnit from Stream. I want to have *debug* mode of parser (via CT switch), where I could get information about lineIndex, codeUnitIndex, graphemeIndex. So I don't want to use *front* primitive because it autodecodes everywhere, but I want to get info abot index of *user perceived character* in debug mode (so decoding is needed here). Question is how to detect that I go from one Unicode grapheme to another when iterating on string, wstring, dstring by code unit? Is it simple or is it attempt to reimplement a big piece of existing std library code? You can use std.uni.byGrapheme to iterate by graphemes: http://dlang.org/phobos/std_uni.html#.byGrapheme AFAIK, graphemes are not self synchronizing, but codepoints are. You can pop code units until you reach the beginning of a new codepoint. From there, you can iterate by graphemes, though your first grapheme might be off.
Re: RFC on SlidingSplitter Range
On Friday, 3 October 2014 at 15:22:06 UTC, Nordlöw wrote: Destroy, please! As a quick comment, your definition of moveFront is not what phobos understands with moveFront: https://github.com/D-Programming-Language/phobos/blob/7914fa31cb3b53f4e50421399f2b99d2012e8031/std/range.d#L8267 Namelly, the idea of moveFront, is simply that it takes the front and std.algorithm.move's it. If anything, I'd have expected you to provide something returns the popped element. What you do pops an element, and then returns the *next* one. What good is that? Also, what you want to check is hasSlicing, which is more powerful than isRA. Speaking of which, if you don't have isRA, it looks like your range errors out (no front). Your sliding splitter does not handle narrow strings. I'd have thought that was the original goal. Well, it is better to not support it at all of course, rather than doing it wrong :)
Re: RFC on SlidingSplitter Range
On Friday, 3 October 2014 at 17:06:41 UTC, Nordlöw wrote: On Friday, 3 October 2014 at 16:32:24 UTC, monarch_dodra wrote: If anything, I'd have expected you to provide something returns the popped element. What you do pops an element, and then returns the *next* one. What good is that? My mistake. It's fixed now. Well, yes and no. You are still providing a moveFront that does not conform to what the range interface expects. EG: auto app = appender(); auto myRange = slidingSplitter([1, 2, 3]); for ( ; !myRange.empty ; myRange.popFront() ) app.put(myRange.moveFront()); As you can see from this code snippet, moveFront is not expected to pop. At all. As a matter of fact, this will error out during runtime, as the loop will attempt a pop on an empty range. IMO, you should just leave it out. Also, what you want to check is hasSlicing, which is more powerful than isRA. Speaking of which, if you don't have isRA, it looks like your range errors out (no front). Ok. Fixed know. There's still the issue that if you don't have slicing, then your range doesn't have front at all. You might as well just make it a general template restriction. Your sliding splitter does not handle narrow strings. I'd have thought that was the original goal. Well, it is better to not support it at all of course, rather than doing it wrong :) That's part of episode 2, for now ;) Cool. More things I saw: Don't make opIndex const. You have no guarantee R.opindex is const. Also, opSlice() is not a range primitive. You can implement it, it's basically just a no-op. The one that's important is opSlice(lhs, rhs). Also, no point in returning an auto ref from slidingSplitter, you *know* it's an rvalue. If your implementation use two ranges that you slice on the fly, then you can trivially support strings, thanks to popFront. I threw this together. I left out checks for infinity in favor of brevity: // import std.range, std.stdio; import std.typecons: Tuple, tuple; struct SlidingSplitter(R) if (hasSlicing!R || isSomeString!R) { this(R)(R data) { _original = data; _right = data.save; } auto front() @property { return tuple(_original[0 .. $ - _right.length], _right); } void popFront() { if (_right.empty) _original = _right; else _right.popFront(); } bool empty() const { return _original.empty; } static if (hasSlicing!R) { auto opIndex(size_t i) { return tuple( _original[0 .. i + $ - _right.length], _right[i .. $]); } size_t length() { return _right.length + 1; } } private R _original; private R _right; } auto slidingSplitter(R)(R data) { return SlidingSplitter!R(data); } void main() { { auto r = slidingSplitter([1, 2, 3]); writefln(r.length: %s, r.length); writefln(r[1]: %s, r[1]); writefln(r[2]: %s, r[2]); } { writefln(%(%s\n%), slidingSplitter(Nordlöw)); } } // Output: r.length: 4 r[1]: Tuple!(int[], int[])([1], [2, 3]) r[2]: Tuple!(int[], int[])([1, 2], [3]) Tuple!(string, string)(, Nordlöw) Tuple!(string, string)(N, ordlöw) Tuple!(string, string)(No, rdlöw) Tuple!(string, string)(Nor, dlöw) Tuple!(string, string)(Nord, löw) Tuple!(string, string)(Nordl, öw) Tuple!(string, string)(Nordlö, w) Tuple!(string, string)(Nordlöw, )
Re: RFC on SlidingSplitter Range
On Friday, 3 October 2014 at 19:12:54 UTC, Nordlöw wrote: On Friday, 3 October 2014 at 17:46:18 UTC, monarch_dodra wrote: If your implementation use two ranges that you slice on the fly, then you can trivially support strings, thanks to popFront. Very clever. That's what I wanted. I threw this together. Superb! It could be motivated to use static if (isRandomAccessRange!R) { // my solution for member functions... private R _data; private size_t _index; else // assumes R is either string or wstring { // your solution for member functions... private R _original; private R _right; } to save space in the RA-case, right? The idea is to try to keep as much code in common as possible. You can keep your version, provided you write this for popFront: void popFront() { if (_index _data.length) { static if (isNarrowString!R) _index += stride(_data, _index) else ++_index; } } Is isRandomAccessRange!R the correct way to check for this? Either that or isNarrowString. given the restrictions, both are correct. Nice unittest ;) Thanks ;) I left out checks for infinity in favor of brevity: Last thing for now: - What do you mean by this? I mean that this would not work if you passed in a repeat(5) even though repeat verifies RA and hasSlicing. That's because there's a point where you check for length. The correct restrictions should have been: if (isSomeString || hasSlicing !isInfinite) Note that this works regardless of operator precedence. - Do I have to indicate that this range is not infinite? You indicate a range is infinite with an enum empty = false;. By having a run-time empty, you are implicitly stating you are not infinite. ... That said... You could perfectly well support infinite ranges, with the correct static ifs. You'd produce an infinite sliding splitter.
Re: RFC on SlidingSplitter Range
On Friday, 3 October 2014 at 19:46:10 UTC, Nordlöw wrote: Is prefix ++ preferred in D because of some specific reason? I recall it, for some containers/iterators, gives smaller/faster codegen in C++? Be it C, C++ or D, pre increment is maybe faster, and is never slower. So as a rule of thumb, unless you should *specifically* require post increment, pre-increment is to be prefered, though in 95% of the cases, it results in the same code.
Re: RFC on SlidingSplitter Range
On Friday, 3 October 2014 at 20:28:24 UTC, Nordlöw wrote: On Friday, 3 October 2014 at 20:15:33 UTC, Nordlöw wrote: Could you please take a look again at I made another update at https://github.com/nordlow/justd/blob/master/range_ex.d#L15 I had forgotten to move front and popFront out of static if hasSlicing!R Now auto name = slidingSplitter(Nordlöw); errors range_ex.d(41,24): Error: incompatible types for ((this._index) += (stride(this._data, this._index))): 'ulong' and 'Result' range_ex.d(88,12): Error: template instance range_ex.SlidingSplitter!string error instantiating range_ex.d(131,32):instantiated from here: slidingSplitter!string It must be resolving to std.range.stride. You want std.utf.stride.
Re: RFC on SlidingSplitter Range
On Friday, 3 October 2014 at 20:15:33 UTC, Nordlöw wrote: Note that I had to tweak empty() a bit. I don't know if I got right. Could you check? Sounds about right, but I didn't really look. Further I can't get string support to work: writefln(%(%s\n%), slidingSplitter(Nordlöw)); errors as std.format.FormatException@/home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/format.d(2591): Expected '%s' format specifier for type 'SlidingSplitter!string' and foreach (e; name) { version(show) writeln(e); } errors as range_ex.d(132,5): Error: invalid foreach aggregate name, define opApply(), range primitives, or use .tupleof which diagnostics I btw is responsible for :) Could you please check? Sounds like your range isn't a range. Did you check that: isInputRange!(SlidingSplitter!string) ? As mentioned in the first reply, it's a very important check, as it's very easy to get wrong. For example, if you forget to mark front and empty as properties, then you don't have the correct range interface I believe. On Friday, 3 October 2014 at 17:46:18 UTC, monarch_dodra wrote: writefln(%(%s\n%), slidingSplitter(Nordlöw)); That's a really cool syntax, btw. I got to remember that. Yup. Love it. Use it.
Re: Find Semantically Correct Word Splits in UTF-8 Strings
On Wednesday, 1 October 2014 at 21:34:40 UTC, Nordlöw wrote: On Wednesday, 1 October 2014 at 17:09:57 UTC, monarch_dodra wrote: Does that even work? takeExactly would pop up to N *codepoints*, whereas your string only has N *codeunits*. Your're right again :) If forgot that takeExactly auto-decodes. Technically, it only pops. It's front/popFront that auto-decode.
Re: How do I check if a function got CTFE?
On Thursday, 2 October 2014 at 18:42:56 UTC, AsmMan wrote: I was thiking the dmd compiler did CTFE without someone ask for this, in the way as I've mentioned, checking for constant arguments + function's purity and if all this is true, it did the CTFE rather than generate code to compute it at run-time. In the case of it did happen, I just wanted to know. It was my misunderstsooding how it does works in dmd. A convenient way to force ctfe is eval: http://dlang.org/function.html (search for eval!) Though you'd change const for enum. Unfortunately, it's not in Phobos, but it should be! https://issues.dlang.org/show_bug.cgi?id=11811
Re: Find Semantically Correct Word Splits in UTF-8 Strings
On Wednesday, 1 October 2014 at 11:47:41 UTC, Nordlöw wrote: On Wednesday, 1 October 2014 at 11:06:24 UTC, Nordlöw wrote: I'm looking for a way to make my algorithm Update: S[] findMeaningfulWordSplit(S)(S word, HLang[] langs = []) if (isSomeString!S) { for (size_t i = 1; i + 1 word.length; i++) { const first = word.takeExactly(i).to!string; const second = word.dropExactly(i).to!string; if (this.canMeanSomething(first, langs) this.canMeanSomething(second, langs)) { return [first, second]; } } return typeof(return).init; } works but has unfortunately O(word.length^^2) time-complexity. Do we need a new InputRange algorithm for this? This seems like a text-book case for a trie algorithm: http://en.wikipedia.org/wiki/Trie Once your dictionary is built, it can find *all* the splits in O(word.length). ...but I don't know how well it adapts to the range interface. Should still work though. Also, Aho–Corasick might be relevant depending on what you want to do, for example, find all substrings that happen to be a word, regardless of what comes before or after: http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm
Re: Find Semantically Correct Word Splits in UTF-8 Strings
On Wednesday, 1 October 2014 at 11:06:24 UTC, Nordlöw wrote: I'm looking for a way to make my algorithm S[] findWordSplit(S)(S word, HLang[] langs = []) { for (size_t i = 1; i + 1 word.length; i++) { const first = word[0..i]; const second = word[i..$]; if (this.canMeanSomething(first, langs) this.canMeanSomething(second, langs)) { return [first, second]; } } return typeof(return).init; } correctly work if S is a (UTF-8) string without first, in lazy manner, encode word to a dstring. Currently this algorithm works as carwash = [car, wash] and I would like it to work correctly and efficient in my native language aswell as biltvätt = [bil, tvätt] :) Out of curiosity, why exactly isn't it working in your native language? If you avoid decoding in your canMeanSomething, you should encounter no problems.
Re: Find Semantically Correct Word Splits in UTF-8 Strings
On Wednesday, 1 October 2014 at 11:47:41 UTC, Nordlöw wrote: On Wednesday, 1 October 2014 at 11:06:24 UTC, Nordlöw wrote: I'm looking for a way to make my algorithm Update: S[] findMeaningfulWordSplit(S)(S word, HLang[] langs = []) if (isSomeString!S) { for (size_t i = 1; i + 1 word.length; i++) { const first = word.takeExactly(i).to!string; Does that even work? takeExactly would pop up to N *codepoints*, whereas your string only has N *codeunits*. Something like: for (auto second = str ; !second.empty ; second.popFront() ) { auto first = str[0 .. $ - second.length]; ... } //special case str + str[$ .. $] here. (or adapt your loop) Would also be unicode correct, without increasing the original complexity.
Re: isArray and std.container.Array
On Monday, 29 September 2014 at 10:18:09 UTC, Marc Schütz wrote: On Sunday, 28 September 2014 at 20:24:11 UTC, monarch_dodra wrote: On Sunday, 28 September 2014 at 19:06:09 UTC, Marc Schütz wrote: On Sunday, 28 September 2014 at 16:12:53 UTC, Meta wrote: On Sunday, 28 September 2014 at 08:01:00 UTC, Nordlöw wrote: Is there a reason why isArray!T doesn't match T when T is a std.container.Array? I'm asking because after looking into msgpack-d because of http://forum.dlang.org/thread/aclapseyptgcwntda...@forum.dlang.org#post-aclapseyptgcwntdavwt:40forum.dlang.org I realized that this is the reason why msgpack doesn't correctly pack std.container.Array. It's just an oversight in isArray as far as I can tell. I don't know if there's any specific reason that Array is not considered an array. I don't think so. std.container.Array is just a data structure that behaves like an array, but there could be countless other user defined data structures. It should not get preferred treatment over those other types. At most, isArray could check for the presence of .length, .ptr and indexing/slicing. But I think isArray was intended specifically for built-in arrays. It's description is an array (static or dynamic [...]) is probably meant to express that, because it lists static and dynamic arrays, but doesn't mention array-like containers. Yes, everything here is correct. Interestingly though, Array is not actually array-like (it's not a range, it doesn't slice), however Array.Range *is* an array-like structure. In regards to isArrayLike, it would probably be more interesting to instead integrate it as a isRandomAccessRange range refinement, which would also allow opSlice operations, eg (myRange[0 .. 3] = 5). As for .ptr, I think no range *trait* should expose (require) that, as it would most probably be an underhanded way to leak some abstraction, which would be better expressed as a direct call *prior*, rather than a range proper. EG: myRange.ptr[0 .. 10].doSomeOperation(); The question is whether you want to call something array-like if it isn't stored contiguously in memory. Most algorithms don't depend on it, but it's a significant divergence from what isArray guarantees. Right, but just because it *is* stored contiguous in memory don't mean you want to expose it. Array.Range is contiguous in memory, but it does not provide .ptr. Also, queue-like containers are not fully contiguous in memory, so *couldn't* expose .ptr. They'd still get major benefit from myRange[]=5 though. Because of that, I think a trait like isArrayLike requiring full array-like behavior is not very useful. Rather, just isSliceOpRange would be better.
Re: Turn function into infinite range
On Monday, 29 September 2014 at 17:02:43 UTC, Martin Nowak wrote: I though I've seen this around somewhere but can no longer find it. AFAIK, this as never existed. We recently merged in cache into phobos. This seems like a prime candidate to expand to also take a function/delegate, as on of its built-in feature is that the value of front is not changed until popFront() is called. Having it also accept a function/delegate would make sense. The issue with *not* having that is that a dumb adapter would fail the: r.front == r.front Test. And I'm pretty sure this test is expected to pass, even for the so called transient ranges. I think I'll get to it now (this week). Thoughts?
Re: Turn function into infinite range
On Monday, 29 September 2014 at 21:16:27 UTC, Daniel Kozák via Digitalmars-d-learn wrote: V Mon, 29 Sep 2014 19:02:36 +0200 Martin Nowak via Digitalmars-d-learn digitalmars-d-learn@puremagic.com napsáno: Does anyone know a construct to turn a lambda into an infinite range. import std.random; unittest { Random gen; foreach(v; xxx!(() = uniform(0, 100, gen)).take(10)) writeln(v); } I though I've seen this around somewhere but can no longer find it. http://dlang.org/phobos/std_range.html#.Repeat ? That just repeats the value, but doesn't re-evaluate the value on every call to front/popFront.
Re: isArray and std.container.Array
On Sunday, 28 September 2014 at 19:06:09 UTC, Marc Schütz wrote: On Sunday, 28 September 2014 at 16:12:53 UTC, Meta wrote: On Sunday, 28 September 2014 at 08:01:00 UTC, Nordlöw wrote: Is there a reason why isArray!T doesn't match T when T is a std.container.Array? I'm asking because after looking into msgpack-d because of http://forum.dlang.org/thread/aclapseyptgcwntda...@forum.dlang.org#post-aclapseyptgcwntdavwt:40forum.dlang.org I realized that this is the reason why msgpack doesn't correctly pack std.container.Array. It's just an oversight in isArray as far as I can tell. I don't know if there's any specific reason that Array is not considered an array. I don't think so. std.container.Array is just a data structure that behaves like an array, but there could be countless other user defined data structures. It should not get preferred treatment over those other types. At most, isArray could check for the presence of .length, .ptr and indexing/slicing. But I think isArray was intended specifically for built-in arrays. It's description is an array (static or dynamic [...]) is probably meant to express that, because it lists static and dynamic arrays, but doesn't mention array-like containers. Yes, everything here is correct. Interestingly though, Array is not actually array-like (it's not a range, it doesn't slice), however Array.Range *is* an array-like structure. In regards to isArrayLike, it would probably be more interesting to instead integrate it as a isRandomAccessRange range refinement, which would also allow opSlice operations, eg (myRange[0 .. 3] = 5). As for .ptr, I think no range *trait* should expose (require) that, as it would most probably be an underhanded way to leak some abstraction, which would be better expressed as a direct call *prior*, rather than a range proper. EG: myRange.ptr[0 .. 10].doSomeOperation();
Re: Non-const std.container.Array.opIndex and alikes blocks serialization
On Sunday, 28 September 2014 at 09:04:42 UTC, Nordlöw wrote: On Sunday, 28 September 2014 at 08:58:27 UTC, Nordlöw wrote: In my strive to add msgpacking support for std.container.Array I've been blocked by the fact that std.container.Array.opIndex only has one overload which is non-const probably because it returns a ref T. This doesn't place nicely with serialization. Shouldn't inout be used here? Further I've tried tagging all opIndex in array.d with inout as inout ref T opIndex(size_t i) inout but then I get another error array.d(479,30): Error: cast(string)this._data.refCountedPayload()._payload[i] is not an lvalue Probably you want: ref inout(T) opIndex(size_t i) inout Instead. What you wrote was basically the same as: ref T opIndex(size_t i) inout inout While compiling, the inout(T) obtained from _payload[i] is value-converted into a T (makes it an lvalue), and then the return (which is ref) fails. This is the whole function attributes on left side confusion - fiasco thing...
Re: A few questions regarding GC.malloc
On Friday, 26 September 2014 at 18:03:40 UTC, Steven Schveighoffer wrote: On 9/25/14 6:03 PM, Sean Kelly wrote: On Thursday, 25 September 2014 at 21:43:53 UTC, monarch_dodra wrote: On Thursday, 25 September 2014 at 20:58:29 UTC, Gary Willoughby wrote: What does BlkAttr.FINALIZE do when used in the GC.malloc call? I have no idea. I think its for classes though, since we (currently) don't finalize structs anyways. Yes it's for memory blocks containing class instances. It basically tells the GC to call Object.~this() when collecting the block. Just to add to Sean's statement, don't use this flag. It will crash the runtime, unless you have properly set up the classinfo pointer :) It does NOT work on structs, though I think there is a PR in the works to have structs destroyed from the GC. -Steve Kind of like APPENDABLE I guess, since it only works if you correctly setup the appendable data, and correctly slice at the correct offset, both of which are implementation defined.
Re: Remove filename from path
On Wednesday, 24 September 2014 at 17:15:39 UTC, Ali Çehreli wrote: find() and friends can be used: import std.algorithm; void main() { string path = myFile.doc; string extension = .doc; path = findSplitBefore(path, extension)[0]; assert(path == myFile); } I had thought of that, but then you might get in trouble with something like: string path = myPath.doc.old And three retro()s make one modern(): :p import std.algorithm; import std.range; void main() { string path = myFile.doc; string extension = .doc; path = findSplitAfter(path.retro, extension.retro) [1].retro; assert(path == myFile); } Ali That was the next one I had. Except here: - You still run into issues if the extension is *not* .doc (and there happens to be a .doc somewhere in there). - You are paying for a search, when you are only interested in testing a prefix. I had thought of this though: void main() { string path = myFile.doc; string extension = .doc; auto rpath = path.retro(); skipOver(rpath, extension.retro); path = rpath.retro(); assert(path == myFile); } The issue though is that skipOver modifies an rvalue, so it's not as functional-style as I would have liked it. Anyways, the conclusion here (IMO), is that to manipulate paths, use std.path.
immutable T.init, and pointers to mutable data
I was playing around with how T.init works. And I think I may have found a type loophole. Given that you may initialize a pointer member to the address to a static global: // __gshared int a = 0; struct S { int* p = a; } // Then, in theory, any variable, be they mutable or const, are initialized to T.init: // void main() { immutable S s; } // This is an issue, because I now have an immutable pointer that points to mutable data: // immutable S s = S.init; immutable int* p = s.p; assert(*p == 0); //OK a = 5; assert(*p == 5); //OK // So this violates the type system... The question here is: Is this legit code? At what point do you think my code should have been rejected?
Re: immutable T.init, and pointers to mutable data
On Thursday, 25 September 2014 at 12:46:01 UTC, Steven Schveighoffer wrote: On 9/25/14 5:47 AM, monarch_dodra wrote: I was playing around with how T.init works. And I think I may have found a type loophole. Given that you may initialize a pointer member to the address to a static global: // __gshared int a = 0; struct S { int* p = a; } // Then, in theory, any variable, be they mutable or const, are initialized to T.init: // void main() { immutable S s; } // This is an issue, because I now have an immutable pointer that points to mutable data: // immutable S s = S.init; immutable int* p = s.p; assert(*p == 0); //OK a = 5; assert(*p == 5); //OK // So this violates the type system... The question here is: Is this legit code? At what point do you think my code should have been rejected? It should be rejected. The declaration of s (the variable) should be the trigger, since it casts the pointer to immutable. Please file a bug report. -Steve Hum... So that means certain types just *can't* be initialized (as immutable) at all?
Re: immutable T.init, and pointers to mutable data
On Thursday, 25 September 2014 at 13:37:52 UTC, Steven Schveighoffer wrote: On 9/25/14 9:00 AM, monarch_dodra wrote: On Thursday, 25 September 2014 at 12:46:01 UTC, Steven Schveighoffer wrote: On 9/25/14 5:47 AM, monarch_dodra wrote: I was playing around with how T.init works. And I think I may have found a type loophole. Given that you may initialize a pointer member to the address to a static global: // __gshared int a = 0; struct S { int* p = a; } // Then, in theory, any variable, be they mutable or const, are initialized to T.init: // void main() { immutable S s; } // This is an issue, because I now have an immutable pointer that points to mutable data: // immutable S s = S.init; immutable int* p = s.p; assert(*p == 0); //OK a = 5; assert(*p == 5); //OK // So this violates the type system... The question here is: Is this legit code? At what point do you think my code should have been rejected? It should be rejected. The declaration of s (the variable) should be the trigger, since it casts the pointer to immutable. Please file a bug report. -Steve Hum... So that means certain types just *can't* be initialized (as immutable) at all? I wouldn't say that: immutable s = S(null); But clearly, any code that results in an immutable pointer to mutable data without casts is incorrect. We should start by outlawing such code, and if there are ways we can carve out certain usages, we can do that. -Steve Hum... right, but I meant T.init itself would not be valid. As in: alias T = immutable(S); T t = T.init; //Illegal? This might be a borderline case, but I kind of figured that that piece of code was the *only* one that was universally valid in generic code. The context was this pull request: https://github.com/D-Programming-Language/phobos/pull/2172 This sucks...
Re: Fail to compile phobos
On Thursday, 25 September 2014 at 17:20:42 UTC, JJDuck wrote: I tried to compile phobos according to the last paragraph in this page: http://dlang.org/dmd-linux.html but this is the error I have fatal: Not a git repository (or any of the parent directories): .git I dont know what happened, i have tried for a few days. BTW, should I place my dmd2 folder at ~ or /usr/local/share. which will have less prblem in installing and maintaining? Thanks Please provide the command that produced this output.
Re: A few questions regarding GC.malloc
On Thursday, 25 September 2014 at 20:58:29 UTC, Gary Willoughby wrote: A few questions regarding GC.malloc. When requesting a chunk of memory from GC.malloc am i right in assuming that this chunk is scanned for pointers to other GC resources in order to make decisions whether to collect them or not? By default, yes, but you can use BlkAttr.NO_SCAN if you do not want that (eg, if you want to store integers). As a rule of thumb, you can use hasIndirections!T to know if or if not to scan (that's what most of phobos relies on). What does BlkAttr.FINALIZE do when used in the GC.malloc call? I have no idea. I think its for classes though, since we (currently) don't finalize structs anyways.
Re: Remove filename from path
On Wednesday, 24 September 2014 at 10:11:04 UTC, Suliman wrote: What is the best way to remove file name from full path? string path = thisExePath() Seems like dirName in std.path is a good candidate ;) http://dlang.org/phobos/std_path.html#.dirName You'll find many other path manipulation functions there.
Re: Remove filename from path
On Wednesday, 24 September 2014 at 10:35:29 UTC, Suliman wrote: I can't understand how to use strip? For example I would like to cut just extension. path = path.stripRight(exe); Error: no overload matches for stripRight(C)(C[] str) if stripExtension would be your friend here. If you want the extension, then extension. As a general rule, everything you need to manipulate paths and filenames is in std.path: http://dlang.org/phobos/std_path.html
Re: Remove filename from path
On Wednesday, 24 September 2014 at 10:35:29 UTC, Suliman wrote: I can't understand how to use strip? For example I would like to cut just extension. path = path.stripRight(exe); Error: no overload matches for stripRight(C)(C[] str) if strip doens't work that way. It simply removes leading/trailing white. There's a version in std.algorithm which is more generic, but it accepts either a predicate, or an element, but not a range. Unfortunately, there is no generic function that allows striping of a specific ending range (though there are ways to either detect it, or strip it from the end). If you want something generic, then: string path = myFile.doc; string extension = .doc; if (path.endsWith(extension)) path = path[0 .. $ - extension.length]; Would work.
Re: Recursive function call
On Wednesday, 24 September 2014 at 10:57:27 UTC, Suliman wrote: string getFileName() { //чтобы было проще обрабатываемый файл будем хранить рядом с бинариком string filename = chomp(readln()); string path = getcwd(); writeln((path ~ \\ ~ filename)); if (exists(path ~ \\ ~ filename)) return (path ~ \\ ~ filename); Don't do `path ~ \\ ~ filename`. Instead, use std.path.buildPath. It's more portable, faster, and convenient. Also, you should store the result in a named variable, or you'll reallocate a new string everytime. else { writeln(File do not exists. Please try again); getFilename(); //I need something similar, to call function again. } } In case of error, how I can call function getFileName again? Any kind of looping control structure would work. I'd advocate the while(1) loop with a break or return: while(1) { string filename = chomp(readln()); string path = getcwd(); string fullPath = buildPath(path, filename); if (exists(fullPath)) return fullPath; writeln(File does not exists. Please try again); }
Re: Remove filename from path
On Wednesday, 24 September 2014 at 12:29:09 UTC, ketmar via Digitalmars-d-learn wrote: On Wed, 24 Sep 2014 12:21:40 + monarch_dodra via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Unfortunately, there is no generic function that allows striping of a specific ending range but for strings we have std.string.chomp. I missread that documentation. I thought it removed all characters that can also be found in delim. Power to me.
Re: put string[] into a appender without loop?
On Sunday, 21 September 2014 at 23:50:50 UTC, H. S. Teoh via Digitalmars-d-learn wrote: On Sun, Sep 21, 2014 at 11:41:56PM +, AsmMan via Digitalmars-d-learn wrote: I'd like to copy an array string into a appender!string() but I can't see how to do this without loop myself over the string array. Is there a native function or should I write it myself? Try this: import std.array : appender; import std.algorithm : joiner, copy; string[] arr = [ab, cd, efg]; auto app = appender!string(); arr.joiner.copy(app); assert(app.data == abcdefg); T FYI, that's probably scary expensive in terms of encoding/decoding. Using the free std.range.put should take care of everything, natively.
Re: can't understand why code do not working
On Monday, 22 September 2014 at 20:37:42 UTC, Cliff wrote: Is stdout threadsafe? Yes. All io operations lock in D, so are thread safe. You will never have interlaced io. If you want to do several opeations, then you can use LockingTextWriter, which is faster, s it locks once until you are finished. Though to be honest, the io itself is slow enough that I've never needed it.
Re: can't understand why code do not working
On Monday, 22 September 2014 at 21:19:37 UTC, Steven Schveighoffer wrote: On 9/22/14 4:37 PM, Cliff wrote: Is stdout threadsafe? Yes, stdout is thread safe, it's based on C's stdout which is thread safe. -Steve Techinallly, though thread safe, concurrent writes will create garbled text. D goes one step further in the sense that it prevents concurrent writes entirely.
Re: can't understand why code do not working
On Monday, 22 September 2014 at 20:12:28 UTC, Suliman wrote: std.concurrency.OwnerTerminated@std\concurrency.d(234): Owner terminated You need to make sure your main waits for its workers before exiting. When main dies, it sends an exception message to anyone still working.
Re: destroy(someStruct)
On Saturday, 20 September 2014 at 22:46:10 UTC, John Colvin wrote: import core.stdc.stdio; struct S { ~this() { printf(%x\n.ptr, this); } } void main() { S* sp = new S; destroy(*sp); S s; destroy(s); auto sa = new S[2]; foreach(ref s_; sa) destroy(s_); } output: 4002dff0 bfa89a70 4002dfe0 4002dfe1 bfa89a70 Note the double destruction of s Its seems that calling destroy on a stack-allocated struct is a no-no (unless you have a re-entrant destructor). The other two examples seem OK though. Am I in dangerous territory? Will I see unexpected double-destructions in some cases? Destroy leaves your struct in its T.init state, and T.init should always be destroyable. So even though the destroyer gets called twice, you should be perfectly safe. FYI, move relies on this mechanism: it sets object state to T.init, to make sure the later stack destruction has no side effect.
Re: std.range.byLine
On Friday, 12 September 2014 at 13:25:22 UTC, Nordlöw wrote: On Thursday, 11 September 2014 at 22:39:40 UTC, H. S. Teoh via Digitalmars-d-learn wrote: foreach (line; myInput.split(regex(`\n|\r\n|\r`))) Shouldn't you use foreach (line; myInput.split(regex(\n|\r\n|\r))) here? Probably not, as (AFAIK) the splitter engine *itself* will *also* escape the passed in characters. IE: It literally needs the characters '\' and 'n'.
Re: std.conv checking if to will work
On Thursday, 11 September 2014 at 08:58:09 UTC, Robert burner Schadek wrote: I like the to template a lot, but sometimes I want to make sure beforehand that a call to it works. Is there anything in phobos in missed to do that. And I don't want to try catch. There's an open request for it, and plans to have a bool maybeTo!(OUT, WHAT)(WHAT what, ref OUT out), but we aren't quite there yet. The idea is that *once* we have that, then to would simply become an enforce!maybeTo. But in the meantime, no. you have to trycatch.
Re: std.range.byLine
On Wednesday, 10 September 2014 at 23:01:44 UTC, Nordlöw wrote: On Wednesday, 10 September 2014 at 22:45:08 UTC, Nordlöw wrote: auto byLine(Range)(Range input) if (isForwardRange!Range) { import std.algorithm: splitter; import std.ascii: newline; static if (newline.length == 1) { return input.splitter(newline.front); } else { return input.splitter(newline); } } IMHO, this should be added to std.string and restricted to isSomeString. Should I do a PR? Well, the issue is that this isn't very portable for *reading*, as even on linux, you may read files with \r\n line endings (It's standard for csv files, for example), or read \n terminated files on windows. The issue is that (currently) we don't have any splitter that operates on multiple needles. *That'd* be what needs to be written (probably not too hard either, since find already exists). We also have splitLines, http://dlang.org/phobos/std_string.html#.splitLines;. Is that good enough for you by any chance? Or do you need it to actually be lazy?
Re: std.conv checking if to will work
On Thursday, 11 September 2014 at 09:33:20 UTC, Robert burner Schadek wrote: On Thursday, 11 September 2014 at 09:10:03 UTC, monarch_dodra wrote: There's an open request for it, and plans to have a bool maybeTo!(OUT, WHAT)(WHAT what, ref OUT out), but we aren't quite there yet. The idea is that *once* we have that, then to would simply become an enforce!maybeTo. But in the meantime, no. you have to trycatch. thanks for the quick anwser. Is anyone working on it currently? just for completeness the bugzilla entry is: https://issues.dlang.org/show_bug.cgi?id=6840 Nope, no one (AFAIK). I think it only needs a bit of refactoring std.conv, but it's a pretty damn big module.
Re: std.algorithm.reduce on an array of structs
On Thursday, 11 September 2014 at 14:56:00 UTC, Daniel Kozak via Digitalmars-d-learn wrote: V Thu, 11 Sep 2014 14:49:02 + bearophile via Digitalmars-d-learn digitalmars-d-learn@puremagic.com napsáno: Daniel Kozak: You can just use min: import std.stdio, std.algorithm; struct Thing { uint x; alias x this; } alias minimum = reduce!min; void main() { immutable ar1 = [10, 20, 30, 40, 50]; ar1.minimum.writeln; immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophile Yep, this look the most idiomatic :). Why there is no phobos function for minimum of array(range)? There is: http://dlang.org/phobos/std_algorithm.html#.minPos To note though: minPos will find the position of the smallest element, whereas reduce will accumulate and return the lowest value. That said: alias minmax = reduce!(min, max); auto mm = ar1.minmax(); auto min = mm[0]; auto max = mm[1]; Found both in one line of code, and only 1 iteration of ar1.
Re: std.algorithm.reduce on an array of structs
On Thursday, 11 September 2014 at 15:29:18 UTC, Daniel Kozak wrote: On Thursday, 11 September 2014 at 15:07:03 UTC, Daniel Kozak wrote: or use alias minimum = reduce!a b; ;) ok this one does not work Yeah, it's actually reduce!a b ? a : b
Re: std.range.byLine
On Thursday, 11 September 2014 at 20:03:26 UTC, Nordlöw wrote: On Thursday, 11 September 2014 at 10:19:17 UTC, monarch_dodra wrote: Well, the issue is that this isn't very portable for *reading*, as even on linux, you may read files with \r\n line endings (It's standard for csv files, for example), or read \n terminated files on windows. The issue is that (currently) we don't have any splitter that operates on multiple needles. *That'd* be what needs to be written (probably not too hard either, since find already exists). Good idea. So its just a matter of extending splitter with std.algorithm.find with these three keys: - \n - \r - \r\n then? Or are there more encodings to choose from? Hum... no, those are the correct splitting elements. However, I don't think that would actually work, as find will privilege the first whole element to match as a hit, so \r\n never be hit (rather, it will be hit twice, in the form of two individual line breaks `\r` and '\n'). Bummer...
Re: Intended behavior of std.range.cycle?
On Friday, 5 September 2014 at 10:41:22 UTC, Vlad Levenfeld wrote: On Thursday, 4 September 2014 at 11:43:28 UTC, monarch_dodra wrote: *Should* cycle be negatively index-able? Personally, I don't think so. And even if it could, it has been proven non-size_t indexing is not well supported at all. It was de-facto chosen after the iota-map fiasco that all ranges be indexed with size_t and nothing else... Can you elaborate on what the problem was? I'm curious as I've recently implemented a DSP module that uses ranges with floating-point slicing and, other than having to define a second kind of length (I call it measure so I can still have a discrete length when I need it), it seems to work well enough so far. It'd be bad if there were some unseen fiasco waiting for me... In itself, there is nothing wrong with having a shallow container that can be indexed from -inf to +inf. The issues might appear if you try to tag on the range interface on it. In particular, who is front? If I do a foreach over the sequence, then will it miss half the elements? What does it mean to slice from -5 to +5 ? Which element becomes the new 0? As for floating point indexing, it's the same thing. The indexing itself is fine, there's no problem there. But if you popFront, how many elements are you actually skipping over. What would it mean if I were to take(4.5) elements? *Overall*, it should be fine, but if you are creative, you could hurt yourself. I don't know your exact use case though. So my conclusion is mostly that as long as you only index, you should be fine. Mix in range adaptors, and things *could* become less stable. *could*. But you should still be mostly safe. Again, depends on use case.
Re: How to get nogc to work with manual memory allocation
On Sunday, 24 August 2014 at 09:29:53 UTC, Jacob Carlborg wrote: On 2014-08-24 10:03, Bienlein wrote: I have omitted the code for the TestClass class to save space. Problem is that the compiler outputs this: Error: @nogc function 'main.nogcNew!(TestClass, ).nogcNew' cannot call non-@nogc function 'core.exception.onOutOfMemoryError' Error: @nogc function 'main.nogcNew!(TestClass, ).nogcNew' cannot call non-@nogc function 'std.conv.emplace!(TestClass, ).emplace' Error: @nogc function 'main.nogcDel!(TestClass).nogcDel' cannot call non-@nogc function 'object.destroy!(TestClass).destroy' Is there a way to get around this? @nogc is a very new attribute. The runtime and standard library have not been properly annotated with this attribute yet. As a workaround you could try copy implementation of these functions to you're own code and annotate them as appropriate. The real issue here is actually the *language*. Exceptions and Errors are GC allocated, so if you try to check your no-GC allocation, you'll use the GC... A possible workaround is to preemptively static allocate the Error. However, this can cause issues if you chain Errors, or re-enter your function while throwing.
Re: Good/Bad? @disable postblit for struct InputRange
On Friday, 5 September 2014 at 19:55:50 UTC, Nick Sabalausky wrote: One issue with struct-based input ranges: Saving the state of an input range is not supported (by definition of input range), and yet, you can trivially and accidentally do so with a simple assignment or passing into a function. The results may or may not blow up depending on the exact situation. And if the input range happens to hit a poorly-implemented algorithm which *should* be statically requiring a ForwardRange and using .save() to duplicate state, but instead accepts any range and (accidentally?) saves state by simple struct copy...which will work fine for most struct-based forward ranges and therefore could go completely unnoticed...Then once again, your input range touches it and BOOM. This *could* be addressed by making the input range a class, but that seems a bit overkill in many cases. So I'm tempted to give my struct-bassed input ranges a @disable'd postblit. That would solve the problem, right? Would there be any reason NOT to do this? Ref semantics is one option, yes. Either by class, or by struct. For example, most IO ranges implemented ref-counted reference semantics. IMO, disabling postblit is overkill, as almost anything that does anything with ranges will pass them by value at one point or another. That said, most of the functions that do operate (and modify) a range either take it by reference, or return the modified copy. This means you can boomrang your range in and then back out. EG: r = doIt(r); For example, copy, find etc... do this. *Ideally*, these functions would do a move-return, and you'd pass-by-move, so you'd be able to effectively disable postblit, but still pass by move-value. Unfortunately, we aren't quite there yet... My 0.02$
Re: Intended behavior of std.range.cycle?
On Thursday, 4 September 2014 at 11:29:30 UTC, rcor wrote: auto c = cycle([1,2,3]); foreach(i ; iota(-4,4)) { writeln(c[i]); } prints the sequence 1 2 3 1 1 - c[0] == c[-1] 2 3 I understand this is what would happen if I were to just use modulus on an index to access the original array, but should Cycle really mimic this behavior? I feel like most uses of Cycle would expect element -1 to be the last element of the original range, not the first. I could manually apply addition with modulus to ensure that the index is always positive, but then there's not much benefit to using cycle anyways -- I might as well be accessing the original range. Is this behavior intentional or an oversight? Indexing is done with the unsigned size_t. You aren't indexing at -1, but rather, size_t.max. size_t.max % 3 probably doesn't result in 3 - 1 hence what you are observing. *Should* cycle be negatively index-able? Personally, I don't think so. And even if it could, it has been proven non-size_t indexing is not well supported at all. It was de-facto chosen after the iota-map fiasco that all ranges be indexed with size_t and nothing else...
Re: Intended behavior of std.range.cycle?
On Thursday, 4 September 2014 at 11:43:28 UTC, monarch_dodra wrote: Indexing is done with the unsigned size_t. I re-read your post, and I don't think I actually answered your question...? I don't know of any case where you'd want to index negativelly. That said, I'm sure it could be possible to wrap a cycle into a simple signed cycle adaptor. There's one issue with what you want to do though: Who is front, and where does your range start?
Re: Should formattedWrite take the outputrange by ref?
On Thursday, 4 September 2014 at 17:06:00 UTC, Márcio Martins wrote: On Wednesday, 3 September 2014 at 07:43:20 UTC, Guillaume Chatelet wrote: +1 I've been bitten by this also. Same here, +1 It's still on my radar, but it's actually not that trivial of a change, especially if we want to avoid breaking code, and binary bloat...
Re: Allowing Expressions such as (low value high)
On Thursday, 4 September 2014 at 20:03:57 UTC, Nordlöw wrote: Are there any programming languages that extend the behaviour of comparison operators to allow expressions such as if (low value high) ? This syntax is currently disallowed by DMD. I'm aware of the risk of a programmer misinterpreting this as if ((low value) high) Is this the reason why no languages (including D allows it). I'm asking for in some cases, where value is a long expression, it would be a nice syntatic sugar to use. In the case of D, it's a C compatibility thing. Other languages I don't know.
Re: Building a string from n chars
On Thursday, 4 September 2014 at 20:38:39 UTC, Nordlöw wrote: On Thursday, 4 September 2014 at 19:24:00 UTC, Nordlöw wrote: string t1; t1 ~= '*'.repeat(n).array; string t2; t2 ~= *.replicate(n); After having read http://dlang.org/phobos/std_array.html#.replicate I came to the conclusion that the lazy std.range:repeat is preferred. If lazy is good enough for you yes. AFAIK, replicate is *very* close in terms of implementation to what a.repeat(n).array() would do anyways. Heck, I'd be surprised if it did it differently, since (again, AFAIK) repeat.array() is optimal anyways. I'm still a bit confused about the fact that -vgc gives no warnings about GC-allocations, though. Strange indeed. Both solutions allocate a slice, and then append that slice. The s[]='*' Solution I gave you will not create a temporary allocation.
Re: Building a string from n chars
On Thursday, 4 September 2014 at 20:57:43 UTC, monarch_dodra wrote: On Thursday, 4 September 2014 at 20:38:39 UTC, Nordlöw wrote: On Thursday, 4 September 2014 at 19:24:00 UTC, Nordlöw wrote: string t1; t1 ~= '*'.repeat(n).array; string t2; t2 ~= *.replicate(n); After having read http://dlang.org/phobos/std_array.html#.replicate I came to the conclusion that the lazy std.range:repeat is preferred. If lazy is good enough for you yes. AFAIK, replicate is *very* close in terms of implementation to what a.repeat(n).array() would do anyways. Heck, I'd be surprised if it did it differently, since (again, AFAIK) repeat.array() is optimal anyways. I re-read the doc and implementation: replicate replicates a *range*. It is a bit optimized to detect the case where the range is a single element, but it still has to do the check, and even then (implementation detail), it is less efficient. I might create a pull to tweak that.
Re: opSlice() or opIndex() for the entire slice?
On Thursday, 4 September 2014 at 19:12:27 UTC, Ali Çehreli wrote: The documentation says To overload a[], simply define opIndex with no parameters: http://dlang.org/operatoroverloading.html#Slice And it works with some uses of a[]. However, opSlice() seems to be needed to actually use the returned slice further. This must be new, as I've read that page several times, and have never seen that before. Furthermore, I've done a *lot* pulls to improve ranges' slicing capabilities, and no reviewer has ever mentioned this before.
Re: std.container.Array
On Wednesday, 3 September 2014 at 16:44:45 UTC, Casper Færgemand wrote: Is there a good reason std.container.Array doesn't work with @nogc? The ddoc seems pretty explicit about its purpose: Array type with deterministic control of memory. The memory allocated for the array is reclaimed as soon as possible; there is no reliance on the garbage collector. Array uses malloc and free for managing its own memory. Well, for starters, probably simply because we didn't take the right precautions to make it work. It should. I'll look into it. That said, keep in mind that Array only manages *its* objects. But when an Array has pointers, then it *will* tell the GC it holds indirections, and that it should be scanned in regards to the cleanup of *other* objects. Think Array!string.
Re: Building a string from n chars
On Wednesday, 3 September 2014 at 19:43:26 UTC, Nordlöw wrote: Is there a simpler way to way to s ~= repeat('*', n).array.to!string; if s has to be of type string? s ~= repeat('*', n).array(); Should be enough. Why the to!string? There's 1 useless allocation, but I think that's OK for code this trivial? Else, you can do: s.length+=n; s[$-n .. $] []= '*'; This is also relatively simple. The ownside is doing double assignement, as length will initialize new elements to char.init. Probably not noticeable. There *might* be more efficient ways to do it, but I'd doubt it qualifies as simpler. Or if it's really observeable. Are these good enough for you?
Re: Comparing TypeTuples
On Tuesday, 2 September 2014 at 08:27:14 UTC, Tudor Berariu wrote: How can I check if two TypeTuples containing both types and values are the same? This fails: static assert(is(TypeTuple!(3, int, Zorro) == TypeTuple!(3, int, Zorro))); Thank you! Tudor Yeah, this fails because you can't use is(a == b) with values. However, *you* use is(a) to check if a is an actual type. Then, you can do something like: alias Args1 = TypeTuple!(3, int, Zorro); alias Args2 = TypeTuple!(3, int, Zorro); static assert(Args1.length == Args2.length); foreach (I, _; Args1) { pragma(msg, I); static assert(is(Args1[I]) == is(Args2[I])); static if (is(Args1[I])) static assert(is(Args1[I] == Args2[I])); else static assert(Args1[I] == Args2[I]); }
Re: Implementing Template Restrictions in Different Way
On Monday, 1 September 2014 at 22:46:52 UTC, Nordlöw wrote: Is this a other/newer preferred way to describe the template restriction, using for example __traits(compiles, ...)? Is is(typeof(... AFAIK, those produce the same results 99% of the time. The only cases where they differ are borderline buggy. the fastest way to do this? Are you talking about constraints, or implementation of safeSkipOver? BTW: Is there a way to prevent the calls to r1.length and r2.length in this case? Hum... Are you writing this function because skipOver will actually fail? AFAIK, it shouldn't. We should fix skipOver...
Re: Implementing Template Restrictions in Different Way
On Monday, 1 September 2014 at 22:46:52 UTC, Nordlöw wrote: BTW: Is there a way to prevent the calls to r1.length and r2.length in this case? Also, this assumes your ranges have front at all. AFAIK, skipOver operates on forward ranges. Related: Your condition could fail if R1/R2 are strings of un-matching widths.
Re: Implementing Template Restrictions in Different Way
On Tuesday, 2 September 2014 at 11:41:51 UTC, Nordlöw wrote: On Tuesday, 2 September 2014 at 10:22:49 UTC, monarch_dodra wrote: the fastest way to do this? Are you talking about constraints, or implementation of safeSkipOver? The constraint. In that case, I'm not sure what you mean by fastest in the context of constraints, which are compile-time. Hum... Are you writing this function because skipOver will actually fail? AFAIK, it shouldn't. We should fix skipOver... Yes, I'm writing this wrapper because call to r.front in bool skipOver(alias pred = a == b, R, E)(ref R r, E e) if (is(typeof(binaryFun!pred(r.front, e { if (!binaryFun!pred(r.front, e)) return false; r.popFront(); return true; } fails when r is empty. It believe it should be if (r.empty || !binaryFun!pred(r.front, e)) right? Should I do a PR? I think so yes. That's the R/E version though. Is the R/R version also subject to this issue?
Re: Overriding to!string on enum types
On Tuesday, 2 September 2014 at 14:59:41 UTC, evilrat wrote: sorry, i forgot everything. here is example of how to do this - import std.conv : to; enum Test { One, Two, Three, } template to(T: string) { T to(A: Test)(A val) { final switch (val) { case Test.One: return 1; case Test.Two: return 2; case Test.Three: return 3; } } } void main() { assert(to!string(Test.One) == 1); auto t = cast(Test)2; assert(to!string(t) == 3); assert(to!int(4) == 4); // shows original to! template works } Word of warning: You are not overriding to, but rather, simply defining your own to locally, which resolves as a better match in the context where you are using it. If you pass the enum to another function in another module, your to will NOT be called.
Re: Overriding to!string on enum types
On Tuesday, 2 September 2014 at 12:54:55 UTC, Nordlöw wrote: Is it possible to override the behaviour of to!string(x) when x is an enum. I'm asking because this enum CxxRefQualifier { none, normalRef, rvalueRef } string toString(CxxRefQualifier refQ) @safe pure nothrow { final switch (refQ) { case CxxRefQualifier.none: return ; case CxxRefQualifier.normalRef: return ; case CxxRefQualifier.rvalueRef: return ; } } doesn't affect behaviour of to!string(x) when x is an instance of CxxRefQualifier. That won't work, because your toString is a free function. The module system doesn't allow this kind of Koenig lookup-like hijack. The only reason it allows for things like front/popFront and arrays, is that the other modules import std.array, and are aware of the functions. This is not true for user defined types. This may or may not be a feature :) Unless we allow defining enum-member functions, AFAIK, it is impossible to override the printing behavior for enums... short of injecting your own modules in std.format/std.conv. Or to have a parameter moduleLookup in said template functions.
Re: Overriding to!string on enum types
On Tuesday, 2 September 2014 at 15:41:17 UTC, monarch_dodra wrote: Unless we allow defining enum-member functions, AFAIK, it is impossible to override the printing behavior for enums... ... If your enum actually represents strings, then you could: enum CxxRefQualifier : string { none = , normalRef = , rvalueRef = , } That in itself is not enough, but you *can* cast your enum to string, and then print that, or pass that. See also: https://issues.dlang.org/show_bug.cgi?id=11571
Re: Reading unicode chars..
On Tuesday, 2 September 2014 at 17:10:57 UTC, Ali Çehreli wrote: 1) To avoid a common gotcha, note that 'line' is reused at every iteration here. You must make copies of portions of it if you need to. Ali I don't know if you are aware, but byLineCopy was recently introduced. It will be available in 2.067. Just spreading info.
Re: Reading unicode chars..
On Tuesday, 2 September 2014 at 18:30:55 UTC, seany wrote: Your example reads the file by lines, i need to get them by chars. If you are intent on reading the stream character (or wcharacter) 1 by 1, then you will have to decode them manually, as there is no getcd. Unfortunately, the newer std.stdio module does not really provide facilities for such unitary reads. I'd suggest you create a range out of your std.stream.File, which reads it byte by byte. Then, you pass it to the byDchar() range, which will auto decode those characters. If you really want to do it character by character. What's wrong with reading line by line, but processing the characters in said lines 1 by 1? That works out of the box.
Re: Why is rehash not @safe?
On Saturday, 30 August 2014 at 14:27:04 UTC, Nordlöw wrote: I just noticed that AA rehash is @system. Is there a reason for this? Is it system because bad things can happen or simply because it's a low level function? Should I always tag functions calling rehash as @trusted? AFAIK, the whole problem is one of attributes, and run-time inference. AA's are mostly run-time implemented. When you have a U[T], and you want to rehash, then the AA will make a run-time call to typeinfo(T).hash(); The issue is that here, you need to support *all* of the hash function for *all* of the T types. If you make rehash @trusted, then you may end up calling @system hash functions in a @safe context. If you make it @safe, then you either break code, or make it impossible for end users to provide their @system hash functions. Really, it's lose-lose. The only (AFAIK) solution is to migrate AA's to a template-library that individually infers the correct safety for every types.
Re: Issue with dmd 2.066, alias this, and sort
On Wednesday, 27 August 2014 at 21:43:40 UTC, bearophile wrote: rcor: I've tried to express my problem in a mostly minimal example here: https://gist.github.com/murphyslaw480/d4a5f857a104bcf62de1 The class Point has an alias this to its own property 'feature()', which returns a reference to a private member. When I try to sort a Point[], DMD fails with mutable method feature is not callable on const object. I'm not actually using the property 'feature()' or the alias this in the sorting, so it seems like it shouldn't interfere. That being said, I'm still slightly const-challenged so maybe its an error on my part. However, the above example compiles fine with DMD 2.065.0-3. It compiles if you use: @property auto feature() const pure nothrow { return _feature; } Otherwise I get strange errors like: ...\dmd2\src\phobos\std\exception.d(986,31): Error: pure function 'std.exception.doesPointTo!(Point, Point, void).doesPointTo' cannot call impure function 'temp.Point.feature' Bye, bearophile Seems like a library bug. Unsure if DMD or phobos for this one, but there is definitely a phobos bug to be fixed anyways. I'll investigate both.
How to cast to void*, while bypassing alias this or opCast
I'm investigating a phobos regression. From doesPointTo: // static if (isPointer!S || is(S == class) || is(S == interface)) { const m = cast(void*) source; // Basically, given a pointer like structure, I want the void* equivalent. I really don't care about how S works, and am observing the source object as nothing more than a bag of member fields. The issue though is that it turns out that such code can and will call either opCast or alias this, which is *not* what we want at all in this piece of code. Is there any way to do a hard reinterpret cast in such a situation?
Re: Issue with dmd 2.066, alias this, and sort
On Thursday, 28 August 2014 at 10:38:12 UTC, monarch_dodra wrote: On Wednesday, 27 August 2014 at 21:43:40 UTC, bearophile wrote: rcor: It compiles if you use: @property auto feature() const pure nothrow { return _feature; } Otherwise I get strange errors like: ...\dmd2\src\phobos\std\exception.d(986,31): Error: pure function 'std.exception.doesPointTo!(Point, Point, void).doesPointTo' cannot call impure function 'temp.Point.feature' Bye, bearophile Seems like a library bug. Unsure if DMD or phobos for this one, but there is definitely a phobos bug to be fixed anyways. I'll investigate both. DMD issue: https://issues.dlang.org/show_bug.cgi?id=13392 Phobos issue: http://forum.dlang.org/thread/uignsankcumgmhwpo...@forum.dlang.org#post-uignsankcumgmhwpoead:40forum.dlang.org
Re: How to cast to void*, while bypassing alias this or opCast
On Thursday, 28 August 2014 at 11:02:03 UTC, anonymous wrote: On Thursday, 28 August 2014 at 10:45:52 UTC, monarch_dodra wrote: I'm investigating a phobos regression. From doesPointTo: // static if (isPointer!S || is(S == class) || is(S == interface)) { const m = cast(void*) source; // Basically, given a pointer like structure, I want the void* equivalent. I really don't care about how S works, and am observing the source object as nothing more than a bag of member fields. The issue though is that it turns out that such code can and will call either opCast or alias this, which is *not* what we want at all in this piece of code. Is there any way to do a hard reinterpret cast in such a situation? *cast(void**)source Hum... now I feel retarded. In my mind I had I want re-interpret, not address of, so no operator. Thanks.
Re: Issue with dmd 2.066, alias this, and sort
On Thursday, 28 August 2014 at 10:54:47 UTC, monarch_dodra wrote: Phobos issue: http://forum.dlang.org/thread/uignsankcumgmhwpo...@forum.dlang.org#post-uignsankcumgmhwpoead:40forum.dlang.org https://github.com/D-Programming-Language/phobos/pull/2472
Re: 'idiomatic' porting of c and or c++ code that does NULL checking
On Saturday, 23 August 2014 at 10:33:02 UTC, nikki wrote: A good to know! thanks. I'd still be interrested to see the idiomatic D version of that function, what would that depend on ? Honestly, I wouldn't change it much. If it didn't throw exceptions before, then it probably would have trouble handling them now. What I *would* do is use multiple returns though. This style of if/else invariably leads to the dreaded diagonal line of death (http://geekandpoke.typepad.com/geekandpoke/2009/12/geek-for-dummies-chapter-2.html) Once you've done that, any resource you'd have otherwise needed to Un-conditionally release, I'd do with a scope. bool init() { //Initialize SDL if( SDL_Init( SDL_INIT_VIDEO ) 0 ) { printf( SDL could not initialize! SDL_Error: %s\n, SDL_GetError() ); return false; } //Create window gWindow = SDL_CreateWindow( SDL Tutorial, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if( gWindow == NULL ) { printf( Window could not be created! SDL_Error: %s\n, SDL_GetError() ); return false; } //Get window surface gScreenSurface = SDL_GetWindowSurface( gWindow ); return true; } Now, once you've adopted this kind of style, migrating to exceptions (should you so wish to do so) should much easier.
Re: Acces Values in DList
On Saturday, 23 August 2014 at 15:18:15 UTC, axwro wrote: On Saturday, 23 August 2014 at 14:54:55 UTC, axwro wrote: How can i access values in DList? I save different objects of type Property in my DList, but if i want to access them this way: this.properties[0].value.start i get: Error: no [] operator overload for type DList!(Property) Fixed, i just used Array!Property DList implements what is known as a (doubly) linked list. It is a container type that is not capable of providing random acess. As such, you cannot do properties[0]. You can either access the first (front) value individually, or iterate your DList (via its range interface foreach(val; this.properties[]) {...}). Array implements a basic contiguous sequence of elements (hence provides RA). It is important you understand what you are using, and which container best fits your needs.
Re: Module-level attributes and unit tests
On Saturday, 23 August 2014 at 15:26:02 UTC, Leandro Motta Barros via Digitalmars-d-learn wrote: Hello, I have a module which is completelly @nogc, and as such I'd like to just say @nogc: at the top of the file and be happy. However, my unit tests for this same module do some GC allocation, so the module fails to compile. Is there a way to disable @nogc for the unit tests only? Would this be a bad idea in some way I cannot see? Nope. At best, you might be able to *declare* a function that is GC, but even then, you wouldn't be able to call it. I suppose the same question is valid for other attributes, like 'nothrow' and '@safe'. Actually, you can undo @safe with an explicit @system. nothrow (and pure) are in the same boat as @nogc Thank you, LMB Solutions I can see would be to: a) Put your unittests in a separate module. b) Place your unittests before your @nogc: c) Instead of using @nogc:, use @nogc {}: This will make @nogc run until the end of the block.
Re: Generating a tree structure
On Thursday, 21 August 2014 at 14:09:24 UTC, Ricky C wrote: TileTree* self; Don't do that. D has banned internal pointers to implement its move semantics. branches[index] = tile_trees[index]; This will make a *value-copy* of your TileTree nodes. There are good chances it'll break your tree. As a rule of thumbn when managing an Node-like structure, try to avoid storing them by value in a container. Unless you are *exceptionally* about not copying the nodes from one container to another, you'll usually end up shooting yourself in the foot. This is particularly relevant what when you have an internal pointer, as the copy will point to the old node, not itself. Try to rewrite your code to use TileTree* objects instead: http://dpaste.dzfl.pl/13194a966c07
Re: Variadic parameter of length 1
On Wednesday, 20 August 2014 at 15:11:53 UTC, Dominikus Dittes Scherkl wrote: I have several times seen a construct template foo(T...) if(T.length == 1) { ... } What is that good for? Why using variadic parameter if anyway exactly one parameter is required?!? AFAIK, it's a historical workaround to accept T as either alias or not alias, as varargs have auto alias. EG: foo!int //OK foo!hello //OK too
Re: Variadic parameter of length 1
On Wednesday, 20 August 2014 at 17:02:59 UTC, Dicebot wrote: On Wednesday, 20 August 2014 at 15:34:30 UTC, Dominikus Dittes Scherkl wrote: And why historical? Is that not necessary anymore? What better solution is there today? Historical in a sense that distinct can be anything template parameter is probably a better approach but it is too late to change such core language part. Yeah, what he said. It's a language artifact.
Re: Can you explain this?
On Wednesday, 20 August 2014 at 20:39:42 UTC, Jonathan M Davis wrote: is(typeof(foo)) and __traits(compiles, foo) are not the same. The first tests for the existence of the symbol, whereas the second checks whether the code will actually compile. Is that even true? I mean, are you just repeating something you've heard, or have you checked? is(typeof(foo)) has always failed for me merelly if foo fails to compile. foo being an existing (but private) symbol is enough. Test case: // module foo; struct S { private int i; } // import foo; void main(string[] args) { S s; writeln(is(typeof(s.i))); writeln(__traits(compiles, s.i)); } // This says false, false. I've yet to find a usecase where is(typeof(...)) and __traits(compiles, ...) aren't interchangeable. I mean, I may have missed something, but it seems the whole private thing is just miss-information.
Re: new error message in 2.066, type bool (const)
On Wednesday, 20 August 2014 at 20:46:20 UTC, Paul D Anderson wrote: Re-compiling existing code with version 2.066 generates a lot of errors complaining about implicit conversion to const. Typical is this call (inside a struct with properties 1 2): z.sign = x.sign ^ y.sign; Error: None of the overloads of 'sign' are callable using argument types bool (const), candidates are: 1) @property @safe bool sign() const { return signed; } 2) @property @safe bool sign(in bool value) { signed = value; return signed; } What changed? It ran okay with early beta versions, but not with the release. Paul Could you provide a short, but complete program that reproduces the issue? With this: // struct S { bool signed; @property @safe bool sign() const { return signed; } @property @safe bool sign(in bool value) { signed = value; return signed; } } void main(string[] args) { S s; s.sign = s.sign ^ s.sign; } // It works for me with both 2.065.0 and 2.066.0. What is the type of signed ? Is it something other than bool, by any chance?
Re: String Prefix Predicate
On Monday, 18 August 2014 at 20:50:55 UTC, Nordlöw wrote: On Monday, 18 August 2014 at 12:42:25 UTC, monarch_dodra wrote: If you are using a string, the only thing helpful in there is `byCodeunit`. The rest is only useful if you have actual ranges. Actual ranges of...characters and strings? Could you gives some examples? I'm curious. You could define your own range of chars, for example, a rope. Or, you want to store your string in a deterministic container (Array!char). These would produce individual code units, but you'd still need them to be interpreted your range as a sequence of code points. This is where `byDchar` would come in handy. There is a fair bit of discrepancy between a char[], and a range where `ElementType!R` is `char`, which is quite unfortunate. There have been talks of killing auto-decode, in which case, a range of chars would have the same behavior as a char[].
Re: In the new D release why use free functions instead of properties?
On Monday, 18 August 2014 at 21:17:11 UTC, Jonathan M Davis wrote: On Monday, 18 August 2014 at 21:02:09 UTC, Gary Willoughby wrote: In the new D release there have been some changes regarding built-in types. http://dlang.org/changelog.html?2.066#array_and_aa_changes I would like to learn why this has been done like this and why it is desired to be free functions rather than properties? Probably because they never should have been properties in the first place. Properties are supposed to emulate variables, whereas something like dup is clearly an action. So, it's clearly not supposed to be a property. However, because D doesn't require parens on a function with no arguments, you can still call it without parens. Some of the changes probably also help with cleaning up the AA internals, which is sorely needed. - Jonathan M Davis Actually, the new free functions *are* properties. All that you just declared is valid, but we never got around to doing it. Walter (If I remember correctly) was opposed. So right now, even if dup is a free function, myArray.dup() is still invalid. :(
Re: goto skips declaration of variable
On Monday, 18 August 2014 at 13:51:14 UTC, nrgyzer wrote: Hi all, I've the following code snipped: import std.bigint; void main(string[] args) { BigInt i = 12345; if (args.length 1) { goto Exit; } i = BigInt(67890); Exit: return; } For what it's worth, whenever you have goto-end style code, place all your code in a proper block, in such a way that all your variable declarations are in that block, and all your gotos break out of this block. This way, a goto will *never* cross a declaration, so coding is easy. The only variables you place at the top or the ones that could need cleanup. void main(string[] args) { //Declarations that need cleanup: void* p; //Code { BigInt i = 12345; //Local variable if (args.length 1) { goto Exit; //Breaks out of block } i = BigInt(67890); BigInt j = 54321; //Local variable } //End Exit: CleanUp(p); return; }
Re: String Prefix Predicate
On Monday, 18 August 2014 at 11:28:25 UTC, Nordlöw wrote: On Saturday, 16 August 2014 at 20:59:47 UTC, monarch_dodra wrote: I don't get it? If you use byDchar, you are *explicitly* decoding. How is that any better? If anything, you are *preventing* the (many) opportunities phobos has to *avoid* decoding when it can... byDchar and alikes are lazy ranges, ie they don't allocate. Lazy does NOT mean does not allocate. You are making a terrible mistake if you assume that. Furthermore decoding does NOT allocate either. At worst, it can throw an exception, but that's exceptional. They also don't throw exceptions which is preferably in some cases. Even then, startsWith(string1, string2) will *NOT* decode. It will do a binary comparison of the codeunits. A fast one at that, since you'll use SIMD vector comparison. Because of this, it won't throw any exceptions either. This compiles just fine: void main() nothrow { bool b = foobar.startsWith(foo); } In contrast, with: whole.byDchar().startsWith(part.byDchar()) You *will* decode. *THAT* will be painfully slow. Read the details at https://github.com/D-Programming-Language/phobos/pull/2043 If you are using a string, the only thing helpful in there is `byCodeunit`. The rest is only useful if you have actual ranges. If you are using phobos, you should really trust the implementation that decoding will only happen on a as needed basis.
Re: Using std.container.BinaryHeap like C++
On Monday, 18 August 2014 at 06:50:08 UTC, Paulo Pinto wrote: On Sunday, 17 August 2014 at 21:09:04 UTC, monarch_dodra wrote: On Sunday, 17 August 2014 at 18:54:27 UTC, Paulo Pinto wrote: Hi, I was wondering if it is possible to use the BinaryHeap store like the C++'s make_heap/pop_heap/push_heap functions. I would like to port to D some A* C++ code I have which rearranges the priorities on the underlying store, followed by another make_heap() call on the vector used as store. Doing the same in D by calling again heapify() does not seem to provide similar behavior. Just curious about it, as I don't plan to invest too much time on it. Thanks, Paulo AFAIK, D's BinaryHeap works just like C++'s make_heap/pop_heap/push_heap, except that it provides an actual object you can interface with, which has font, removeFront, removeAny and insert. What exactly is the difference in behavior you are seeing? Just different results that can be attributed to implementation details, or fundamental differences? It doesn't seem to like I change the store contents directly under its feet and recalling heapify again on the same store, like I am doing in C++'s heap. Sometimes I get a different sequence of data or just a crash. I still need to make the D code reflect my latest C++ changes, as the C++ code is what really matters in this hobby project, there is where my focus has been lately. The D version is more of a playing around thing. As I said, I curious what the behavior is supposed to be. Thanks, Paulo Weird. The behavior should be the same as C++'s. As I said, the difference is that D gives you a handle object. This object assumes you *don't* modify it's store under the hood, but as long as you don't use the heap after a store modification, you should be fine. Do you have a minimal test case?
Re: Using std.container.BinaryHeap like C++
On Sunday, 17 August 2014 at 18:54:27 UTC, Paulo Pinto wrote: Hi, I was wondering if it is possible to use the BinaryHeap store like the C++'s make_heap/pop_heap/push_heap functions. I would like to port to D some A* C++ code I have which rearranges the priorities on the underlying store, followed by another make_heap() call on the vector used as store. Doing the same in D by calling again heapify() does not seem to provide similar behavior. Just curious about it, as I don't plan to invest too much time on it. Thanks, Paulo AFAIK, D's BinaryHeap works just like C++'s make_heap/pop_heap/push_heap, except that it provides an actual object you can interface with, which has font, removeFront, removeAny and insert. What exactly is the difference in behavior you are seeing? Just different results that can be attributed to implementation details, or fundamental differences?
Re: @safe, pure and nothrow at the beginning of a module
On Saturday, 16 August 2014 at 19:30:16 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: On Sat, 16 Aug 2014 14:39:00 +0200 Artur Skawina via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On 08/16/14 13:58, Philippe Sigaud via Digitalmars-d-learn wrote: On Sat, Aug 16, 2014 at 1:30 PM, Artur Skawina via Digitalmars-d-learn http://forum.dlang.org/post/mailman.125.1397731134.2763.digitalmar...@puremagic.com Okay... So @safe includes child scopes. I suppose @trusted and @system work in the same way. *but* nothrow, @nogc and UDA's do not include child scopes. Putting them at the beginning of a module will not affect methods in aggregates... What's the situation for pure? (I don't have a D compiler handy right now, or I would test it myself). @safe, @trusted, @system, shared, immutable, const, inout and `extern (...)` affect child scopes. `synchronized` does too, but in a rather unintuitive way; hopefully nobody uses this. ;) Other attributes, including 'pure' and 'nothrow' only affect symbols in the current scope. It sounds like a bug to me if they're not consistent. - Jonathan M Davis Well, you got @system to override @safe, but no @impure or @throws. So the behavior can kind of make sense in a way. Maybe.
Re: drop* and take* only for specific element values
On Thursday, 14 August 2014 at 07:30:59 UTC, Nordlöw wrote: On Thursday, 14 August 2014 at 00:56:47 UTC, Jonathan M Davis wrote: You forgot the !, making the predicate a function argument. It Great! My solution: Depending on your exact needs, don't forget too about findSkip (same as find, but skips found element), as well as filter. In particular, r.filter!pred.take(N) would give you a (lazy) range consisting of the first 10 elements in r that verify pred. In some cases, until could also suit your needs. Long story short, D range and algorithms are little building blocks. There aren't that many basic functions that can't simply be expressed as a combination of already existing blocks.
Re: String Prefix Predicate
On Thursday, 14 August 2014 at 17:41:08 UTC, Nordlöw wrote: On Thursday, 14 August 2014 at 17:33:41 UTC, Justin Whear wrote: std.algorithm.startsWith? Should auto-decode, so it'll do a What about https://github.com/D-Programming-Language/phobos/pull/2043 Auto-decoding should be avoided when possible. I guess something like whole.byDchar().startsWith(part.byDchar()) is preferred right? I don't get it? If you use byDchar, you are *explicitly* decoding. How is that any better? If anything, you are *preventing* the (many) opportunities phobos has to *avoid* decoding when it can... If you really want to avoid decoding, use either representation which will do char[] = ubyte[] conversion, or byCodeUnit, which will create a range that returns single elements (IMO, byCodeUnit should be prefered over byChar, as it infers the correct width).
Re: String Prefix Predicate
On Saturday, 16 August 2014 at 20:59:47 UTC, monarch_dodra wrote: If anything, you are *preventing* the (many) opportunities phobos has to *avoid* decoding when it can... By that I want to stress what Jonathan M Davis said Unless the string types match, there's no way around it. You should absolutely realize that that means that when the string types (widths) *do* match, then search (which includes all flavors in phobos) will NOT decode. Heck, if you do a string, element search, eg find(my phrase, someDchar), then phobos will *encode* someDchar into a correctly sized string, and then do a full non-decoding string-string search, which is actually much faster than the naive decoding search.
Re: Appender is ... slow
On Friday, 15 August 2014 at 11:57:30 UTC, Messenger wrote: T[size] beats all of those on dmd head, though it is inarguably a bit limiting. Hey guys, just a bit of background and my own understanding of Appender, having worked on it a fair bit. First of all, Appender was not designed as a neck-breaking, mind-bending speed object. It is merely a tool to offset the slow GC-based appending. Indeed, when doing a raw GC-append, you first have to give the GC a pointer to the start of your array. The GC will then lookup in which block that pointer belongs, then look up the info related to that block, check if appending is possible, and then do the append proper... ...And then it will do all that all over again on the next append. Appender is simply a tool to cache the results of that once, and then do quicker appends. There are two other things to take into consideration with Appender: For starters, it can append to an *existing* array it is given. Second, you may destroy the Appender object at any time, and the referenced array is still valid: Appender does not *own* its buffer, and as such, is not allowed certain optimizations. Really, it's just designed for convenience and pretty good speed. Also, another thing to take into account when benchmarking, is that Appender is a reference semantic object: It has a payload which itself references an array. This creates a double indirection. This usually doesn't have much impact, but with the right optimizations, it can probably explain the x10 performance differences we are seeing, in our *synthetic* benchmarks. I have some doubts about the validity of the results in a real application. So TL;DR; yeah, you can probably do faster. But Appender is convenient, fast enough, and works with the GC. If you *do* need super speeds, look into something a bit more manual: Walter's ScopeBuffer would be a good choice. I also did some work on something called ScopeAppender, but didn't have time to finish it yet. https://github.com/monarchdodra/phobos/compare/ScopeAppender It provides better speeds and deterministic management, at the cost of partial private buffer ownership.
Re: Appender is ... slow
On Friday, 15 August 2014 at 12:08:58 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: Hmm, what about a sort of linked list of static arrays, that allocates a new one when necessary? Appender is not a container, and has no freedom on the data it manipulates. It has to be able to accept an array as input, and when it is finished, it needs to be able to return an actual array, so that's arguably out of the question.
Re: Appender is ... slow
On Friday, 15 August 2014 at 14:40:36 UTC, Philippe Sigaud wrote: Well, I created a wrapper around a std.array.uninitializedArray call, to manage the interface I need Make sure you don't use that if your type has elaborate construction, or assumes a certain initial state (unless you are actually emplacing your objects of course). I thought that, having lots of concatenation in my code, that'd be a bottleneck. But it appears than pre-allocation does not give me any speed-up. If you are using raw GC arrays, then the raw append operation will, outweigh the relocation cost on extension. So pre-allocation wouldn't really help in this situation (though the use of Appender *should*)