Re: opIndexAssign

2023-10-05 Thread Timon Gehr via Digitalmars-d-learn

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

2023-06-11 Thread Timon Gehr via Digitalmars-d-learn

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?

2023-04-01 Thread Timon Gehr via Digitalmars-d-learn

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?

2022-07-30 Thread Timon Gehr via Digitalmars-d-learn

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?

2022-07-30 Thread Timon Gehr via Digitalmars-d-learn

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

2022-04-11 Thread Timon Gehr via Digitalmars-d-learn

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"?

2021-12-08 Thread Timon Gehr via Digitalmars-d-learn

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"?

2021-12-08 Thread Timon Gehr via Digitalmars-d-learn

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

2020-10-03 Thread Timon Gehr via Digitalmars-d-learn

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

2020-03-09 Thread Timon Gehr via Digitalmars-d-learn

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?

2020-03-09 Thread Timon Gehr via Digitalmars-d-learn

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

2020-03-04 Thread Timon Gehr via Digitalmars-d-learn

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?

2019-12-06 Thread Timon Gehr via Digitalmars-d-learn

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?

2019-11-27 Thread Timon Gehr via Digitalmars-d-learn

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?

2019-11-26 Thread Timon Gehr via Digitalmars-d-learn

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?

2019-11-26 Thread Timon Gehr via Digitalmars-d-learn

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?

2019-11-25 Thread Timon Gehr via Digitalmars-d-learn

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*

2019-08-10 Thread Timon Gehr via Digitalmars-d-learn

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

2019-07-22 Thread Timon Gehr via Digitalmars-d-learn

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

2019-06-15 Thread Timon Gehr via Digitalmars-d-learn

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?

2019-05-23 Thread Timon Gehr via Digitalmars-d-learn

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

2019-05-03 Thread Timon Gehr via Digitalmars-d-learn

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?

2018-12-03 Thread Timon Gehr via Digitalmars-d-learn

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

2018-08-06 Thread Timon Gehr via Digitalmars-d-learn

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

2018-08-05 Thread Timon Gehr via Digitalmars-d-learn

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

2018-04-21 Thread Timon Gehr via Digitalmars-d-learn

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

2018-02-22 Thread Timon Gehr via Digitalmars-d-learn

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

2018-01-21 Thread Timon Gehr via Digitalmars-d-learn

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 ?

2018-01-15 Thread Timon Gehr via Digitalmars-d-learn

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 ?

2018-01-15 Thread Timon Gehr via Digitalmars-d-learn

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?

2018-01-09 Thread Timon Gehr via Digitalmars-d-learn

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?

2017-10-22 Thread Timon Gehr via Digitalmars-d-learn

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

2017-10-15 Thread Timon Gehr via Digitalmars-d-learn

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

2017-10-14 Thread Timon Gehr via Digitalmars-d-learn

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

2017-10-12 Thread Timon Gehr via Digitalmars-d-learn

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

2017-09-21 Thread Timon Gehr via Digitalmars-d-learn

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

2017-09-21 Thread Timon Gehr via Digitalmars-d-learn

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

2017-09-20 Thread Timon Gehr via Digitalmars-d-learn

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

2017-08-10 Thread Timon Gehr via Digitalmars-d-learn

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

2017-08-10 Thread Timon Gehr via Digitalmars-d-learn

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

2017-08-09 Thread Timon Gehr via Digitalmars-d-learn

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!

2017-07-29 Thread Timon Gehr via Digitalmars-d-learn

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!

2017-07-29 Thread Timon Gehr via Digitalmars-d-learn

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?

2017-07-24 Thread Timon Gehr via Digitalmars-d-learn

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

2017-07-24 Thread Timon Gehr via Digitalmars-d-learn

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

2017-07-16 Thread Timon Gehr via Digitalmars-d-learn

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

2017-07-16 Thread Timon Gehr via Digitalmars-d-learn

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

2017-07-16 Thread Timon Gehr via Digitalmars-d-learn

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

2017-07-08 Thread Timon Gehr via Digitalmars-d-learn

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?

2017-06-08 Thread Timon Gehr via Digitalmars-d-learn

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?

2017-01-12 Thread Timon Gehr via Digitalmars-d-learn

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?

2017-01-08 Thread Timon Gehr via Digitalmars-d-learn

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)`

2016-12-15 Thread Timon Gehr via Digitalmars-d-learn

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)`

2016-12-13 Thread Timon Gehr via Digitalmars-d-learn

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

2016-12-02 Thread Timon Gehr via Digitalmars-d-learn

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

2016-11-05 Thread Timon Gehr via Digitalmars-d-learn

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

2016-06-17 Thread Timon Gehr via Digitalmars-d-learn

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

2016-06-10 Thread Timon Gehr via Digitalmars-d-learn

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?

2016-05-31 Thread Timon Gehr via Digitalmars-d-learn

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

2016-05-26 Thread Timon Gehr via Digitalmars-d-learn

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

2016-04-22 Thread Timon Gehr via Digitalmars-d-learn

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?

2016-02-03 Thread Timon Gehr via Digitalmars-d-learn

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

2016-01-19 Thread Timon Gehr via Digitalmars-d-learn

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

2016-01-16 Thread Timon Gehr via Digitalmars-d-learn

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)

2015-09-17 Thread Timon Gehr via Digitalmars-d-learn

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

2015-09-04 Thread Timon Gehr via Digitalmars-d-learn

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

2015-09-04 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-30 Thread Timon Gehr via Digitalmars-d-learn

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?

2015-08-26 Thread Timon Gehr via Digitalmars-d-learn

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?

2015-08-26 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-19 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-19 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-15 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-15 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-14 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-14 Thread Timon Gehr via Digitalmars-d-learn

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?

2015-08-14 Thread Timon Gehr via Digitalmars-d-learn

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 ?

2015-08-12 Thread Timon Gehr via Digitalmars-d-learn

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

2015-08-09 Thread Timon Gehr via Digitalmars-d-learn

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?

2015-08-07 Thread Timon Gehr via Digitalmars-d-learn

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

2015-07-21 Thread Timon Gehr via Digitalmars-d-learn

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

2015-07-09 Thread Timon Gehr via Digitalmars-d-learn

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

2015-06-27 Thread Timon Gehr via Digitalmars-d-learn

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

2015-06-27 Thread Timon Gehr via Digitalmars-d-learn

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?

2015-06-27 Thread Timon Gehr via Digitalmars-d-learn
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?

2015-06-14 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-29 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-28 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-27 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-27 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-22 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-15 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-09 Thread Timon Gehr via Digitalmars-d-learn

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

2015-05-09 Thread Timon Gehr via Digitalmars-d-learn

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 ?

2014-11-10 Thread Timon Gehr via Digitalmars-d-learn

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 ?

2014-11-10 Thread Timon Gehr via Digitalmars-d-learn

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

2014-07-19 Thread Timon Gehr via Digitalmars-d-learn

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

2014-07-13 Thread Timon Gehr via Digitalmars-d-learn

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

2014-07-13 Thread Timon Gehr via Digitalmars-d-learn
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

2014-07-13 Thread Timon Gehr via Digitalmars-d-learn

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.


  1   2   3   4   5   6   7   8   9   >