Re: opIndexAssign
On 10/3/23 00:11, Salih Dincer wrote: Hi, opIndexAssign, which is void, cannot compromise with opIndex, which is a ref! Solution: Using opSliceAssign. Could this be a bug? Because there is no problem in older versions (e.g. v2.0.83). ```d struct S { int[] i; ref opIndex(size_t index) => i[index]; auto opSliceAssign/* auto opIndexAssign//*/ (int value) => i[] = value; } void main() { auto s = S([1, 2]); s[] = 2; assert(s.i == [2, 2]); s[1] = 42; assert(s.i == [2, 42]); } ``` **Source:** https://run.dlang.io/is/G3iBEw If you converted comment line 7 with // and you will see this error: onlineapp.d(19): Error: function `onlineapp.S.opIndexAssign(int value)` is not callable using argument types `(int, int)` onlineapp.d(19): expected 1 argument(s), not 2 SDB@79 void opIndexAssign(int value, int index){ i[index] = value; }
Re: Problem with dmd-2.104.0 -dip1000 & @safe
On 6/9/23 06:05, An Pham wrote: Getting with below error for following codes. Look like bug? onlineapp.d(61): Error: scope variable `a` assigned to non-scope parameter `a` calling `foo` @safe: struct A(S = string) { @safe: S s; void delegate() c; } struct B(S = string) { @safe: @disable this(); this(C!S c, A!S a) { this.c = c; this.a = a; } C!S foo() { return c; } A!S a; C!S c; } class C(S = string) { @safe: C!S foo(A!S a) { auto o = new Object(); return foo2(o, a); } C!S foo2(Object n, A!S a) { auto b = B!S(this, a); return b.foo(); } } unittest { static struct X { @safe: void foo3() { } } X x; A!string a; a.s = "foo"; a.c = auto c = new C!string(); c.foo(a); } void main() { } I think the behavior you are seeing here is by design. There are two things happening: - There is no `scope` inference for virtual methods, as it is impossible to get the inference right without knowing all overriding methods in advance. - You cannot mark the parameter `a` `scope`, because the lifetimes of `this` and `a` become conflated within `b` in the body of `foo2` when calling the constructor of `B!S`, and `this` is subsequently escaped. As Dennis points out, a workaround is to mark the parameter `a` `return scope`. However, this may lead to other problems down the line, as `a` is never actually escaped.
Re: Why are globals set to tls by default? and why is fast code ugly by default?
On 4/1/23 17:02, Ali Çehreli wrote: Does anyone have documentation on why Rust and Zip does not do thread local by default? Rust just does not do mutable globals except in unsafe code.
Re: Is this a violation of const?
On 7/30/22 15:19, Salih Dincer wrote: On Saturday, 30 July 2022 at 10:02:50 UTC, Timon Gehr wrote: It's a `const` hole, plain and simple. This code, which consists of 26 lines, does not compile in DMD 2.087. I am getting this error: constHole.d(15): Error: mutable method `source.Updater.opCall` is not callable using a `const` object constHole.d(15): Consider adding `const` or `inout` to source.Updater.opCall constHole.d(21): Error: function `source.Updater.opCall(string s)` is not callable using argument types `(string*)` constHole.d(21): cannot pass argument `` of type `string*` to parameter `string s` SDB@79 Exactly. This is my point. This code does not compile, and neither should the original version, because it's doing basically the same thing.
Re: Is this a violation of const?
On 7/30/22 00:16, H. S. Teoh wrote: On Fri, Jul 29, 2022 at 09:56:20PM +, Andrey Zherikov via Digitalmars-d-learn wrote: In the example below `func` changes its `const*` argument. Does this violates D's constness? ```d import std; struct S { string s; void delegate(string s) update; } void func(const S* s) { writeln(*s); s.update("func"); writeln(*s); } void main() { auto s = S("test"); s.update = (_) { s.s = _; }; writeln(s); func(); writeln(s); } ``` The output is: ``` S("test", void delegate(string)) const(S)("test", void delegate(string)) const(S)("func", void delegate(string)) S("func", void delegate(string)) ``` At first I thought this was a bug in the const system, It very much is. https://issues.dlang.org/show_bug.cgi?id=9149 (Note that the fix proposed in the first post is not right, it's the call that should be disallowed.) but upon closer inspection, this is expected behaviour. The reason is, `const` guarantees no changes *only on the part of the recipient* of the `const` reference; The delegate _is_ the recipient of the delegate call. The code is calling a mutable method on a `const` receiver. it does not guarantee that somebody else doesn't have a mutable reference to the same data. For the latter, you want immutable instead of const. So in this case, func receives a const reference to S, so it cannot modify S. However, the delegate created by main() *can* modify the data, This delegate is not accessible in `func`, only a `const` version. because it holds a mutable reference to it. So when func invokes the delegate, the delegate modifies the data thru its mutable reference. ... `const` is supposed to be transitive, you can't have a `const` delegate that modifies data through 'its mutable reference'. Had func been declared with an immutable parameter, it would have been a different story, because you cannot pass a mutable argument to an immutable parameter, so compilation would fail. Either s was declared mutable and the delegate can modify it, but you wouldn't be able to pass it to func(), or s was declared immutable and you can pass it to func(), but the delegate creation would fail because it cannot modify immutable. In a nutshell, `const` means "I cannot modify the data", whereas `immutable` means "nobody can modify the data". Apparently small difference, but actually very important. T This is a case of "I am modifying the data anyway, even though am `const`." Delegate contexts are not exempt from type checking. A `const` existential type is still `const`. What the code is doing is basically the same as this: ```d import std; struct Updater{ string *context; void opCall(string s){ *context=s; } } struct S{ string s; Updater update; } void func(const S* s){ writeln(*s); s.update("func"); writeln(*s); } void main(){ auto s = S("test"); s.update = Updater(); writeln(s); func(); writeln(s); } ``` It's a `const` hole, plain and simple.
Re: Lambdas Scope
On 11.04.22 11:11, Salih Dincer wrote: How is this possible? Why is it compiled? Don't the same names in the same scope conflict? ```d int function(int) square; void main() { square = (int a) => a * a; int square = 5.square; assert(square == 25); } ``` Thanks, SDB@79 - Local variables in a function can hide variables in less nested scopes. (Such hiding is only an error for nested block scopes within the same function.) - UFCS always looks up names in module scope, it does not even check locals.
Re: Any workaround for "closures are not yet supported in CTFE"?
On 12/8/21 9:07 AM, Petar Kirov [ZombineDev] wrote: On Wednesday, 8 December 2021 at 07:55:55 UTC, Timon Gehr wrote: On 08.12.21 03:05, Andrey Zherikov wrote: On Tuesday, 7 December 2021 at 18:50:04 UTC, Ali Çehreli wrote: I don't know whether the workaround works with your program but that delegate is the equivalent of the following struct (the struct should be faster because there is no dynamic context allocation). Note the type of 'dg' is changed accordingly: The problem with struct-based solution is that I will likely be stuck with only one implementation of delegate (i.e. opCall implementation). Or I'll have to implement dispatching inside opCall based on some "enum" by myself which seems weird to me. Do I miss anything? This seems to work, maybe it is closer to what you are looking for. ... Incidentally, yesterday I played with a very similar solution. Here's my version: https://run.dlang.io/gist/PetarKirov/f347e59552dd87c4c02d0ce87d0e9cdc?compiler=dmd ```d interface ICallable { void opCall() const; } auto makeDelegate(alias fun, Args...)(auto ref Args args) { return new class(args) ICallable { Args m_args; this(Args p_args) { m_args = p_args; } void opCall() const { fun(m_args); } }; } alias Action = void delegate(); Action createDelegate(string s) { import std.stdio; return !((string str) => writeln(str))(s).opCall; } struct A { Action[] dg; } A create() { A a; a.dg ~= createDelegate("hello"); a.dg ~= createDelegate("buy"); return a; } void main() { enum a = create(); foreach(dg; a.dg) dg(); } ``` Nice, so the error message is lying. This is a bit more complete: ```d import std.stdio, std.traits, core.lifetime; auto partiallyApply(alias fun,C...)(C context){ return class(move(context)){ C context; this(C context) { foreach(i,ref c;this.context) c=move(context[i]); } auto opCall(ParameterTypeTuple!fun[context.length..$] args) { return fun(context,forward!args); } }.opCall; } alias Action = void delegate(); Action createDelegate(string s){ import std.stdio; return partiallyApply!((string str) => writeln(str))(s); } struct A{ Action[] dg; } A create(){ A a; a.dg ~= createDelegate("hello"); a.dg ~= createDelegate("buy"); return a; } void main(){ enum a = create(); foreach(dg; a.dg) dg(); } ```
Re: Any workaround for "closures are not yet supported in CTFE"?
On 08.12.21 03:05, Andrey Zherikov wrote: On Tuesday, 7 December 2021 at 18:50:04 UTC, Ali Çehreli wrote: I don't know whether the workaround works with your program but that delegate is the equivalent of the following struct (the struct should be faster because there is no dynamic context allocation). Note the type of 'dg' is changed accordingly: The problem with struct-based solution is that I will likely be stuck with only one implementation of delegate (i.e. opCall implementation). Or I'll have to implement dispatching inside opCall based on some "enum" by myself which seems weird to me. Do I miss anything? This seems to work, maybe it is closer to what you are looking for. ```d import std.stdio, std.traits, core.lifetime; struct CtDelegate(R,T...){ void* ctx; R function(T,void*) fp; R delegate(T) get(){ R delegate(T) dg; dg.ptr=ctx; dg.funcptr=cast(typeof(dg.funcptr))fp; return dg; } alias get this; this(void* ctx,R function(T,void*) fp){ this.ctx=ctx; this.fp=fp; } R opCall(T args){ return fp(args,ctx); } } auto makeCtDelegate(alias f,C)(C ctx){ static struct Ctx{ C ctx; } return CtDelegate!(ReturnType!(typeof(f)),ParameterTypeTuple!f[0..$-1])(new Ctx(forward!ctx), (ParameterTypeTuple!f[0..$-1] args,void* ctx){ auto r=cast(Ctx*)ctx; return f(r.ctx,forward!args); }); } struct A{ CtDelegate!void[] dg; } auto createDelegate(string s){ return makeCtDelegate!((string s){ s.writeln; })(s); } A create(){ A a; a.dg ~= createDelegate("hello"); a.dg ~= createDelegate("buy"); return a; } void main(){ static a = create(); foreach(dg; a.dg) dg(); } ```
Re: static foreach over constant range in @nogc block
On 03.10.20 13:18, tspike wrote: I came across an issue recently that I’m a little confused by. The following program fails to compile under LDC and DMD, though it compiles fine under GDC: @nogc: void main() { static foreach(i; 0 .. 4) { pragma(msg, i); } } Both DMD and LDC report the following error if I try to compile it: test.d(7): Error: cannot use operator ~= in @nogc delegate test.main.__lambda1 I was just wondering, is this is a compiler bug or is there a reason I'm overlooking preventing this sort of code from compiling? It's a compiler bug, the same as this one: @nogc: void main(){ static immutable x = { int[] a; a~=1; return a; }(); }
Re: @property with opCall
On 09.03.20 13:14, Adam D. Ruppe wrote: Here's a wiki page referencing one of the 2013 discussions https://wiki.dlang.org/Property_Discussion_Wrap-up https://wiki.dlang.org/DIP24
Re: static foreach / How to construct concatenated string?
On 07.03.20 17:41, MoonlightSentinel wrote: On Saturday, 7 March 2020 at 16:30:59 UTC, Robert M. Münch wrote: Is this possible at all? You can use an anonymous lambda to build the string in CTFE: It turns out that if you do use this standard idiom, you might end up getting blamed for an unrelated DMD bug though: https://github.com/dlang/dmd/pull/9922 :o)
Re: Improving dot product for standard multidimensional D arrays
On 01.03.20 21:58, p.shkadzko wrote: ** Matrix!T matrixDotProduct(T)(Matrix!T m1, Matrix!T m2) in { assert(m1.rows == m2.cols); This asserts that the result is a square matrix. I think you want `m1.cols==m2.rows` instead. } do { Matrix!T m3 = Matrix!T(m1.rows, m2.cols); for (int i; i < m1.rows; ++i) { for (int j; j < m2.cols; ++j) { for (int k; k < m2.rows; ++k) { m3.data[toIdx(m3, i, j)] += m1[i, k] * m2[k, j]; } } } return m3; } ** ... I can see that accessing the appropriate array member in Matrix.data is costly due to toIdx operation but, I can hardly explain why it gets so much costly. Maybe there is a better way to do it after all? Changing the order of the second and third loop probably goes a pretty long way in terms of cache efficiency: Matrix!T matrixDotProduct(T)(Matrix!T m1,Matrix!T m2)in{ assert(m1.cols==m2.rows); }do{ int m=m1.rows,n=m1.cols,p=m2.cols; Matrix!T m3=Matrix!T(m,p); foreach(i;0..m) foreach(j;0..n) foreach(k;0..p) m3.data[i*p+k]+=m1.data[i*n+j]*m2.data[j*p+k]; return m3; } (untested.)
Re: How to invert bool false/true in alias compose?
On 07.12.19 05:00, Marcone wrote: import std; alias cmd = compose!(to!bool, wait, spawnShell, to!string); void main(){ writeln(cmd("where notepad.exe")); } Result: C:\Windows\System32\notepad.exe C:\Windows\notepad.exe false The result show "false" because good spawnshell command return 0 and 0 to bool is false. But I want to invert false to true to get true or false if command success. alias cmd = compose!(not!(to!bool), wait, spawnShell, to!string);
Re: Simple casting?
On 27.11.19 11:43, ixid wrote: On Tuesday, 26 November 2019 at 16:33:06 UTC, Timon Gehr wrote: import std; void main(){ int[] x=[1,1,2,3,4,4]; int[][] y=x.chunkBy!((a,b)=>a==b).map!array.array; writeln(y); } This stuff is a nightmare for less experienced users like myself, I wish there were a single function that would make any data obkect eager, no matter how convoluted its arrays of arrays of arrays. import std; auto eager(T)(T r){ static if(isInputRange!T) return r.map!eager.array; else return r; } void main(){ int[] x=[1,1,2,3,4,4]; int[][] y=x.chunkBy!((a,b)=>a==b).eager; writeln(y); }
Re: Simple casting?
On 26.11.19 23:08, Taylor R Hillegeist wrote: On Tuesday, 26 November 2019 at 16:33:06 UTC, Timon Gehr wrote: int[][] y=x.chunkBy!((a,b)=>a==b).map!array.array; how did you know to do that? chunkBy with a binary predicate returns a range of ranges. So if I want an array of arrays I have to convert both the inner ranges and the outer range.
Re: Simple casting?
On 26.11.19 06:05, Taylor R Hillegeist wrote: I'm attempting to do a segment group. details: alias ProbePoint[3]=triple; triple[] irqSortedSet = UniqueTriples.keys .sort!("a[1].irqid < b[1].irqid",SwapStrategy.stable) .array; 83:triple[][] irqSortedSets = irqSortedSet.chunkBy!((a,b) => a[1].irqid == b[1].irqid); GetAllTriplesExtractFileIrqSplit.d(83): Error: cannot implicitly convert expression `chunkBy(irqSortedSet)` of type `ChunkByImpl!(__lambda4, ProbePoint[3][])` to `ProbePoint[3][][]` I have something that looks like a triple[][] but I can't seem to get that type out. when I add .array it converts to a Group which doesn't make sense to me because I'm not using a unary comparison. Any thought? import std; void main(){ int[] x=[1,1,2,3,4,4]; int[][] y=x.chunkBy!((a,b)=>a==b).map!array.array; writeln(y); }
Re: why local variables cannot be ref?
On 25.11.19 10:00, Dukc wrote: On Monday, 25 November 2019 at 03:07:08 UTC, Fanda Vacek wrote: Is this preferred design pattern? ``` int main() { int a = 1; //ref int b = a; // Error: variable `tst_ref.main.b` only parameters or `foreach` declarations can be `ref` ref int b() { return a; } b = 2; assert(a == 2); return 0; } ``` Fanda It's okay, but I'd prefer an alias, because your snippet uses the heap needlessly (it puts variable a into heap to make sure there will be no stack corruption if you pass a pointer to function b() outside the main() function) This is not true. You can annotate main with @nogc.
Re: Abstract classes vs interfaces, casting from void*
On 10.08.19 16:29, John Colvin wrote: Ok. What would go wrong (in D) if I just replaced every interface with an abstract class? interface A{} interface B{} class C: A,B{ }
Re: accuracy of floating point calculations: d vs cpp
On 22.07.19 14:49, drug wrote: I have almost identical (I believe it at least) implementation (D and C++) of the same algorithm that uses Kalman filtering. These implementations though show different results (least significant digits). Before I start investigating I would like to ask if this issue (different results of floating points calculation for D and C++) is well known? May be I can read something about that in web? Does D implementation of floating point types is different than the one of C++? Most of all I'm interesting in equal results to ease comparing outputs of both implementations between each other. The accuracy itself is enough in my case, but this difference is annoying in some cases. This is probably not your problem, but it may be good to know anyway: D allows compilers to perform arbitrary "enhancement" of floating-point precision for parts of the computation, including those performed at compile time. I think this is stupid, but I haven't been able to convince Walter.
Re: Strange closure behaviour
On 15.06.19 18:29, Rémy Mouëza wrote: On Saturday, 15 June 2019 at 01:21:46 UTC, Emmanuelle wrote: On Saturday, 15 June 2019 at 00:30:43 UTC, Adam D. Ruppe wrote: On Saturday, 15 June 2019 at 00:24:52 UTC, Emmanuelle wrote: Is it a compiler bug? Yup, a very longstanding bug. You can work around it by wrapping it all in another layer of function which you immediately call (which is fairly common in javascript): funcs ~= ((x) => (int i) { nums[x] ~= i; })(x); Or maybe less confusingly written long form: funcs ~= (delegate(x) { return (int i) { nums[x] ~= i; }; })(x); You write a function that returns your actual function, and immediately calls it with the loop variable, which will explicitly make a copy of it. Oh, I see. Unfortunate that it's a longstanding compiler bug, but at least the rather awkward workaround will do. Thank you! I don't know if we can tell this is a compiler bug. It's a bug. It's memory corruption. Different objects with overlapping lifetimes use the same memory location. The same behavior happens in Python. No, it's not the same. Python has no sensible notion of variable scope. >>> for i in range(3): pass ... >>> print(i) 2 Yuck. The logic being variable `x` is captured by the closure. That closure's context will contain a pointer/reference to x. Whenever x is updated outside of the closure, the context still points to the modified x. Hence the seemingly strange behavior. ... It's not the same instance of the variable. Foreach loop variables are local to the loop body. They may both be called `x`, but they are not the same. It's most obvious with `immutable` variables. Adam's workaround ensures that the closure captures a temporary `x` variable on the stack: a copy will be made instead of taking a reference, since a pointer to `x` would be dangling once the `delegate(x){...}` returns. Most of the time, we want a pointer/reference to the enclosed variables in our closures. Note that C++ 17 allows one to select the capture mode: the following link lists 8 of them: https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture. ... No, this is not an issue of by value vs by reference. All captures in D are by reference, yet the behavior is wrong. D offers a convenient default that works most of the time. The trade-off is having to deal with the creation of several closures referencing a variable being modified in a single scope, like the incremented `x` of the for loop. ... By reference capturing may be a convenient default, but even capturing by reference the behavior is wrong.
Re: Performance of tables slower than built in?
On 23.05.19 12:21, Alex wrote: On Wednesday, 22 May 2019 at 00:55:37 UTC, Adam D. Ruppe wrote: On Wednesday, 22 May 2019 at 00:22:09 UTC, JS wrote: I am trying to create some fast sin, sinc, and exponential routines to speed up some code by using tables... but it seems it's slower than the function itself?!? There's intrinsic cpu instructions for some of those that can do the math faster than waiting on memory access. It is quite likely calculating it is actually faster. Even carefully written and optimized tables tend to just have a very small win relative to the cpu nowadays. Surely not? I'm not sure what method is used to calculate them and maybe a table method is used internally for the common functions(maybe the periodic ones) but memory access surely is faster than multiplying doubles? ... Depends on what kind of memory access, and what kind of faster. If you hit L1 cache then a memory access might be (barely) faster than a single double multiplication. (But modern hardware usually can do multiple double multiplies in parallel, and presumably also multiple memory reads, using SIMD and/or instruction-level parallelism.) I think a single in-register double multiplication will be roughly 25 times faster than an access to main memory. Each access to main memory will pull an entire cache line from main memory to the cache, so if you have good locality (you usually won't with a LUT), your memory accesses will be faster on average. There are a lot of other microarchitectural details that can matter quite a lot for performance. And most of the time these functions are computed by some series that requires many terms. I'd expect, say, to compute sin one would require at least 10 multiplies for any accuracy... and surely that is much slower than simply accessing a table(it's true that my code is more complex due to the modulos and maybe that is eating up the diff). Do you have any proof of your claims? Like a paper that discusses such things so I can see what's really going on and how they achieve such performance(and how accurate)? Not exactly what you asked, but this might help: https://www.agner.org/optimize Also, look up the CORDIC algorithm.
Re: CTFE sort of tuples
On 02.05.19 09:28, Stefan Koch wrote: On Thursday, 2 May 2019 at 02:54:03 UTC, Andrey wrote: Hello, I have got this code: [...] I want to sort array of tuples using "data" element in CTFE. But this code give me errors: [...] As I understand the function "sort" sometimes can't be run at CT because of reinterpreting cast. In this case how to sort? write a sort? a bubble-sort should be sufficient for if the arrays are as short as in the example. Well, clearly, we should be able to /swap values/ at compile time.
Re: Why does nobody seem to think that `null` is a serious problem in D?
On 22.11.18 16:19, Steven Schveighoffer wrote: In terms of language semantics, I don't know what the right answer is. If we want to say that if an optimizer changes program behavior, the code must be UB, then this would have to be UB. But I would prefer saying something like -- if a segfault occurs and the program continues, the system is in UB-land, but otherwise, it's fine. If this means an optimized program runs and a non-optimized one crashes, then that's what it means. I'd be OK with that result. It's like Schrodinger's segfault! I don't know what it means in terms of compiler assumptions, so that's where my ignorance will likely get me in trouble :) This is called nondeterministic semantics, and it is a good idea if you want both efficiency and memory safety guarantees, but I don't know how well our backends would support it. (However, I think it is necessary anyway, e.g. to give semantics to pure functions.)
Re: foreach on a tuple using aliases
On 06.08.2018 14:37, Steven Schveighoffer wrote: On 8/5/18 11:40 AM, Timon Gehr wrote: On 05.08.2018 16:07, Steven Schveighoffer wrote: So is this a bug? Is it expected? It's a bug. The two copies of 'item' are not supposed to be the same symbol. (Different types -> different symbols.) Yep. I even found it has nothing to do with foreach on a tuple: https://run.dlang.io/is/vxQlIi I wonder though, it shouldn't really be a different type that triggers it, right? It shouldn't.
Re: foreach on a tuple using aliases
On 05.08.2018 16:07, Steven Schveighoffer wrote: I have found something that looks like a bug to me, but also looks like it could simply be a limitation of the foreach construct. Consider this code: struct Foo {} enum isFoo(alias x) = is(typeof(x) == Foo); void main() { Foo foo; assert(isFoo!foo); static struct X { int i; Foo foo; } X x; foreach(i, ref item; x.tupleof) static if(is(typeof(item) == Foo)) // line A static assert(isFoo!item); // line B else static assert(!isFoo!item); } Consider just the two lines A and B. If you saw those lines anywhere, given the isFoo definition, you would expect the assert to pass. But in this case, it fails. What is happening is that the first time through the loop, we are considering x.i. This is an int, and not a Foo, so it assigns false to the template isFoo!item. The second time through the loop on x.foo, the compiler decides that it ALREADY FIGURED OUT isFoo!item, and so it just substitutes false, even though the item in question is a different item. So is this a bug? Is it expected? It's a bug. The two copies of 'item' are not supposed to be the same symbol. (Different types -> different symbols.) Is it too difficult to fix? ... Unlikely. The workaround of course is to use x.tupleof[i] when instantiating isFoo. But it's a bit ugly. I can also see other issues cropping up if you use `item` for other meta things. -Steve
Re: dynamically allocating on the stack
On 21.04.2018 12:08, Giles Bathgate wrote: On Saturday, 21 April 2018 at 07:57:41 UTC, Uknown wrote: The language itself doesn't have something, but you could use `alloca` I don't know if this little template function makes life easier: -- pragma(inline, true) ref T push(T)(size_t len) { import core.stdc.stdlib, core.stdc.stdio; return *cast(T*)alloca(T.sizeof * len); } void doSomething(size_t len) { auto stackBuffer = push!char(len+1); stackBuffer[0] = 'H'; stackBuffer[1] = '\0'; printf("%.*s", stackBuffer.ptr); } void main() { doSomething(2); } -- That does not work (you are returning a dangling reference into the stack of the function that is returning). You could do this: import core.stdc.stdlib, core.stdc.stdio; auto push(T,alias len)(T[] mem=(cast(T*)alloca(T.sizeof*len))[0..len]){ return mem; // (uninitialized!) } void doSomething(size_t len){ char[] stackBuffer=push!(char,len); stackBuffer[0] = 'H'; stackBuffer[1] = '\0'; printf("%s", stackBuffer.ptr); } void main(){ doSomething(2); }
Re: Negative index range violation
On 22.02.2018 01:26, Adam D. Ruppe wrote: On Thursday, 22 February 2018 at 00:13:43 UTC, SrMordred wrote: string x = "123"; auto c = x.ptr; c++; writeln(c[-1]); // 1 That's only happening because pointers bypass range checks. writeln(c[-1..0]); //BOOM Range violation But with a slice negative indexes are never allowed, even on a pointer. Actually, it's slightly more complicated than that. E.g. c[-2..-1] does not trigger the range check and will behave as expected. For slices c[l..r] there is a check whether cast(size_t)l<=cast(size_t)r. The range violation happens because -1 is larger than 0 as an unsigned integer.
Re: Templated Binary Search Tree treats class as const, compiler complains
On 21.01.2018 21:20, Mark wrote: Just realized that I commented out the creation of the BST new link: https://dpaste.dzfl.pl/ce620cbee919 'in' means 'const scope', but it seems you need references that are allowed to mutate the incoming items. Remove the 'in' attribute from the parameters and your problem should disappear.
Re: How to imporve D-translation of these Python list comprehensions ?
On 15.01.2018 20:05, xenon325 wrote: I think, most clear code would be with tripple `foreach`, so I'll go with that. But probably someone will come up with something better and range-ier. Suggestion are welcome! import std.stdio, std.algorithm, std.range, std.array, std.conv, std.json, std.typecons; auto aa(R)(R r){ typeof(r.front[1])[typeof(r.front[0])] a; foreach(x;r) a[x[0]] = x[1]; return a; } alias emap(alias a) = map!(x => a(x.expand)); void main(){ auto srv1 = [ "acs": ["ver": "1.2.3", "rev": "6f2260d"], "cms": ["ver": "4.5", "rev": "b17a67e"], "ots": ["ver": "6.7.80", "rev": "4f487d2"]]; auto srv2 = [ "acs": ["ver": "1.2.3", "rev": "6f2260d"], "cms": ["ver": "5.1", "rev": "2a56c53"], "vaa": ["ver":"0.7", "rev": "00852cb"]]; chain(srv1.keys, srv2.keys).sort.uniq .map!(k => chain(only(tuple("_name", k)), cartesianProduct(only("ver", "rev"), only(srv1, srv2).enumerate) .emap!((prop, srv) => tuple(text(prop, srv.index), srv.value.get(k, null).get(prop, ""))) ).aa).array.JSONValue.toPrettyString.writeln; }
Re: How to imporve D-translation of these Python list comprehensions ?
On 15.01.2018 22:51, Timon Gehr wrote: auto aa(R)(R r){ typeof(r.front[1])[typeof(r.front[0])] a; foreach(x;r) a[x[0]] = x[1]; return a; } Actually, better to use std.array.assocArray. import std.stdio, std.algorithm, std.range, std.array, std.conv, std.json, std.typecons; alias emap(alias a) = map!(x => a(x.expand)); void main(){ auto srv1 = [ "acs": ["ver": "1.2.3", "rev": "6f2260d"], "cms": ["ver": "4.5", "rev": "b17a67e"], "ots": ["ver": "6.7.80", "rev": "4f487d2"]]; auto srv2 = [ "acs": ["ver": "1.2.3", "rev": "6f2260d"], "cms": ["ver": "5.1", "rev": "2a56c53"], "vaa": ["ver": "0.7", "rev": "00852cb"]]; chain(srv1.keys, srv2.keys).sort.uniq .map!(k => chain(only(tuple("_name", k)), cartesianProduct(only("ver", "rev"), only(srv1, srv2).enumerate) .emap!((prop, srv) => tuple(text(prop, srv.index), srv.value.get(k, null).get(prop, ""))) ).assocArray).array.JSONValue.toPrettyString.writeln; }
Re: Is old style compile-time foreach redundant?
On 09.01.2018 22:04, H. S. Teoh wrote: if (0 == 3) {} // all subsequent iterations deleted because the static break is unconditionally compiled (it has nothing to do with the runtime branch). You'd have to use static if to make it conditionally-compiled and thus not instantly aborting the loop. Such semantics would be logically consistent, but unfortunately rather counterintuitive at first glance. I think "if (0 == 3) { static break; }" should be a compile-time error.
Re: Why 2 ^^ 1 ^^ 2 = 2?
On 22.10.2017 16:20, Ilya Yaroshenko wrote: .. i thought it should be (2 ^^ 1) ^^ 2 = 4 2 ^^ (1 ^^ 2) == 2 It is standard for ^/**/^^ to be right-associative. (This is also the standard convention in mathematics.)
Re: Assert and undefined behavior
On 14.10.2017 23:36, kdevel wrote: On Saturday, 14 October 2017 at 09:32:32 UTC, Timon Gehr wrote: Also, UB can and does sometimes mean that the program can execute arbitrary code. It's called "arbitrary code execution": https://en.wikipedia.org/wiki/Arbitrary_code_execution This confuses different levels of reasoning. It's a correct statement about the semantics of programs produced from sources with UB by standard-compliant compilers. In C/C++ "undefined behavior" is a property of the SOURCE code with respect to the specification. It states: The spec does not not apply, it does not define the semantic. ... I.e., the semantics of a program produced by a conforming compiler can be arbitrary. This issue is totally different from the question what a given program containing undefined behavior actually does after is compiles and the after the linker produces an executable. This is reasoning about generated MACHINE code. ... Sure. This is very much intentional. The current subthread is about what kind of programs the compiler might produce (in practice) if the provided source code contains UB. The claim I was refuting was that the produced program cannot have branching and other behaviors not specified in the source. A result of this confusion has been that some clever people tried to "detect" certain kinds of undefined behavior "after" they "happended". E.g. <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475> This is the danger of undefined behavior: The MACHINE code may also work as the programmer expected. At least for some time. I'm not confused about this at all.
Re: Assert and undefined behavior
On 14.10.2017 07:20, Jesse Phillips wrote: On Thursday, 12 October 2017 at 15:37:23 UTC, John Burton wrote: This is an example of what I mean :- undefined what it is meant to do anyway, so the compiler can "optimize" out the if condition as it only affects the case where the language doesn't define what it's supposed to do anyway, and compiles the code as if it was :- void test(int[] data) { control_nuclear_reactor(); } Yeah the C/C++ community/haters love to talk about all the code the compiler can inject because of undefined behavior. But that is not what it means. ... It can mean that, but that is not even what happened in the given example. The compiler does not know the value of data.length so it could not make such a transformation of the code. The compiler can easily prove that the value of data.length does not change between the two points in the program. According to the specification, the behavior of the program is undefined in case the assertion fails, not just the behavior of the program after the assertion would have failed if it had not been removed. Now had the assert been written before the if, you're telling the compiler some properties of data.length before you check it and it could make such optimizations. The point is assert tells the compiler something it can use to reason about its job, not that it can insert additional runtime checks to see if you code is invalid an then add new jumps to execute whatever the hell it wants. In the above example, a branch was removed, not added. However, optimizers can add branches. (For example, it can check whether there is aliasing and use optimized code if it is not the case.) Also, UB can and does sometimes mean that the program can execute arbitrary code. It's called "arbitrary code execution": https://en.wikipedia.org/wiki/Arbitrary_code_execution
Re: Assert and undefined behavior
On 11.10.2017 11:27, John Burton wrote: The spec says this :- "As a contract, an assert represents a guarantee that the code must uphold. Any failure of this expression represents a logic error in the code that must be fixed in the source code. A program for which the assert contract is false is, by definition, invalid, and therefore has undefined behaviour." Now I worry about the words "undefined behavior" because in C++ compiler writers seem to have decided that these words mean that it's ok for the compiler to generate code to do whatever it feels like even in unconnected code and even before the undefined behavior is invoked because some subsequent code has undefined behavior. From my C++ experience this paragraph tells me that if I use "assert" to check my assumptions, and the assertion is false, then this could lead to my program failing in unpredictable ways unconnected with the actual assertion. Yes, that's what it is saying. (The other answers, that say or try to imply that this is not true or true but not a bad thing, are wrong.) To make this more obvious, see: http://forum.dlang.org/post/lrbpvj$mih$1...@digitalmars.com Refer to point 2. The fix is to not use both assert and -release. However, in practice, I think none of the current compiler implementations actually uses assert expressions for optimizations.
Re: [OT] Converting booleans to numbers
On 21.09.2017 17:53, Steven Schveighoffer wrote: On 9/21/17 11:48 AM, Steven Schveighoffer wrote: On 9/21/17 11:06 AM, Timon Gehr wrote: foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } So am I, but I wasn't commenting on trade-offs, only the view that there are no good uses. This seems way easier for me to grok, and is how I would write it. dfs(a + 1, 0); dfs(a - 1, 0); dfs(0, b + 1); dfs(0, b - 1); Of course, without bugs :) ... It was the same bug in every copy. Impressive! ;) dfs(a + 1, b); dfs(a - 1, b); dfs(a, b + 1); dfs(a, b - 1); -Steve This is a good alternative, maybe arrange it like this: dfs(a + 1, b); dfs(a, b + 1); dfs(a - 1, b); dfs(a, b - 1); Just need to make sure no code is duplicated. (For example, there could be more work to do in each loop iteration, and then you'd need to use a local function.)
Re: [OT] Converting booleans to numbers
On 20.09.2017 23:13, nkm1 wrote: Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { if (a<0 || a >= data.length) return; if (b<0 || b >= data[a].length) return; if (data[a][b] == c) return; data[a][b] = c; foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } } dfs(i, j); } I don't agree it's a good use. Well, you can trust me that it is. ;) Actually, that seems quite obfuscated to me. It's actually straightforward. This C code is obfuscated: #define C , #define S(X) "Fizz"X"Buzz" int main(){ char j[]="00",*k=j+1,*g[]={k,S(C),S()}; while(':'-*j) ++*k>'9'&&++*j&&(1<:*g=j:>='0'), puts(g[!((*j+*k)%3)|2*(3==*k%5)]); return 0; } (And yet, you are probably able to guess what it does.) Consider: (I had considered that.) foreach (point; [[1, 0], [-1, 0], [0, 1], [0, -1]]) { dfs(a + point[0], b + point[1]); } void floodFill(dchar[][] data,dchar c,int i,int j) @nogc { I.e., I'd possibly call this a bad use of array literals. ;) (The fix is to initialize a static array of static arrays.) Also, it's not really a point, rather, it's a delta. Finds some random 10 programmers and ask them what's easier to understand... Personally, I think it is a tie as both are obvious. Also, in my experience (in C and C++) it is extremely rare for programmers to use booleans in arithmetic. So even if in some situation you would have to replace this thing with more verbose (i == 0 ? 1 : 0), it's no big deal. I didn't say it was. OTOH, booleans being numbers is a source of some bugs (just like other cases of weak typing). Not a ton of bugs, but the utility of implicit conversion to numbers is so unnoticeable that I'm sure it's just not worth it. So am I, but I wasn't commenting on trade-offs, only the view that there are no good uses.
[OT] Converting booleans to numbers
On 19.09.2017 23:17, nkm1 wrote: ... OTOH, booleans converting to numbers is a very questionable feature. > I certainly have never seen any good use for it. ... Actually, it is useful enough to have a Wikipedia page: https://en.wikipedia.org/wiki/Iverson_bracket Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { if (a<0 || a >= data.length) return; if (b<0 || b >= data[a].length) return; if (data[a][b] == c) return; data[a][b] = c; foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } } dfs(i, j); } unittest { import std.algorithm, std.conv, std.array; auto data = ["###....##"d, "##...#..."d, "..###.###"d, "##...###...##"d, "...#."d, "#.#.#.#.#.#.#"d, "#.###"d] .map!(to!(dchar[])).array; floodFill(data, '#', 1, 1); assert(data==["#"d, "#"d, "#.###"d, "...##"d, "."d, "#.#.###.#.#.#"d, "#"d]); }
Re: delegates/lambas do not pick up calling convention
On 10.08.2017 15:22, Adam D. Ruppe wrote: On Wednesday, 9 August 2017 at 23:52:00 UTC, Johnson Jones wrote: extern(C) delegate(void*) {} You should very rarely use extern(C) delegate... delegate is a D type, so the C function is almost certainly not actually receiving it. Only time you'd want an extern(C) using D types like delegates, arrays, strings, etc., is if the receiver is actually also written in D. idk if this would fix your problem, but it should be changed regardless. gdk is actually using a function with arguments of type (extern(C) int function(void*),void*). Anyway, I think there are use cases for extern(C) delegates too, along the following lines: alias D=extern(C) int delegate(int); struct F(S,T...){ // this struct is compatible with C void* ptr; extern(C) S function(void*,T) funptr; auto opCall(T args){ return funptr(ptr,args); } } void main(){ int y=2; D dg=(x)=>x+y; auto f=*cast(F!(int,int)*) import std.stdio; writeln(f(3)); }
Re: delegates/lambas do not pick up calling convention
On 10.08.2017 01:52, Johnson Jones wrote: given somethign like Threads.threadsAddIdle which takes an extern(C) int (void*) we can't seem to do threadsAddIdle((void*) { }, null); I think this is a compiler bug. Try: threadsAddIdle((x){ }, null); It seems that the calling convention is deduced only if the parameter type needs to be deduced too. https://issues.dlang.org/show_bug.cgi?id=17739
Re: Cannot use std.array.Appender in recursive types
On 09.08.2017 21:00, Steven Schveighoffer wrote: On 8/9/17 2:25 PM, Nordlöw wrote: Why doesn't appending to `subs` work with std.array.Appender in struct T { string src; import std.array : Appender; Appender!(T[]) subs; } T t; t.subs ~= T.init; // ERRORS t.subs.put(T.init); // ERRORS when it works with builtin arrays as in struct S { string src; S[] subs; } S s; s.subs ~= S.init; ? Specifically t.subs ~= T.init errors as Error: cannot append type T to type Appender!(T[]) Here is the problem: ElementType!(T[]) is void. Here is ElementType: template ElementType(R) { static if (is(typeof(R.init.front.init) T)) alias ElementType = T; else alias ElementType = void; } So what is happening here (I think), is that T isn't fully defined, so T.init.front.init is an error at this point. Therefore the else clause is selected. This is one of the problems with using is(typeof) (or __traits(compiles)) with an "else" clause. You may not be checking what you think you are checking, and end up with the wrong result. So essentially, Appender!(T[]) inside a T becomes (essentially) Appender!(void[]). And you can't append a T to a void[]. If I change the definition of ElementType to use R.init.front instead of R.init.front.init, it compiles. But I'm pretty sure this will break other ranges. Somewhere, there's an answer. -Steve It's a forward reference bug. Self-contained test case: auto front(T)(T[] a){ return a[0]; } template ElementType(R){ pragma(msg, typeof(R.init.front)); /* Error: struct bug.T no size because of forward reference */ static if (is(typeof(R.init.front) T)) alias ElementType = T; else alias ElementType = void; } struct Appender(A){ A a; alias T=ElementType!A; private enum canPutItem(U)=is(U==T); void put(T)(T t)if(canPutItem!T){ a~=t; } } struct T{ string src; Appender!(T[]) subs; } void main(){ T t; t.subs.put(T.init); }
Re: It makes me sick!
On 29.07.2017 23:52, FoxyBrown wrote: On Saturday, 29 July 2017 at 21:48:09 UTC, Timon Gehr wrote: On 28.07.2017 23:30, FoxyBrown wrote: because you didn't want to spend 10 minutes to fix a program. You need to realize that the same thing applies to you. There is no "us" vs "you". I.e. if you know it to only be 10 minutes of work, why don't you just fix it yourself? Mike currently has as many commits in DMD as you do, and he is already busy contributing in other ways. EXACTLY! Your problem is that you are taking the you vs me too literal. I am talking about a mentality people have that think that them saving 10 minutes by not implementing something that will save 10 hours(low estimate) for everyone else is a good thing and criticize people when they say there is a better and try to condemn them and continue the status quo that wastes more time. Personally, I expect a minimal amount of consistency. I.e. when someone criticizes something, I only take them seriously when they don't go on to indulge in the very behavior they criticize. Also, Mike was not showing this mindset. Mike was saying it is not reasonable to expect being able to manually and somewhat carelessly juggle around the files of the installation on the file system and only get expected behaviour. Everything else is your own interpretation. Note that there are a lot of things that anyone could work on that saves them or someone else a lot of time, and not everyone agrees on priorities. I think it is safe to assume that it was not laziness that led to the current behaviour, but that it was just an oversight.
Re: It makes me sick!
On 28.07.2017 23:30, FoxyBrown wrote: because you didn't want to spend 10 minutes to fix a program. You need to realize that the same thing applies to you. There is no "us" vs "you". I.e. if you know it to only be 10 minutes of work, why don't you just fix it yourself? Mike currently has as many commits in DMD as you do, and he is already busy contributing in other ways. The compiler is here: https://github.com/dlang/dmd Just implement the check, and commit it with commit message "fix Issue 17699 - Importing a module that has both modulename.d and modulename/package.d should be an error", then create a pull request. It is very easy to figure out where to add the check: $ git clone g...@github.com:dlang/dmd $ cd dmd/src/ddmd$ $ grep "package.d" * # the obvious string to search for access.d:printf("\ts is in same package.d module as sc\n"); astbase.d:PKGunknown, // not yet determined whether it's a package.d or not astbase.d:PKGmodule, // already determined that's an actual package.d grep: backend: Is a directory dimport.d:// mod is a package.d, or a normal module which conflicts with the package name. dmodule.d: * Therefore, the result should be: filename/package.d dmodule.d: * iff filename/package.d is a file dmodule.d:const(char)* ni = FileName.combine(filename, "package.di"); dmodule.d:const(char)* n = FileName.combine(filename, "package.d"); dmodule.d:const(char)* n2i = FileName.combine(n, "package.di"); dmodule.d:const(char)* n2 = FileName.combine(n, "package.d"); dmodule.d:PKGunknown, // not yet determined whether it's a package.d or not dmodule.d:PKGmodule, // already determined that's an actual package.d dmodule.d:bool isPackageFile; // if it is a package.d dmodule.d:// if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module dmodule.d:bool isPackageMod = (strcmp(toChars(), "package") != 0) && (strcmp(srcfile.name.name(), "package.d") == 0 || (strcmp(srcfile.name.name(), "package.di") == 0)); dmodule.d:.error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'", toChars(), srcfile.toChars()); dmodule.d:isPackageFile = (strcmp(srcfile.name.name(), "package.d") == 0 || dmodule.d: strcmp(srcfile.name.name(), "package.di") == 0); dmodule.d:if (m && (strcmp(m.srcfile.name.name(), "package.d") != 0 && dmodule.d: strcmp(m.srcfile.name.name(), "package.di") != 0)) dmodule.d: * +- package.d dmodule.d: * If both are used in one compilation, 'pkg' as a module (== pkg/package.d) dmodule.d: *later package.d loading will change Package::isPkgMod to PKGmodule and set Package::mod. dmodule.d: * 2. Otherwise, 'package.d' wrapped by 'Package' is inserted to the internal tree in here. dmodule.d:/* If the previous inserted Package is not yet determined as package.d, module.h:PKGunknown, // not yet determined whether it's a package.d or not module.h:PKGmodule, // already determined that's an actual package.d module.h:bool isPackageFile; // if it is a package.d I.e., let's check out dmodule.d. We immediately find the following code: extern (C++) const(char)* lookForSourceFile(const(char)** path, const(char)* filename) { *path = null; /* Search along global.path for .di file, then .d file. */ const(char)* sdi = FileName.forceExt(filename, global.hdr_ext); if (FileName.exists(sdi) == 1) return sdi; const(char)* sd = FileName.forceExt(filename, global.mars_ext); if (FileName.exists(sd) == 1) return sd; if (FileName.exists(filename) == 2) { /* The filename exists and it's a directory. * Therefore, the result should be: filename/package.d * iff filename/package.d is a file */ const(char)* ni = FileName.combine(filename, "package.di"); if (FileName.exists(ni) == 1) return ni; FileName.free(ni); const(char)* n = FileName.combine(filename, "package.d"); if (FileName.exists(n) == 1) return n; FileName.free(n); } ... I'll let you (or anyone else who would like to) take it from here.
Re: Why D have two function contains and canFind?
On 24.07.2017 20:19, Suliman wrote: Why D have two function `contains` and `canFind` `contains` guarantees logarithmic running time, while `canFind` can be linear.
Re: Best syntax for a diagonal and vertical slice
On 22.07.2017 22:55, kerdemdemir wrote: We have awesome way for creating slices like: a = new int[5]; int[] b = a[0..2]; But what about if I have 2D array and I don't want to go vertical. Something like : int[3][3] matrix = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]; I believe I can use std.range function "RoundRobin"(or maybe it won't work with 2D array directly) for having a good looking vertical slice which will have 1,4,7 or 2,5,8 or 3,6,9 in my example above. And what if I want to go diagonal like 1,5,9 or 3,5,7 in the example above. Is there a good solution in std without using for loops? I have one more requirement for fulfilling the task that I working on. This slices do not have to be the same size as the array. For example in the example above slice size could have 2 instead of 3. In this case I need to have slices like 1,5;2,6;4,8;5,9 ... and so on for diagonal case. Erdem Ps: Converting the 2D array to 1D array is possible in my case. horizontal: matrix[i][j..j+k] vertical: matrix[i..i+k].map!(x=>x[j]) diagonal 1: iota(k).map!(x=>matrix[i+x][j+x]) diagonal 2: iota(k).map!(x=>matrix[i+x][j-x])
Re: Avoid if statements for checking neighboring indexes in a 2D array
On 16.07.2017 19:10, Timon Gehr wrote: ... (This works even if there are * at the border.) Well, not really. :) Version that actually works if there are * at the border: import std.stdio, std.range, std.algorithm, std.array; char[][] arr; int componentSize(int row,int col){ if(row>=arr.length||col>=arr[row].length||arr[row][col]!='*') return 0; arr[row][col]='x'; return 1+cartesianProduct(iota(row-1,row+2),iota(col-1,col+2)) .map!(a=>componentSize(a.expand)).sum; } void main (){ arr=["***", "*xx", "xx**xxx", "xxx*x**", "**x"].map!dup.array; cartesianProduct(iota(cast(int)arr.length),iota(cast(int)arr[0].length)) .filter!(a=>arr[a[0]][a[1]]=='*') .each!(a=>writeln(componentSize(a.expand))); }
Re: Avoid if statements for checking neighboring indexes in a 2D array
On 16.07.2017 18:55, Timon Gehr wrote: On 16.07.2017 12:37, kerdemdemir wrote: My goal is to find connected components in a 2D array for example finding connected '*' chars below. x x x x x x x x x x x x x x * * x x x x * * x x x x x * * x * x x x x x There are two connected '*' group in this example. First group is composes of six '*' located closer to middle and the second group composes only one '*' char located in the left bottom corner. Do to this I generally implement a recursive algorithm which repeat calling the same function by checking all neighbors around the current index. I generally end up with something like : void foo( int row, int col) { //Do something here like caching the index if ( twoDimensionData[row - 1][col] == '*') foo(row- 1, col); else if ( twoDimensionData[row + 1][col] == '*') foo(row+ 1, col); else if ( twoDimensionData[row - 1 ][col - 1] == '*') foo(row - 1, col - 1); //. I need 5 more of this bad boys I mean if checks } ... It is wrong to explore in only one direction, so I assume you do not mean "else". Is there any better way to achieve this foreach(i;row-1..row+2){ foreach(j;col-1..col+2){ if(i==row && j==col) continue; if(twoDimensionData[i][j] == '*') foo(row,col); } } with cool std functions like enumerate or iota without needing to write eight if checks? cartesianProduct(iota(row-1,row+2),iota(col-1,col+2)) .filter!(a=>(a[0]!=row||a[1]!=col)) .filter!(a=>twoDimensionData[a[0]][a[1]]=='*') .each!(a=>foo(a.expand)); (You can usually drop the first filter because "doing something" will usually involve checking if the node has been visited and returning or else marking the node as visited.) Ivan's example in this style: import std.stdio, std.range, std.algorithm, std.array; char[][] arr; int componentSize(size_t row, size_t col){ if(row>=arr.length||col>=arr[row].length||arr[row][col]!='*') return 0; arr[row][col]='x'; return 1+cartesianProduct(iota(row-1,row+2),iota(col-1,col+2)) .map!(a=>componentSize(a.expand)).sum; } void main (){ arr=["xx*", "*xx", "xx**xxx", "xx**x**", "xxx"].map!dup.array; cartesianProduct(iota(arr.length),iota(arr[0].length)) .filter!(a=>arr[a[0]][a[1]]=='*') .each!(a=>writeln(componentSize(a.expand))); } (This works even if there are * at the border.)
Re: Avoid if statements for checking neighboring indexes in a 2D array
On 16.07.2017 12:37, kerdemdemir wrote: My goal is to find connected components in a 2D array for example finding connected '*' chars below. x x x x x x x x x x x x x x * * x x x x * * x x x x x * * x * x x x x x There are two connected '*' group in this example. First group is composes of six '*' located closer to middle and the second group composes only one '*' char located in the left bottom corner. Do to this I generally implement a recursive algorithm which repeat calling the same function by checking all neighbors around the current index. I generally end up with something like : void foo( int row, int col) { //Do something here like caching the index if ( twoDimensionData[row - 1][col] == '*') foo(row- 1, col); else if ( twoDimensionData[row + 1][col] == '*') foo(row+ 1, col); else if ( twoDimensionData[row - 1 ][col - 1] == '*') foo(row - 1, col - 1); //. I need 5 more of this bad boys I mean if checks } ... It is wrong to explore in only one direction, so I assume you do not mean "else". Is there any better way to achieve this foreach(i;row-1..row+2){ foreach(j;col-1..col+2){ if(i==row && j==col) continue; if(twoDimensionData[i][j] == '*') foo(row,col); } } with cool std functions like enumerate or iota without needing to write eight if checks? cartesianProduct(iota(row-1,row+2),iota(col-1,col+2)) .filter!(a=>(a[0]!=row||a[1]!=col)) .filter!(a=>twoDimensionData[a[0]][a[1]]=='*') .each!(a=>foo(a.expand)); (You can usually drop the first filter because "doing something" will usually involve checking if the node has been visited and returning or else marking the node as visited.)
Re: The Nullity Of strings and Its Meaning
On 08.07.2017 19:16, kdevel wrote: I wonder if this distinction is meaningful Not nearly as much as it would need to be to justify the current behavior. It's mostly a historical accident. and---if not---why it is exposed to the application programmer so prominently. I don't think there is a good reason except backwards-compatibility. Also see: https://github.com/dlang/dmd/pull/4623 (This is the pull request that restored the bad behaviour after it had been fixed.)
Re: .sort vs sort(): std.algorithm not up to the task?
On 08.06.2017 14:06, Steven Schveighoffer wrote: The issue here is that arrays are special. Arrays allow foreach(i, v; arr) and foreach(v; arr). Ranges in general do not. So there is no way to forward this capability via the range interface. Not only that, but foreach(i, v; arr) is much different than iterating even a range that returns a tuple in that the index is *specific to the loop* and doesn't involve the array at all. It's more similar to opApply. opApply can help, but still is different than how arrays work (foreach with array is handled directly by the compiler). But ranges are not going to be forwarding this feature just for arrays. Arguably, foreach over ranges and foreach over arrays are badly designed. Automatic tuple expansion only works with ranges, and indexed iteration only works with arrays, and they are mutually incompatible. Therefore, there is no good way to fix the problem.
Re: Primality test function doesn't work on large numbers?
On 10.01.2017 04:02, Elronnd wrote: Thank you! Would you mind telling me what you changed aside from pow() and powm()? 1. This code: // make 2^a = integer-1 while ((integer-1)%(pow(bigint(2), a))!=0) a--; m = (integer-1) / pow(bigint(2), a); a starts out as integer-1, so this computes many big powers of two if integer-1 has only a few factors of 2 (which is very likely if integer is a random number), so I changed this to: for(m=integer-1;m%2==0;m/=2,++a){} where a starts from 0. Now it just counts the factors of two and m is computed on the fly. 2. There was a bug in the Miller-Rabin implementation. (There are two cases where the function should return false. Only one was present.) diff isn't giving me readable results, since there was some other stuff I trimmed out of the original file. Also, while this is a *lot* better, I still get some lag generating 1024-bit primes and I can't generate larger primes in a reasonable amount of time. Maybe my genbigint() function is to blame? It isn't efficient: bigint genbigint(int numbits) { bigint tmp; while (numbits --> 0) { tmp <<= 1; tmp += uniform(0, 2); } return tmp; } This should be quite fine, as its running time is linear in numbits (when rejection sampling to get into the right range, the running time will still be linear in numbits in expectation). I would expect that the problem is pow and powm, as for the typical bases, exponents and moduli you use, they have running time Ω((log(modulus)+log(exponent))*log(exponent)). The actual asymptotic running time is significantly more than this bound, as multiplication is done using Karatsuba. Maybe you can get a relevant speedup by using a different bigint implementation. The std.bigint documentation says that it is optimized for numbers up to ~1000 decimal digits and that you should probably use GMP for larger numbers. https://dlang.org/phobos/std_bigint.html GMP also has implementations of pow and powm built-in. Other than that: 1. You can save a constant factor of time in genbigint by generating more than one bit at a time. (But I don't think this is the bottleneck.) 2. Generating only odd candidates should give you a factor of two. 3. In mrprime, you should check other small primes other than 2, as a random number is likely to have a small prime factor. If what you need is some fast black-box to generate large primes, you can probably use existing libraries.
Re: Primality test function doesn't work on large numbers?
On 08.01.2017 08:52, Elronnd wrote: I'm working on writing an RSA implementation, but I've run into a roadblock generating primes. With a more than 9 bits, my program either hangs for a long time (utilizing %100 CPU!) or returns a composite number. With 9 or fewer bits, I get primes, but I have to run with a huge number of iterations to actually _get_ a random number. It runs fast, though. Why might this be? Code: http://lpaste.net/1034777940820230144 Fixed version: import std.bigint; import std.stdio; private alias bigint = BigInt; bigint pow(bigint base,bigint exponent){ bigint tmp=1; for(auto x=base,y=exponent;y;x*=x,y/=2) if(y%2) tmp*=x; return tmp; } bigint powm(bigint base,bigint exponent,bigint modulus){ bigint tmp=1; for(auto x=base,y=exponent;y;x=x*x%modulus,y/=2) if(y%2) tmp=tmp*x%modulus; return tmp; } private pragma(inline, true) bigint pow(int base, bigint exponent) { return pow(bigint(base), exponent); } private pragma(inline, true) bigint pow(bigint base, int exponent) { return pow(base, bigint(exponent)); } private pragma(inline, true) bigint pow(int base, int exponent) { return pow(bigint(base), bigint(exponent)); } // Credit to http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf appendix C.3 private bigint genprime(int bits, int numtests){ import std.random: uniform; bool mrprime(bigint integer, int iterations) { if(integer%2==0) return false; bigint m, a = 0, tmp = integer, b, z; int length; for(m=integer-1;m%2==0;m/=2,++a){} assert((integer-1)%pow(bigint(2), a)==0); while(tmp != 0) { tmp >>=1; length += 1; } for (int i=0; i= (integer-1))) { b = 0; for (int j = 1; j<=length; j++) { b <<= 1; b += uniform(0, 2); } } z = powm(b, m, integer); if((z == 1) || (z == integer-1)) goto endofloop; for(int k=1; k<=a-1; k++) { z = z*z%integer; if(z == integer-1) goto endofloop; if(z == 1) return false; } return false; endofloop: } return true; } bigint genbigint(int numbits) { bigint tmp; while (numbits --> 0) { tmp <<= 1; tmp += uniform(0, 2); } return tmp; } bigint currnum; while (true) { currnum = genbigint(bits); if (mrprime(currnum, numtests)) { return currnum; } } assert(0); } void main(){ writeln(genprime(300,30)); }
Re: DRY version of `static if(__traits(compiles, expr)) fun(expr)`
On 15.12.2016 01:38, Basile B. wrote: On Wednesday, 14 December 2016 at 22:06:35 UTC, Ali Çehreli wrote: On 12/14/2016 09:25 AM, Basile B. wrote: > On Tuesday, 13 December 2016 at 23:37:59 UTC, Timon Gehr wrote: >> I usually do >> >> enum code = q{expr}; >> static if(__traits(compiles,mixin(code))) >> fun(mixin(code)); > > Strangely if i put this in a templated enum that doesn't work. > If instead i use a delegate literal it works. > > enum Compiles(string code) = is(typeof((){mixin(code);})); > > enum Compiles2(string code) = __traits(compiles, mixin(code)); When you do that, the code does not match the syntax of __traits(compiles). Putting the code inside a scope works at least in this case: enum Compiles2(string code) = __traits(compiles, mixin('{' ~ code ~ '}')); Ali I see, it makes sense. Anyway the two templates have a common problem (protection attributes: data used in the code must be visible to the outside), so using them as a shortcut is a false good idea. Shortcut that works: enum ifCompiles(string code)=`static if(__traits(compiles,{ `~code~` })){ `~code~` }`; mixin(ifCompiles!q{ ... });
Re: DRY version of `static if(__traits(compiles, expr)) fun(expr)`
On 14.12.2016 00:00, Timothee Cour via Digitalmars-d-learn wrote: what's the best (and DRY) way to achieve: ``` static if(__traits(compiles, expr)) fun(expr); ``` ie, without repeating the expression inside expr? eg: ``` static if(__traits(compiles, foo.bar[2])){ counter++; writeln(" expr = ", foo.bar[2]); } ``` I usually do enum code = q{expr}; static if(__traits(compiles,mixin(code))) fun(mixin(code));
Re: Delegates: Print 0..9
On 01.12.2016 21:12, Ali Çehreli wrote: This is a common issue with D and some other languages (as I had learned during a Dart language presentation, of which Dart does not suffer from). All those delegates do close on the same loop variable. You need to produce copies of the variable. This is a common misconception. It's an implementation bug. The variables /are/ distinct. It is actually memory corruption. Evidence: import std.stdio; void main(){ int delegate()[] dgs; foreach(immutable i;0..10){ dgs~=()=>i; // i is immutable } foreach(dg;dgs) writeln(dg()); // yet changes dgs=[]; foreach(i;0..10){ int j=i; // creating a new variable dgs~=()=>j; } foreach(dg;dgs) writeln(dg()); // does not help }
Re: Combining "chunkBy" and "until" algorithms
On 04.11.2016 09:04, Jacob Carlborg wrote: I have a file with a bunch of lines I want to process. I want to process these lines line by line. Most of these lines have the same pattern. Some of the lines have a different pattern. I want to bundle those lines, which have a non-standard pattern, together with the last line that had the standard pattern. The number of lines with a non-standard pattern is unknown. Are there some algorithms in Phobos that can help with this? Maybe an algorithm combining "chunkBy" and "until" could do it? Currently I'm using a standard for loop iterating over the lines. I'm always looking at the current line and the next line. When the current line is the standard pattern and the next line is is not, I do a separate loop until I see a standard pattern again, collecting the lines with the non-standard pattern in an array. "chunkBy" a predicate that checks whether a line is standard. Use 'zip' to focus two adjacent chunks at the same time. Use 'filter' to only consider adjacent chunks where the first chunk consists of standard lines. Then extract the last line of the first chunk and combine it with the second chunk. import std.algorithm, std.range, std.typecons; import std.stdio; void main(){ auto data=["standard1","standard2","non-standard1","standard3", "non-standard2","non-standard3","standard4"]; static bool isStandard(string s){ return s.startsWith("standard"); } auto chunks=data.chunkBy!isStandard; auto pairs=zip(chunks.save,chunks.dropOne); auto result=pairs.filter!(x=>x[0][0]) .map!(x=>tuple(last(x[0][1]),x[1][1])); result.each!(x=>writeln(x[0],", (",x[1].joiner(", "),")")); } auto last(R)(R r){ // missing from Phobos AFAIK return zip(r.save,r.dropOne.recurrence!"a[n-1].dropOne" .until!(x=>x.empty)) .filter!(x=>x[1].empty).front[0]; } Prints: standard2, (non-standard1) standard3, (non-standard2, non-standard3)
Re: Variadic function with parameters all of a specific type
On 17.06.2016 23:00, Nordlöw wrote: I want to create a function that takes a variadic number of arguments all of a specific type, say T, without having to create GC-allocated heap array. Is there a better way than: f(Args...)(Args args) if (allSameType!(Args, T); in terms of template bloat? alias T=int; void foo(T[] a...)@nogc{} void bar()@nogc{ foo(1,2,3); }
Re: operator overload for enum
On 10.06.2016 13:02, Satoshi wrote: Hello, why operator overloading is not working as a static methods through the UFCS? ... It's an arbitrary limitation. https://issues.dlang.org/show_bug.cgi?id=8062 (The specification has been updated in the meantime, it now documents the limitation explicitly. https://dlang.org/spec/operatoroverloading.html) I need overload a << operator in this way: enum PlatformID { None, Trinix, Unix, MacOS, Windows } PlatformID toPlatformID(string platform) { switch (platform.toLower()) { case "trinix": return PlatformID.Trinix; case "unix":return PlatformID.Unix; case "macos": return PlatformID.MacOS; case "windows": return PlatformID.Windows; default:return PlatformID.None; } } void opBinary(string op)(ref PlatformID plat, auto ref const string str) if (op == "<<") { plat = toPlatformID(str); } void thisIsTest() { PlatformID id; id << "x86_64"; // this is not working id.opBinary!("<<")("test"); // but this works O.K. } Yuck. This should at the very least be opAssign instead.
Re: Why aren't overloaded nested functions allowed?
On 30.05.2016 18:22, Max Samukha wrote: From the spec (https://dlang.org/spec/function.html#nested): "Nested functions cannot be overloaded." Anybody knows what's the rationale? The rationale is that nobody has implemented it in DMD. https://issues.dlang.org/show_bug.cgi?id=12578
Re: Operator overloading through UFCS doesn't work
On 25.05.2016 01:19, Elie Morisse wrote: On Saturday, 13 October 2012 at 22:58:56 UTC, Timon Gehr wrote: Afaik free-function operator overloads (but not in the context of UFCS) were considered and turned down because D did not want to get amidst discussions about adding Koenig lookup. UFCS does not do Koenig lookup. I don't get it, aren't the current symbol lookup rules enough to make free function operator overloads useful? To me it looks like they are. ... Yup. It could be argued that it is essentially a compiler bug. Sorry for digging up this thread, just getting irritated by a restriction that seems pointless and arbitrary. ... It is, but it has a few vocal proponents. Overloaded operators would suffer from the same potential abuses other methods are subjected to if UFCS was enabled, nothing more as far as I can see. You are perfectly right of course. It's painful for no benefit. (For example, there's no way to overload e.g. '+=' for classes in a way that reassigns the reference.)
Re: Ada-Style Modulo Integer Types
On 22.04.2016 21:52, Nordlöw wrote: On Friday, 22 April 2016 at 17:37:44 UTC, Nordlöw wrote: Have anybody implement Ada-style modulo types https://en.wikibooks.org/wiki/Ada_Programming/Types/mod Here's my first try https://github.com/nordlow/phobos-next/blob/master/src/modulo.d Is there a way to use alias _value this; except mutation of _value which should check that _value is within value range (0 .. m-1)? Why do you want to perform a range check? Shouldn't it just take the appropriate remainder? Anyway, the following will do what you request: struct Mod(int M){ private int x; @property int prop(int x)in{assert(0<=x&
Re: Why this code can't take advantage from CTFE?
On 02/03/2016 11:39 PM, Andrea Fontana wrote: On Wednesday, 3 February 2016 at 17:49:39 UTC, Marc Schütz wrote: On Wednesday, 3 February 2016 at 16:07:59 UTC, Messenger wrote: What is a good way to try to force it? Using enum? Then optionally copying the value once to avoid the "manifest constant" copy/paste behaviour, where applicable? template forceCTFE(alias expr) { alias forceCTFE = expr; } auto value = forceCTFE!(some_expression()); Interesting :) Thank you! I would use enum forceCTFE(alias expr)=expr; though. With alias it won't force compile-time evaluation of expressions that can be interpreted as symbols.
Re: Functions that return type
On 01/17/2016 08:09 PM, data pulverizer wrote: On Sunday, 17 January 2016 at 02:08:06 UTC, Timon Gehr wrote: On 01/16/2016 11:50 PM, data pulverizer wrote: I guess the constraints are that of a static language. (This is not true.) Could you please explain? E.g., a few of the systems discussed at https://ncatlab.org/nlab/show/pure+type+system would be a fine basis for a "static language" that supports returning types from functions.
Re: Functions that return type
On 01/16/2016 11:50 PM, data pulverizer wrote: I guess the constraints are that of a static language. (This is not true.)
Re: bug? for(int i=0;i<1;) vs while(true)
On 09/17/2015 09:47 PM, ddos wrote: yeah i tried for(;;) and it generates the same warning :) sure, here is the full example, it's not too long anyways ( the example doesn't make much sense tho because socket.accept is blocking :P ) http://pastebin.com/9K0wRRD6 ps: pastebin needs D support :-D Remove the return statement from main and the warning will go away. (Note: unless you want to influence the return code, you can actually declare main as returning void, then you don't need it even if the end of the function is reachable.)
Re: Superfluous code in switch statement
On 09/04/2015 09:39 PM, Paul wrote: I discovered the other day (during a cut and paste malfunction!) that it's possible to have code before the first case in a switch. Google tells me that it's legal C code and something I read said it could be used for initialization but was rather vague. void main() { import std.stdio; int a=1; switch(a) { a=2; writeln("hello"); case 1: break; case 2: break; default: } writeln(a); } The code before the 'case' has to be legal D code to pass compilation but it seems to have no effect (which is probably a good thing!). I was a bit surprised that the compiler (dmd) didn't generate a warning when using the -w option. Can someone explain what's going on here please? The switch statement is quite unstructured. You can have your case statements basically at arbitrary points where a statement is expected: import std.stdio; int main(){ int x=2; switch(x){ do{ for({case 0:};){} x--; case 1: x--; if(false){ default: writeln("!"); return 0; } }while(true); } } The only case where statements before the first case/default are potentially useful is when there is some way to jump back there. One could use goto or something like https://en.wikipedia.org/wiki/Duff%27s_device It's not a very common thing to do though, and I don't think anyone would be sad if there was a dead code warning for the case where the code before the case statements cannot actually be reached. It's not done though. DMD never warns about dead code.
Re: Superfluous code in switch statement
On 09/04/2015 11:12 PM, anonymous wrote: On Friday 04 September 2015 23:04, Timon Gehr wrote: DMD never warns about dead code. It warns here: import std.stdio; void main() { return; writeln("hi"); /* Warning: statement is not reachable */ } You are right, it does. Then I suppose there is no reason why it shouldn't warn in the switch case.
Re: stuck on opDiv / opBinary
On 08/30/2015 07:02 PM, Spacen Jasset wrote: I have just added an opDiv to this class, but it doesn't seem to pick it up. math/vector.d(30): Error: 'this /= mag' is not a scalar, it is a Vector3 I can't see why that is, becuase my opMul works in the same place. Can anyone point out what I have done wrong? ... import std.math: sqrt; import std.algorithm: map,sum,canFind; struct Vector3{ float[3] xyz; void normalise(){ this/=magnitude(); } float magnitude(){ return sqrt(xyz[].map!(a=a*a).sum); } enum scalarOps=[*,/]; enum isScalarOp(string op)=scalarOps.canFind(op); void scalar(string op)(float scalar)if(isScalarOp!op){ foreach(ref a;xyz) mixin(`a `~op~`=scalar;`); } Vector3 opBinary(string op)(float scalar)if(isScalarOp!op){ Vector3 v=this; v.scalar!op(scalar); return v; } auto opOpAssign(string op)(float rhs)if(isScalarOp!op){ return mixin(`this=this `~op~` rhs`); } }
Re: Should this compile?
On 08/25/2015 08:29 PM, Vladimir Panteleev wrote: I think this is a bug, but is easily worked around with: auto test(string a) { return .test(a, b); } I suspect that the reason the error occurs, is that the auto return type automatically rewrites the function declaration into an eponymous template declaration. ... No true. In fact, doing so manually works around the problem. :o) This compiles and runs: import std.stdio; import std.range : chain; auto test()(string a) { return test(a,b); } auto test(string a,string b) { return chain(a,b); } void main() { writeln(test(a)); }
Re: Should this compile?
On 08/26/2015 09:55 PM, Timon Gehr wrote: On 08/25/2015 08:29 PM, Vladimir Panteleev wrote: I think this is a bug, but is easily worked around with: auto test(string a) { return .test(a, b); } I suspect that the reason the error occurs, is that the auto return type automatically rewrites the function declaration into an eponymous template declaration. ... No true. In fact, doing so manually works around the problem. :o) This compiles and runs: import std.stdio; import std.range : chain; auto test()(string a) { return test(a,b); } auto test(string a,string b) { return chain(a,b); } void main() { writeln(test(a)); } Another workaround is to order the declarations in the opposite way: import std.stdio; import std.range : chain; auto test(string a,string b) { return chain(a,b); } auto test(string a) { return test(a,b); } void main() { writeln(test(a)); }
Re: automatically verifying code samples in phobos docs
On 08/20/2015 01:41 AM, Laeeth Isharc wrote: BTW I don't know why you can't convert a char[] to string - seems harmless enough conversion that way around. It would need to allocate a new string, otherwise, one would be able to modify the contents of the immutable string via the char[] reference.
Re: automatically verifying code samples in phobos docs
On 08/20/2015 02:02 AM, Laeeth Isharc wrote: On Thursday, 20 August 2015 at 00:00:55 UTC, Timon Gehr wrote: On 08/20/2015 01:41 AM, Laeeth Isharc wrote: BTW I don't know why you can't convert a char[] to string - seems harmless enough conversion that way around. It would need to allocate a new string, otherwise, one would be able to modify the contents of the immutable string via the char[] reference. and you don't want sneaky allocations creeping in. ok. tku. how about automatically checking code in examples? I think this is the recommended mechanism for that: http://dlang.org/unittest.html (documented unit tests)
Re: cannot implicitly convert char[] to string
On 08/15/2015 01:54 PM, Timon Gehr wrote: On 08/15/2015 01:25 PM, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. Get rid of the 'in' in format's signature. Oh, I see, this is by design (which I don't like, but OK.) The reason the conversion does not go through is that format is not marked as pure.
Re: cannot implicitly convert char[] to string
On 08/15/2015 01:25 PM, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. Get rid of the 'in' in format's signature.
Re: iterating through a range, operating on last few elements at a time
On 08/14/2015 05:12 AM, H. S. Teoh via Digitalmars-d-learn wrote: On Fri, Aug 14, 2015 at 02:42:26AM +, Laeeth Isharc via Digitalmars-d-learn wrote: I have a range that is an array of structs. I would like to iterate through the range, calling a function with the prior k items in the range up to that point and storing the result of the function in a new range/array. what's the best way to do this? for low fixed k I could use zip with staggered slices (s[3..$],s[2..$-1],s[1..$-2],s[0..$-3]) and then map. I can't think of how to do it elegantly. any thoughts? Maybe something like this? import std.algorithm; import std.stdio; import std.range; auto slidingWindow(R)(R range, int k) { return iota(k).map!(i = range.save.drop(i)) .array .transposed; } void main() { auto data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; writeln(data.slidingWindow(3)); } To apply the function to each slice, just write: data.slidingWindow(k).map!myFunc ... I didn't figure out how to eliminate the short slices toward the end, import std.algorithm; import std.stdio; import std.range; auto transp(RoR)(RoR ror){ static struct Transp{ typeof(transposed(ror)) orig; alias orig this; @property bool empty(){ return orig.tupleof[0].any!(a=a.empty); } } return Transp(transposed(ror)); } auto slidingWindow(R)(R range, int k) { return iota(k).map!(i = range.save.drop(i)).array.transp; } void main() { auto data = iota(1,11).array; writeln(data.slidingWindow(3)); } :o) but all you need to do is to somehow drop the last (k-1) elements from the range returned by slidingWindow.
Re: iterating through a range, operating on last few elements at a time
On 08/14/2015 03:26 PM, Timon Gehr wrote: On 08/14/2015 05:12 AM, H. S. Teoh via Digitalmars-d-learn wrote: ... I didn't figure out how to eliminate the short slices toward the end, ... :o) ... Less hacky and less efficient: auto slidingWindow(R)(R range, int k) { return iota(k).map!(i=range.save.drop(i)) .array.transposed.zip(range.save.drop(k-1)).map!(a=a[0]); }
Re: Attributes not propagating to objects via typeinfo?
On 08/13/2015 06:05 PM, Steven Schveighoffer wrote: On 8/13/15 11:59 AM, Steven Schveighoffer wrote: That is definitely a bug. It's because typeid is looking up the derived type via the vtable, but the compiler should rewrap it with 'shared' afterwards. Actually, now that I think about it, I'm not sure how the compiler can figure this out. There would have to be a way to construct a TypeInfo_Shared at runtime, which the compiler shouldn't be doing. Alternatively, it could proactively create a TypeInfo_Shared (and all the other flavors) for each class type in the runtime, and then look it up using some hash mechanism. ... Can't the shared typeinfo be constructed for all superclasses of C at the point where shared(C) is used? (Think: template instantiation.) This likely isn't fixable. ... I don't understand. It is evidently fixable. E.g. if TypeInfo was just a template without the mostly redundant additional compiler support, this would be a trivial fix.
Re: Should these aliases kind be illegal ?
On 08/13/2015 12:17 AM, anonymous wrote: The following alias declaration is totally legal but actually it's not usable --- class Foo { void something(size_t param){} } class Bar { private Foo foo; this(){foo = new Foo;} alias somethingelse = foo.something; } void main(string[] args) { auto bar = new Bar; //bar.somethingelse(0u); } --- The call doesn't work but the declaration is fine. What is possible to make with this declaration ? I believe it currently just does the same thing as: --- class Foo{ void something(size_t param){} } class Bar{ private Foo foo; this(){foo = new Foo;} alias somethingelse = typeof(foo).something; } --- But IMO the appropriate response here is to just make it work as one would expect, not to make it illegal.
Re: std.array: array, ulong and Win32
On 08/09/2015 10:13 PM, ixid wrote: This seems like a reasonable use but errors, obviously I can do it in many other ways: ulong[] result = iota(1UL, 10UL).array; Error: static assert Argument types in (ulong) are not all convertible to size_t: (ulong)C:\D\dmd2\src\phobos\std\array.d516 ... I consider this to be a bug. Also, it's annoying static assert abuse. And while I'm here why do arrays not implicitly cast? Array literals do cast implicitly. ulong is happy to accept uint values but ulong[] will not accept uint[]. Many reasons. E.g. it would be a hidden not-necessarily-constant-time operation.
Re: Find on sorted range slower?
On 08/07/2015 11:03 AM, Tofu Ninja wrote: On Friday, 7 August 2015 at 08:18:04 UTC, Nordlöw wrote: On Friday, 7 August 2015 at 05:21:32 UTC, Tofu Ninja wrote: HAHAH wow, this is hilarious, I just checked, nothing in std.algo takes advantage of sorted ranges, sort doesn't even take advantage of it! You pass a sorted range into sort and it will just resort it! Wow Who fixes this? I can look into it... is there an issue for this? I have no idea, but it is pretty silly. Sort/isSorted on a sorted range should be a nop. Find and friends, should do doing some kind of binary search. Max and min should be O(1). Some of the functions that return a sub range or a mutated range could probably be returning sorted ranges as well if its input is a sorted range, remove, strip and split at least could. Binary search is not always faster than linear search.
Re: Passing struct and struct[] into a template
On 07/22/2015 06:29 AM, Taylor Gronka wrote: Hi, I have a template function, and I want it to do something if the input variable is a list of structs, and something else if the input is a struct. 1) What's the best way to test this? I suppose I can call __traits(identifier, results) and look at the last two characters. 2) If `T` is a list of structs, how can I initialize a new struct so that I can append to `T`? This is sort of how it might be done in python. I haven't implemented question 2 yet since I'm not sure how atm: template Uks(T) { T query(string q) { T result; try { ulong test = result.length; // won't compile for non-list structs // append to a struct list T.subtype newResult; // is there a function like this? result ~= newResult; } catch { // assign the struct members directly } return result; } } I would like to call it like either of the following, depending on if I want 1 result or X results: auto res = Uks!(U_Struct).query(email); auto res = Uks!(U_Struct[]).query(email); I'd be happy to hear better design methods. Thanks template Uks(T){ T query(string q){ T result; static if(is(T==S[],S)){ ulong test=result.length; // append S newResult; result~=newResult; }else{ // assign } return result; } } void main(){ struct U_Struct{} auto res1=Uks!(U_Struct).query(email); auto res2=Uks!(U_Struct[]).query(email); }
Re: Fixed Length Array Syntax in extern(C) Function Signatures
On 07/09/2015 05:19 PM, Nordlöw wrote: Given extern(C): struct AVFrame { uint8_t*[AV_NUM_DATA_POINTERS] data; int[AV_NUM_DATA_POINTERS] linesize; int width, height; ... } void av_image_copy(ubyte *[4] dst_data, int[4] dst_linesizes, const ubyte *[4] src_data, const int[4] src_linesizes, AVPixelFormat pix_fmt, int width, int height) will `dst_data` will be C-ABI-fed to `image_copy()` as a C-style single pointer in constrast to what happens in D which calls it as fixed-size (4) array of ubyte-pointers? No. You'll need explicit pass by reference on the D side.
Re: Autocorrelation function with ranges
On 06/27/2015 12:29 PM, kerdemdemir wrote: Hi My question is more about Maths than D lang, I am hoping, maybe somebody worked with AutoCorrelation function before. auto autoCorrelation(R)(R range) if (isRandomAccessRange!R) { auto residual = residualPowerOf2(range.length); // Find how many zeros to add auto fftResult = range.chain(repeat(0, residual)).fft(); // Takes FFT //First zip each element of fft with conjagute of fft auto autoCorrResult = fftResult.zip(fftResult.map!(a = a * a.conj())). map!( a= a[0] * a[1] ). // Than multiple them inverseFft(). // Than take inverse dropBack(residual);//Drop the additional zeros auto finalResult = autoCorrResult.take(1). // Take DC element chain(autoCorrResult[$/2..$]).//Take last half to beginning chain(autoCorrResult[1..$/2]). // First(negative lags) to end map!(a = a.re); // I just need real part return finalResult ; } My autocorrelation method return some crazy values(finalResult[0] = -101652). I am mostly suspicious about calculations to set finalResult variable. ... One obvious problem is this: fftResult.zip(fftResult.map!(a = a * a.conj())).map!(a=a[0]*a[1]). This computes a²·a̅ instead of a·a̅. What is the source code for residualPowerOf2? Also is there any performance issues? can I make this faster? Probably you should use http://dlang.org/phobos/std_complex.html#.sqAbs instead. You then also don't need the final map to extract the real part.
Re: Autocorrelation function with ranges
On 06/27/2015 02:17 PM, Timon Gehr wrote: You then also don't need the final map to extract the real part. (This is actually not true, your inverseFFT presumably still returns complex numbers.)
Re: Static constructors guaranteed to run?
On 06/27/2015 11:54 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= schue...@gmx.net wrote: Also are static constructors in templated types guaranteed to run for every instantiation? Even if the instantiation is never actually used outside of compile time code, like in an alias or in a UDA? Definitely not. Things inside a template don't even exist if that template is never instantiated. (That wasn't his question.)
Re: @property on free function for UFCS?
On 06/14/2015 05:50 PM, ketmar wrote: On Sun, 14 Jun 2015 12:26:52 +, rcorre wrote: Suppose I have a function defined like so: void foo(int i) { } intended to be called like: 5.foo Should it be labeled with @property? Or is @property only for true member functions? only if you plan to use it like `foo = 5;`. You can use it like that anyway. i.e. exactly like field variable. struct S{ void delegate() dg; } int main(){ S s; s.dg=(){ writeln(!); }; s.dg(); } Now show me the UFCS way. compiler will not complain, but putting `@property` here is stylistically wrong. It's neither wrong nor right.
Re: Get index of string in array at compile time
On 05/29/2015 06:43 PM, tcak wrote: I have define an immutable string array: [code] immutable string[] placeHolderDefinitionList = [ !-- fullname --, !-- list item -- ]; [/code] I need to get index of a string at compile time. So I have written a function as below: [code] public size_t getPlaceholderIndex(string PlaceHolderText)( size_t lookIndex = 0 ){ static if( lookIndex = placeHolderDefinitionList.length ) return size_t.max; static if( placeHolderDefinitionList[lookIndex] == PlaceHolderText ) return lookIndex; else return getPlaceholderIndex( lookIndex + 1 ); } [/code] Called it as below: [code] writeln( Index: , getPlaceholderIndex!!-- list item --( 0 ) ); [/code] Compiler didn't like my code. It said those things to my face: main.d(22): Error: variable lookIndex cannot be read at compile time main.d(25): Error: variable lookIndex cannot be read at compile time main.d(28): Error: template main.getPlaceholderIndex cannot deduce function from argument types !()(ulong), candidates are: main.d(21):main.getPlaceholderIndex(string PlaceHolderText)(size_t lookIndex = 0) main.d(105): Error: template instance main.getPlaceholderIndex!!-- list item -- error instantiating This is my first try with this type of code. So I am confused a little about what I should be doing. The easiest way is to just write runtime code and evaluate it via CTFE: immutable string[] placeHolderDefinitionList = [ !-- fullname --, !-- list item -- ]; void main(){ import std.stdio, std.algorithm; enum index=placeHolderDefinitionList.countUntil(!-- list item --); writeln(Index: , index); } If you never need the placeHolderDefinitionList at runtime, make it enum instead of immutable.
Re: drastic slowdown for copies
On 05/28/2015 11:27 PM, Adam D. Ruppe wrote: 16 bytes is 64 bit It's actually 128 bits.
Re: problem with custom predicate
On 05/27/2015 05:30 PM, Steven Schveighoffer wrote: On 5/27/15 9:11 AM, Simon =?UTF-8?B?QsO8cmdlciI=?= simon.buer...@rwth-aachen.de wrote: On Wednesday, 27 May 2015 at 14:58:39 UTC, drug wrote: Do you want to dynamically change priority? Actually yes. In my actual code I am not using a RedBlackTree but my own Container (a heap with the possibility to modify elements inside), which is notified when prio changes so it can do a (local) reordering. It would be a very bad idea to change prio if the RBTree is constructed already (and if this works). Why prio is outside of your predicate? Well, how would I get it into the lambda? In C++ I would use a comparision class, and the constructor of the container would take an instance of that class. But D's RedBlackTree-constructor does not take such a (run-time) argument. And I dont see a way to get prio into the predicate, which is a template-argument. This is true, RedBlackTree does not take a functor as a parameter to the constructor, it just uses an alias. This should work if your RedBlackTree is scoped inside a function where the data exists. But at the time of declaration inside the class, the instance of prio doesn't exist, so you can't alias it. It would be a good enhancement I think to add support for function objects. -Steve Also, apart from missing implementation, there is no good reason why the code given should not work, is there? I think nested template instantiation should work in all scopes. (Of course, there is the issue that nested structs are somewhat arbitrarily not given a context pointer when declared within a class/struct, so this might be a little inconsistent in case it also works for structs, no question for classes though: just instantiate as nested class.)
Re: Null argument and function resolution
On 05/27/2015 10:09 PM, Meta wrote: On Wednesday, 27 May 2015 at 19:38:16 UTC, ketmar wrote: On Wed, 27 May 2015 14:09:47 +, Adam D. Ruppe wrote: Two options: 1) add an overload that takes typeof(null) this(typeof(null)) { /* handles the null literal specially */ } you keep breaking my box of thinking. ;-) never thought about such declaration. Unfortunately, there is no equivalent way to disable assignment of [] at compile time. struct ArrayWrapper(T) { T[] a; this(T[] arr) { a = arr; } //Doesn't work; Conflicts with this(T[] arr) //@disable this(typeof(this)[]); //Doesn't work; hijacked by this(T[] arr) //@disable this(typeof([])); } https://issues.dlang.org/show_bug.cgi?id=7007
Re: Distinguish recursive Templates
On 05/23/2015 12:12 AM, Manfred Nowak wrote: Matt Kline wrote: isn't making any use of the template argument T Correct. I do not know how to use `T' to determine the recursion depth of the template---and I want no further parameter. -manfred import std.stdio, std.range, std.algorithm; template getDepth(T){ static if(is(T==Set!S,S)) enum getDepth=1+getDepth!S; else enum getDepth=0; } class Set(T){ override string toString(){ enum r=Set.repeat.take(getDepth!Set).join; return r; } } void main(){ auto s0=new Set!uint; writeln(s0); // writes Set auto s1=new Set!(Set!uint); writeln(s1); // writes SetSet }
Re: UFCS
On 05/15/2015 11:31 PM, Manfred Nowak wrote: class C{} int main(){ void opOpAssign( string op)( C a, C b){ } C a, b; a+= b; } https://issues.dlang.org/show_bug.cgi?id=8062
Re: Lambda functions in D
On 05/09/2015 05:52 PM, Dennis Ritchie wrote: On Saturday, 9 May 2015 at 14:15:21 UTC, Ali Çehreli wrote: On 05/09/2015 04:59 AM, Dennis Ritchie wrote: On Saturday, 9 May 2015 at 11:49:48 UTC, Timon Gehr wrote: assert((function int(int x)=x?x*__traits(parent,{})(x-1):1)(10)==3628800); Thanks. Yes, it is similar to what I wanted :) Also interesting: http://rosettacode.org/wiki/Y_combinator#D I think that code was improved by Timon Gehr as well. Ali Yes, it's much better. Well, it is much slower due to all the allocated closures, owed to the fact that the implementations of 'fix' on that page are expected to mirror a particular famous implementation in untyped lambda calculus. In case you have a use for 'fix', a more efficient implementation might be: auto fix(S,T...)(S delegate(T) delegate (S delegate(T)) f){ S delegate(T) g=(T a){ assert(0,f is too eager.); }; return g=f((T a)=g(a)); } (In particular, this will only allocate two closures for the plumbing instead of a number of them linear in the number of recursive invocations.) Even something like Common Lisp. (Be aware that Common Lisp implementations typically have better garbage collectors than what is available for D.)
Re: Lambda functions in D
On 05/09/2015 01:20 PM, Dennis Ritchie wrote: Hi, Can lambda functions or delegates in D to call themselves? Can I write something like this: - import std.stdio; void main() { auto fact = function (int x) = x * { if (x) fact(x - 1); }; assert(fact(10) == 3628800); } assert((function int(int x)=x?x*__traits(parent,{})(x-1):1)(10)==3628800);
Re: status of D optimizers benefiting from contracts ?
On 11/09/2014 11:39 PM, H. S. Teoh via Digitalmars-d-learn wrote: The original meaning of assert() is what assume() means nowadays, whereas nowadays what people think of as assert() is actually what enforce() does in Phobos. T No.
Re: status of D optimizers benefiting from contracts ?
On 11/09/2014 05:24 PM, H. S. Teoh via Digitalmars-d-learn wrote: On Sun, Nov 09, 2014 at 04:12:06PM +, bearophile via Digitalmars-d-learn wrote: H. S. Teoh: Walter *did* mention recently that he was planning to eventually take advantage of information in assert()'s as optimizer hints. Not sure when this will happen, though, but it seems inevitable at some point. And it caused a storm, because it's an awfully bad idea. [...] It's only a bad idea because people abuse assert() where it's not appropriate. T Some do, but that's basically orthogonal to why this is a bad idea.
Re: Calling dynamically bound functions from weakly pure function
On 07/19/2014 03:53 PM, Kagamin wrote: It's ok to deduce opDispatch as pure, but then its purity should be enforced and error reported. Why would it be ok to deduce opDispatch as pure only to report an error that it is not actually pure? This would be a bug as well (albeit none that causes unsoundness.)
Re: std.algorithm.among
On 07/13/2014 01:18 PM, bearophile wrote: The idea of not making std.algorithm.among!() a predicate was not so good: ... Agreed. void main() { import std.stdio, std.algorithm; auto s = hello how\nare you; s.until!(c = c.among!('\n', '\r')).writeln; } (A normal workaround is to use !!c.among!). Bye, bearophile It works with filter, so I think it should just work with until as well.
Re: DStyle: Braces on same line
On 07/13/2014 06:45 PM, Joseph Rushton Wakeling via Digitalmars-d-learn wrote: Two consequences of adapting myself to Phobos style were that I realized (i)how little most of these things really matter, and (ii) pretty much any stylistic choice carries both benefits and drawbacks. ... Wrong. There are things which are simply bad ideas. E.g. in this case, Egyptian-style braces definitely make your code more compact, I.e. you see where everything is. but separate-line opening braces definitely make it easier to see where scopes begin and end. This is the only argument I have heard in favour of doing this, but it is not actually valid. This critique might apply to Lisp style.
Re: DStyle: Braces on same line
On 07/13/2014 07:51 PM, Brian Rogoff wrote: On Sunday, 13 July 2014 at 17:24:40 UTC, Timon Gehr wrote: On 07/13/2014 06:45 PM, Joseph Rushton Wakeling via Digitalmars-d-learn wrote: Wrong. There are things which are simply bad ideas. E.g. in this case, Egyptian-style braces definitely make your code more compact, I.e. you see where everything is. Yes, the same argument for books and slides is also applicable to all other media. Exactly. This style has also caught on amongst the other curly braced languages that I use, so that most of the code I read (and write) has adopted it (C/C++/Java/Javascript code, that is). The Phobos style is incredibly wasteful IMO, but that's what D has adopted, so if you intend to contribute to Phobos, you had better get used to it. The Rust community appears to have made the right choice with Egyptian for everything. ... Yup, but they also do horrible things like using '+' to denote intersection (multiple trait bounds). but separate-line opening braces definitely make it easier to see where scopes begin and end. All of this is subjective, of course, but I definitely don't find that the Phobos style provides this advantage. This is the only argument I have heard in favour of doing this, but it is not actually valid. This critique might apply to Lisp style. Not sure I follow you here. Most of the Lisp I've read is indented like Python, the idea being that you learn not to not see all of the parens and rely on tools like paredit to do the trivial balancing. I'd hate to read Lisp with separate lines for parens that open scopes. I'm sure that's not what you mean! I was suggesting that if someone does this: http://en.wikipedia.org/wiki/Indent_style#Lisp_style Then I would have an easier time seeing where a person is coming from who claims that it makes it in some way harder to see at a glance where scopes begin and end.