Re: How to partially forward properties of struct array member to struct (disable length property) ?

2015-09-08 Thread Kenji Hara via Digitalmars-d-learn

On Sunday, 6 September 2015 at 10:12:58 UTC, ParticlePeter wrote:
In the end all that I want is "just" to disable access to 
array.length through vector and alias this array.


struct Vec(T, size_t n = 3)
{
T[n] data;

alias data this;

@disable @property size_t length() const;
}

void main()
{
Vec!int v;
v[0] = 1;   // ok
assert(v[0] == 1);  // ok
int n = v.length;   // error
}

- Kenji


Re: Cannot use the same template arguments on function as the ones on struct

2015-02-12 Thread Kenji Hara via Digitalmars-d-learn

On Wednesday, 11 February 2015 at 22:24:53 UTC, anonymous wrote:

On Wednesday, 11 February 2015 at 22:14:44 UTC, MrSmith wrote:

http://dpaste.dzfl.pl/5f1d5d5d9e19

Instead I need to use template constraint which is less 
compact.

http://dpaste.dzfl.pl/571ae84d783e

Why such behavior happens?


Seems to work when you add an empty template argument list to 
`accepter()`, making it `accepter!()()`: 
http://dpaste.dzfl.pl/2ec186453907


So, compiler bug, I guess? The error message says it tried 
!()(), but explicit !()() actually works. And the empty 
template argument list should be optional anyway.


It would be a compiler bug. As far as I know, accepter() and 
accepter!()() has no difference in IFTI.


I filed the issue in bugzilla.
https://issues.dlang.org/show_bug.cgi?id=14174

Kenji Hara


Re: class is forward referenced when looking for 'v'

2015-01-30 Thread Kenji Hara via Digitalmars-d-learn

On Friday, 30 January 2015 at 00:09:17 UTC, Amber Thralll wrote:

And the errors dmd returns:
test.d(16): Error: class test.A!int.A is forward referenced 
when looking for 'v'
test.d(16): Error: class test.A!int.A is forward referenced 
when looking for 'opDot'
test.d(16): Error: class test.A!int.A is forward referenced 
when looking for 'opDispatch'

test.d(29): Error: no property 'v' for type 'test.A!int.A'
test.d(10): Error: template instance test.B!int error 
instantiating

test.d(16):instantiated from here: Base!int
test.d(35):instantiated from here: A!int

Is this a bug in D?  Or am I doing something wrong?


In D, forward reference resolution should have consistent result 
for template classes and non-template ones. If the code is 
rewritten to non-template version:


import std.stdio;

class Base
{
public void Foo(A a)
{
writeln(Base.Foo(A a));
}

public void Foo(B a)
{
writeln(Base.Foo(B a));
}
};

class A : Base
{
public int v;
this(int v)
{
this.v = v;
}
}

class B : Base
{
public override void Foo(A a)
{
writeln(A: , a.v);
}
}

int main()
{
A a = new A(1);
B b = new B();

a.Foo(b);
b.Foo(a);

return 0;
}

Compiler properly resolves forward references. Therefore, it's 
definitely a compiler bug, and the template version should be 
accepted.


I filed the issue in bugzilla:
https://issues.dlang.org/show_bug.cgi?id=14083

And will open a new pull request to fix compiler.

Kenji Hara


Re: Segfault upon modifying immutable AA in static this

2015-01-24 Thread Kenji Hara via Digitalmars-d-learn

On Saturday, 24 January 2015 at 13:29:36 UTC, Nordlöw wrote:
The issue originates from module level intialization of static 
immutable AAs at


https://github.com/nordlow/justd/blob/master/conv_ex.d

Do I have to change the initialization of the AAs to be 
explicitly inline at definition of the AAs or can I preserve my 
convenient foreach over the AAs in the `static this` to 
automatically get the integer value to be stored?


Note that this does not segdefault on latest stable DMD 2.066.


It's a regression in git-head.

https://issues.dlang.org/show_bug.cgi?id=14038

Kenji Hara


Re: Initialization of structure field w/o default ctor

2015-01-22 Thread Kenji Hara via Digitalmars-d-learn

On Thursday, 22 January 2015 at 12:45:53 UTC, drug wrote:

On 22.01.2015 15:30, bearophile wrote:

drug:


Also can I avoid dummy non-default ctor for Bar?


One solution:


struct Foo {
int foo;

@disable this();

this(int foo_) pure nothrow @safe @nogc {
this.foo = foo_;
}
}

struct Bar {
enum arraySize = 3;

Foo[arraySize] foo = Foo(1);
}

void main() @safe {
import std.stdio;

Bar bar;
bar.writeln;
}


Bye,
bearophile


Yes, that's what the doctor prescribed. Thank you!


Or you can use block assignment in the constructor.

struct Bar
{
enum ArraySize = 3;

Foo[ArraySize] foo;

this(string dummy) // == here because compiler demands to 
initialize field foo

{
import std.algorithm: fill;

//fill(foo[], Foo(0));
foo[] = Foo(0);   // == OK
}
}

Compiler can recognize the block assignment as a construction for 
the field Bar.foo.


Kenji Hara


Re: Redirect to different overloads at compile time?

2014-06-29 Thread Kenji Hara via Digitalmars-d-learn

On Monday, 30 June 2014 at 02:24:10 UTC, David Bregman wrote:
Suppose I have a C library which implements a function for 
several types. C doesn't have overloading, so their names will 
be distinct.


extern(C):
double foo_double(double);
float foo_float(float);

Now I want to build a D wrapper, and merge them into a single 
function with overloading:


T foo(T)

I could write out the two overloads manually:
double foo(double d) { return foo_double(d); }
float foo(float f) { return foo_float(f); }

but this isn't compile time, it will generate a stub function 
for each overload, meaning the wrapper will have performance 
overhead unless inlining can be guaranteed somehow.


Is it possible to do something like
alias foo = foo_double;
alias foo = foo_float;


In D, you can merge arbitrary overloads by using alias 
declaration.


import std.stdio;
extern(C)
{
double foo_double(double a) { writeln(typeof(a).stringof); 
return a; }
float  foo_float (float  a) { writeln(typeof(a).stringof); 
return a; }

}

alias foo = foo_double;
alias foo = foo_float;

void main()
{
double d;
float f;
foo(d);  // prints double
foo(f);  // prints float
}

Kenji Hara


Re: Don't Understand why Phobos Auto-Tester fails for PR #3606

2014-06-07 Thread Kenji Hara via Digitalmars-d-learn

On Saturday, 7 June 2014 at 08:56:38 UTC, Nordlöw wrote:

My recent

https://github.com/D-Programming-Language/dmd/pull/3606

fails in all the Auto-Testers but I don't understand why.

Running make unittest locally in phobos using my locally built 
branch of dmd passes all tests.


Please help!


I commented in github.

Kenji Hara


Re: CTFE error, but I have no idea what it means.

2014-04-03 Thread Kenji Hara

On Monday, 31 March 2014 at 11:51:50 UTC, Olav Lindekleiv wrote:
Here's the issue: 
http://d.puremagic.com/issues/show_bug.cgi?id=12498


Fixed in git-head.

https://github.com/D-Programming-Language/dmd/commit/2c4d8ad711ccb7c94d349830523dd500580b0130

Kenji Hara


Re: template interface and delegates

2014-04-02 Thread Kenji Hara
On Tuesday, 1 April 2014 at 19:55:05 UTC, Steven Schveighoffer 
wrote:
On Tue, 01 Apr 2014 15:47:42 -0400, anonymous 
n...@trash-mail.com wrote:


Is this bug allready reported? or can somebody who has a 
deeper insight to this report it?


I don't know. I think you should report it. If it's already 
reported, someone will close it as a duplicate


-Steve


I filed it.

https://d.puremagic.com/issues/show_bug.cgi?id=12508

Kenji Hara


Re: strange compilation error

2014-03-10 Thread Kenji Hara

On Sunday, 9 March 2014 at 11:21:19 UTC, Jack Applegame wrote:

This fails to compile
http://dpaste.dzfl.pl/e9a90e808af4


It's a compiler bug.

https://d.puremagic.com/issues/show_bug.cgi?id=12334
https://github.com/D-Programming-Language/dmd/pull/3371

Kenji Hara


Re: Type inference and overloaded functions

2013-12-12 Thread Kenji Hara

On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:

Namespace:

Your gig: 
https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045


This is part of the thread there:

Furhtermore, what if we indeed want to pass a dynamic array 
?


Kenji Use cast. In real world, if overloaded function takes 
both int[] and int[3], normally int[3] version would provide 
specialized implementation for 3 length arrays (eg. unroll the 
loop to operate each elements of the given array). Therefore 
force to invoke int[] version with array literal is not usual 
situation. Cast will fit in such case.



If I have a function foo that takes a slice as input, and I 
want to pass it two arrays, the first time allocated on the 
heap and the second on the stack, I have to use an auxiliary 
variable:



void foo(int[]) {}
void main() {
foo([1, 2, 3]);
int[3] tmp = [4, 5, 6];
foo(tmp);
}


There's a known issue that the function foo takes the slice of 
stack allocated data. Today some peoples argue that it is unsafe 
operation and should be disallowed in @safe code.



With the []s syntax it should become:


void foo(int[]) {}
void main() {
foo([1, 2, 3]);
foo([4, 5, 6]s);
}


But I don't know how much common is such need.

In the Rust language when you write an array literal you always 
prefix it with a symbol, to tell the compiler where you want to 
allocate it. So I think it's not so useless :-)


Bye,
bearophile


I'm afraid that allowing foo([4, 5, 6]s) would easily cause 
memory corruption. I don't want to hurt language future by the 
trivial syntactic sugar.


Kenji Hara


Re: Type inference and overloaded functions

2013-12-10 Thread Kenji Hara
On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis 
wrote:

On Tuesday, December 10, 2013 10:10:22 Namespace wrote:
auto staticLiteral(T, size_t n)(T[n] literal)
{
return literal;
}

auto staticArray = staticLiteral([1, 2, 3, 4]);


Why do you think this is possible? If an array literal should 
match _only_ dynamic array types, it would never work.


Because compiler will try to match array literal to static array 
T[n]. The feature which I have described is working here.


Kenji Hara


Re: Type inference and overloaded functions

2013-12-10 Thread Kenji Hara

On Tuesday, 10 December 2013 at 07:32:08 UTC, Marco Leise wrote:

[1,2,3] looks like a static array to me. And if overload
resolution picked the most specialized function it seems
natural to call the int[3] version.
My reasoning being that static arrays can be implicitly
converted to dynamic array, but the reverse is not true. So I
think it would be better to have [1,2,3] be a static array and
keep the current behavoir, no?)


In early D1 age, array literals and string literals had had 
static array types which corresponding to the literals' element 
count. However it had caused template code bloat.


void foo(T)(T arg) { ... }

foo(aaa);   // instantiate foo!(char[3])
foo();  // instantiate foo!(char[4])

foo([1,2]);// instantiate foo!(int[2])
foo([1,2,3]);  // instantiate foo!(int[3])

So their types were changed to dynamic array by default.

Kenji Hara


Re: Type inference and overloaded functions

2013-12-09 Thread Kenji Hara
On Tuesday, 10 December 2013 at 07:15:43 UTC, Jonathan M Davis 
wrote:

On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:

On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
 On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
 I just found weird D behavior about inference of array 
 types.
 
 Let's suppose we have these overloaded functions:
 
 import std.stdio;
 
 void bar(const(int[3]) arr)

 {
 
   writeln(static array);
 
 }
 
 void bar(const(int[]) arr)

 {
 
   writeln(array slice);
 
 }
 
 // In main we have something like that:

 int main(string[] args)
 {
 
   bar([1,2,3]);

   writeln(typeof([1,2,3]).stringof);
   return 0;
 
 }
 
 Weird thing is that the static array version of bar is 
 called,

 but typeof().stringof is int[], not int[3].
 
 Array literals are always dynamic arrays. int[3] is a static 
 array.
 
 - Jonathan M Davis


The original question is valid then: [1,2,3] goes to the 
static array

overload.


Then AFAIK, that's a bug. The type of array literals is always 
a dynamic
array, so they should match dynamic array overloads rather than 
static array
overloads, or if they match both due to an implicit conversion, 
there should
be an ambiguity error. Choosing the static array overload over 
the dynamic one

is just plain wrong.


This is an intended behavior. An array literal has dynamic array 
type *by default*.

But all of literals in D behave as polymorphic.

char c = 'A';   // character literal has char type by default
dchar d = 'A';  // but it may be implicitly typed as wchar/dchar

string str = hello;
dstring dstr = hello;  // string literal is implicitly typed as 
dstring


int[] darr = [1,2,3];
int[3] darr = [1,2,3];   // implicitly typed as int[3]

So, an array literal [1,2,3] is implicitly convertible both to 
int[] and int[3].
And, int[3] is more specialized than int[], so overload 
resolution will choose the first 'bar'.


Kenji Hara


Re: Template condition triggers compiler error?

2013-12-01 Thread Kenji Hara

On Sunday, 1 December 2013 at 16:07:18 UTC, Namespace wrote:

This code compiles:

template gc_free(T) {
static if (is(T : U*, U) || is(T : U[], U))
alias Type = T;
else
alias Type = T*;

void gc_free(Type data) {
import core.memory : GC;

static if (is(Type : U[], U)) {
GC.free(data.ptr);
GC.minimize();
} else {
GC.free(data);
}

data = null;
}
}


But with a template condition it triggers compiler errors:

template gc_free(T) if (!is(T == class)) {
static if (is(T : U*, U) || is(T : U[], U))
alias Type = T;
else
alias Type = T*;

void gc_free(Type data) {
import core.memory : GC;

static if (is(Type : U[], U)) {
GC.free(data.ptr);
GC.minimize();
} else {
GC.free(data);
}

data = null;
}
}


Errors:
share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type
share.d(177): Error: template instance share.share!(A) error 
instantiating

share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type
share.d(197): Error: template instance share.share!(A) error 
instantiating

share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type
share.d(10): Error: undefined identifier Type

It seems to work on Linux with 64 bit, but it fails on Windows 
7 32 bit.


Bug, feature or my fault?


Compiler bug.

https://d.puremagic.com/issues/show_bug.cgi?id=11662

Kenji Hara


Re: alias this leads to compilation error in one of two similar contexts

2013-12-01 Thread Kenji Hara
On Saturday, 30 November 2013 at 22:28:14 UTC, Carl Sturtivant 
wrote:


I just confirmed the same behavior on Ubuntu amd64. dmd 2.063.2 
compiles the example and dmd 2.064.2 produces the same error as 
the Windows 32 bit version.


This is intended behavior change from 2.064.

http://dlang.org/class#field-init

struct my_integer {
int val = 99;
alias val this;
}
void test() {
  //my_interger num = 1;  // NG
my_interger num = my_interger(1);  // OK
// 'alias this' has no effect for object initialization
}
struct blah {
my_integer num;

this(int n) {
  //num = n;  // also NG, my_integer cannot *initialize* by 
int value

num = my_interger(n);  // OK
}
}

Kenji Hara


Re: Function literal bug?

2013-11-28 Thread Kenji Hara

On Thursday, 28 November 2013 at 09:48:47 UTC, bearophile wrote:

Sergei Nosov:


Do you have a 64-bit OS at hand?


On 64 bit using dmd 2.064.2 it doesn't give the 6 6 output, so 
it seems a 64 bit bug. This happens because the 64 bit version 
of dmd is quite more new than the 32 bit version, so it has 
more bugs.


Bye,
bearophile


It's a known front-end issue.

https://d.puremagic.com/issues/show_bug.cgi?id=11545

Kenji Hara


Re: casting as char at CT fail

2013-11-27 Thread Kenji Hara
On Tuesday, 26 November 2013 at 23:31:16 UTC, bioinfornatics 
wrote:

Hi,
this time i have so many question about CT …
iws and ibuclaw help me for this.

I stuck currently about a cast at CT - 
http://www.dpaste.dzfl.pl/1a28a22c


it seem this should works but not…
So if you confirm maybe a report is needed

thanks to everyone


I found two compiler issues:

https://d.puremagic.com/issues/show_bug.cgi?id=11627
https://d.puremagic.com/issues/show_bug.cgi?id=11629

Kenji Hara


Re: pure-ifying my code

2013-11-20 Thread Kenji Hara
On Monday, 18 November 2013 at 19:52:42 UTC, Jonathan M Davis 
wrote:

On Monday, November 18, 2013 19:16:11 Daniel Davidson wrote:

On Sunday, 17 November 2013 at 10:56:16 UTC, Jonathan M Davis

wrote:
 I think that the typical approach at this point is to just 
 drop

 purity for the
 moment, but if you want you really want it, you are indeed
 going to have to
 implement it yourself. But we'll get there with Phobos
 eventually. The primary
 holdup is some compiler improvements, and we'll get them. 
 It's

 just a question
 of when.
 
 - Jonathan M Davis


Why is it that compiler improvements are the holdup? Honest
question. Is it more that the approach taken for the specific
implementation went beyond the capabilities of the compiler at
the time (like its inferencing capabilities)? Maybe purity was
not a focus at the time of writing a lot of phobos and there 
are

not loads of testing on it where purity was a factor.


Attribute inferrence was added to the language specifically in 
order to make it
possible for pure, nothrow, and @safe to work with templates 
and therefore
make it possible to use them with Phobos. Without it, they 
don't, because
you're stuck either requiring a specific set of attributes 
(limiting what the
templates work with) or duplicating the templates with 
different combinations
of attributes. We got enough attribute inferrence to reduce the 
problem, but
the feature has yet to be implemented enough to fully fix the 
problem. It's
compiler improvements which made using pure with std.algorithm 
possible at

all.


If so,
isn't an alternative implementation now an improvement over
waiting for the compiler updates. A corollary question would be
are the benefits of Voldermort types in phobos worth the purity
issues they cause?


Voldemort types are just part of the problem. Attribute 
inferrence is just
plain too primitive right now, and really needs to be improved. 
The problem is

reduced if you don't used Voldemort types, but it's not fixed.


Noble goal - maybe. But maybe not as noble as users' efforts to
realize benefits of purity now. Purity/const/immutable when
broken spread virally.


It's also the case that none of that has ever worked with pure, 
so we haven't
lost anything. We just haven't yet gained what we should have 
gained. But the
push really needs to be to improve the compiler IMHO, because 
without that,
attribute inferrence in general just isn't going to be good 
enough, and if
Phobos' current situation highlights how poor the attribute 
inferrence is, all

the better, because that puts more pressure on getting it fixed.

Some of the newer functions have not used Voldemort types in 
order to fix
similar problems, but I don't think that it's worth going and 
changing them
all just to work around a problem with the compiler. The 
compiler needs to be
fixed. At best, what you're talking about doing is contorting 
Phobos'
implementation in order to make it work better with the 
half-implemented
feature of attribute inferrence, but since it's that feature 
that makes it
possible at all, and it really needs to be fully implemented 
regardless, it
makes by far the most sense IMHO to just finish implementing 
it. But when that
happens is up to the compiler devs, and at this point, I'm a 
library dev, not

a compiler dev.

- Jonathan M Davis



I opened a new pull request to fix the compiler issue.

https://github.com/D-Programming-Language/dmd/pull/2832

Kenji Hara


Re: Calling Base Class Overriden Methods

2013-11-18 Thread Kenji Hara

On Monday, 18 November 2013 at 19:36:07 UTC, Jeroen Bollen wrote:
On Monday, 18 November 2013 at 19:34:56 UTC, Adam D. Ruppe 
wrote:

To do it from outside the class, you write the class name:

void main() {
   auto obj = new SubClass();
   obj.SuperClass.methodA(); // calls the specific super 
method

}


Thanks! :D

Why aren't these things in the documentation? :/


http://dlang.org/function#virtual-functions
=

To avoid dynamic binding on member function call, insert base 
class name before the member function name. For example:


...


void main() {
  auto d = new D();
  assert(d.foo() == 3);// calls D.foo
  assert(d.B.foo() == 1);  // calls B.foo
  assert(d.C.foo() == 2);  // calls C.foo
  d.test();
}

=

Kenji Hara


Re: dchar literals?

2013-11-12 Thread Kenji Hara

On Monday, 11 November 2013 at 13:20:04 UTC, bearophile wrote:

Philippe Sigaud:

And I agree with you than character literals should default to 
dchar. It's

a perpetual source of friction for me.


99% of my char literals need to be of type char.

On the other hand once you have suffixes to specify the char 
type, most of that problem vanishes, because writing 'x'c or 
'x'w, 'x'd is good.


Bye,
bearophile


Or, uniform construction for built-in types would be another 
better way.


auto c = char('a');
auto w = wchar('a');
auto d = dchar('a');

auto x = char('à');   // compile-time error

Kenji Hara


Re: Bug in RefCounted?

2013-10-29 Thread Kenji Hara
On Tuesday, 29 October 2013 at 11:46:53 UTC, Rene Zwanenburg 
wrote:

On Monday, 28 October 2013 at 19:30:12 UTC, Maxim Fomin wrote:

Here is my attempt:

import std.stdio;

struct S
{
  int i;
  this(int i)   { writefln(ctor, %X, i); this.i = i; }
  this(this)  { writefln(postblit, %X, %X, this, i); }
  ~this() { writefln(dtor, %X, %X, this, i); }
}

auto foo()
{
  S s = S(1);
  return { s = S(2); } ;
}

void main()
{
  foo()();
}

ctor, 1
dtor, 77ED8FF8, 1
ctor, 2
dtor, 7FFFDB30, 1

Inside foo() function object 's' is destroyed twice: first 
time as a regular struct at the end of block scope, second 
time before assigning S(2).


There are other tools: union bug, control flow tricks, 
__traits, __dtor but they are move obvious.


That's pretty nasty :). But I suspect this is a bug and not by 
design. __dtor and __traits are, IMHO, the proverbial escape 
hatch D should provide, so I think that's OK. I take it that by 
control flow trick you mean the try/catch example in your other 
post?


Anyway, thanks for pointing this out. Will probably save me 
some debugging in the future.


The combination of closure variables + scoped destruction should 
be rejected, but currently it isn't. It's a compiler bug.


http://d.puremagic.com/issues/show_bug.cgi?id=11382

Kenji Hara


Re: Templates with alias param instantiated with null cached by DMD..?

2013-10-23 Thread Kenji Hara

On Wednesday, 23 October 2013 at 07:22:56 UTC, simendsjo wrote:
I've stumbled upon a strange bug, and I'm not sure what I 
should write in the bug report. Could someone explain what's 
going on here or file the bug for me?


template A(alias T) {
alias A = T;
}

void main() {
struct S1 { S1* p; }
static assert(is(typeof(A!(S1.init.p)) == S1*)); // ok

pragma(msg, NULL: , typeof(A!(null))); // fail: S1*

struct S2 { S2* p; }
static assert(is(typeof(A!(S2.init.p)) == S2*)); // fail: 
S1*

}


A!(S1.init.p) is mostly same as A!( cast(S1*)null ), because the 
expression S1.init.p is interpreted to a null value.


1. But current ABI does not support a typed null template value 
argument because all of null expression on template argument are 
mangled to 'n'. So the type of null value will be never encoded 
in the mangled name, and the three instantiations A!(S1.init.p), 
A!(null) and A!(S2.init.p) will have exactly same mangling.


2. However, the first instantiation A!(S1.init.p) wrongly caches 
the null value type (== S1*), and it appears in following 
instantiations during semantic analysis phase.


#2 is definitely a front-end bug. However I'm not sure the 
current ABI definition issue (== #2) is a language spec bug or 
not...


Kenji Hara


Re: cannot call impure function ~this

2013-10-17 Thread Kenji Hara

On Wednesday, 16 October 2013 at 07:58:09 UTC, Namespace wrote:
On Wednesday, 16 October 2013 at 07:32:27 UTC, monarch_dodra 
wrote:

On Wednesday, 16 October 2013 at 07:27:25 UTC, Namespace wrote:
On Wednesday, 16 October 2013 at 07:23:45 UTC, monarch_dodra 
wrote:

On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote:

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot 
call impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


It could have something to do with the fact that RVO is an 
optimization *opportunity* that the compiler is allowed to 
go for, even if it changes the program output.


Hoewever, being an *opportunity*, the compiler still has to 
make sure the code is valid without said optimization, which 
in this case, isn't: getA would destroy it's temporary after 
blitting it on the stac, leading to an impure call.


So it _could_ be impure, but mostly it isn't, right?


I guess that's one way to put it. I'd say it *is* impure, but 
all its impure bits have been optimized out. That's my 
explanation anyways.


I'm curious: Is this a problem for you? The function calling 
getA *can't* be pure either, so marking getA as pure is ...


I was going to say useless, but I guess pure is always an 
optimization opportunity for the compiler.


I'd file an ER, you never know.
No, I was just curious what's behind it. So specifically why 
the compiler could call the destructor.


In this case, the created struct literal A() will be moved out to 
the function getA(). So dtor is not called and compiler should 
not cause cannot call impure function error.


I filed a bug report and posted possible compiler fix.

http://d.puremagic.com/issues/show_bug.cgi?id=11286
https://github.com/D-Programming-Language/dmd/pull/2677

Kenji Hara


Re: copying const struct

2013-10-14 Thread Kenji Hara

On Monday, 14 October 2013 at 14:18:10 UTC, Maxim Fomin wrote:
On Monday, 14 October 2013 at 11:35:32 UTC, Jack Applegame 
wrote:

Why this doesn't compile?

http://dpaste.dzfl.pl/21ef5b04

class Foo {}

struct Bar1 {
const(Foo[]) member;
}

struct Bar2 {
const Foo member;   
}

void main() {
const Bar1 bar1;
const Bar2 bar2;
Bar1 b1 = bar1; // ok
	Bar2 b2 = bar2; // cannot implicitly convert expression 
(bar2) of type const(Bar2) to Bar2

}


This is compilable using git head.


Recently I found a small compiler bug.
http://d.puremagic.com/issues/show_bug.cgi?id=11187

And, a week ago it is fixed. 2.064 beta1 contains the fix.

Kenji Hara


Re: Phobos - pure, const, safe, nothrow

2013-10-02 Thread Kenji Hara
On Wednesday, 2 October 2013 at 13:31:04 UTC, Joseph Rushton 
Wakeling wrote:

On 29/09/13 11:37, monarch_dodra wrote:

On Sunday, 29 September 2013 at 09:00:56 UTC, simendsjo wrote:
What is the status of adding these annotations to phobos? 
It's difficult to
use these until phobos gets them. E.g. to! and format is not 
pure.


Most of phobos is templated, meaning it relies on inference.


In various recent template-related explorations I have often 
wished it was possible to infer function attributes from 
template arguments  :-(


See e.g. Proxy, which loses all the corresponding attributes of 
the underlying type's methods.


std.typecons.Proxy is designed to work transparently for the 
underlying method qualifiers. But I also agree that the 
implementation is still insufficient.


Could you show us the not working case? It would be much help.

Kenji Hara


Re: Mixin namespace ambiguity?

2013-09-15 Thread Kenji Hara
On Sunday, 15 September 2013 at 18:31:30 UTC, Marek Janukowicz 
wrote:

The code to reproduce the problem consists of 3 modules:

mix.d:

module mix;

mixin template A( alias x) {

  string a () {
return x;
  }
}


aux.d:

module aux;

import mix;

mixin A!(a in aux) X;
string b () { return b in aux; }


main.d:

module main;

import aux;
import mix;
import std.stdio;

mixin A!(a in main) X;
string b () { return b in main; }

void main () {
  writefln( a: %s, X.a );  // Line 1
  //writefln( a: %s, a );  // Line 2
  writefln( b: %s, b ); // Line 3
}

I run it with: dmd -run main.d aux.d mix.d

Line 1 works. Line 3 works. Line 2 fails with:
main.d(13): Error: main.A!(a in main).a at mix.d(5) conflicts 
with aux.A!

(a in aux).a at mix.d(5)

If I omit mixin identifier (X), there is no way I can make 
the call to a

work without prepending module name.

My question is: why calling a function with the same name (from 
different

modules) works when:
- it is just a regular function
- it is a mixed-in function with mixin identifier (even though 
the

identifier is ambiguous)

and it doesn't when it's a mixed-in function with no mixin 
identifier.


My first impression is that either both line 1 and 2 should 
work or neither
of them should work. It's no surprise to me that line 3 works 
(and it
matches the documentation), so I basically included that just 
for reference.


Currently this is not a bug.

Looking from the module 'main', the mixin identifier 'X' declared 
in main.d is *closer* than the 'X' declared in aux.d, because the 
latter exists beyond the module import boundary.
Therefore, the use of 'X' in main.d would prefere the `mixin 
A!(a in main) X`.


On the other hand, when the name search, all mixed-in symbols are 
treated as if they are just imported at the mixed-in scope.
Therefore, even from main.d, the two mixed-in functions 'a' have 
same closeness, and the call is ambiguous because they have 
exactly same signature.


Kenji Hara


Re: Limited type matching?

2013-09-10 Thread Kenji Hara

On Tuesday, 10 September 2013 at 08:04:48 UTC, Namespace wrote:
Currently, all of array types does not allow copy-conversion 
like ushort to short for their elements.


In old D1 age, static array did not have value semantics, so 
the behavior was expected.
In D2, static array had changed to value type, but the 
behavior was not changed.


As far as I know, there was no discussion about that, but at 
least it is not fundamentally wrong.


Kenji Hara


And what is your personal opinion?
I think an implicit cast between signed / unsigned would be 
acceptable even with static arrays. It were only logical.


Hmm, OK. I've taken a look a little deeper about the current 
behavior.


void main()
{
void f1(short) {}
void f2(short[2]) {}
void f3(short[]) {}

ushort us = 1;
short ss = us;  // OK
ss = us;// OK
f1(us); // OK

ushort[2] usa = [1,2];
short[2] ssa = usa; // OK - [x]
ssa = usa;  // NG - [y]
f2(usa);// NG - [y]

ushort[] uda = [1,2];
short[] sda = uda;  // NG, expected
sda = uda;  // NG, expected
f3(uda);// NG, expected
}

Surely the current state that, [x] is accepted but [y] is 
rejected, looks weird to me. It would be a bug.


Kenji Hara


Re: Limited type matching?

2013-09-09 Thread Kenji Hara
On Monday, 9 September 2013 at 11:36:42 UTC, Andrej Mitrovic 
wrote:

On 9/8/13, Namespace rswhi...@googlemail.com wrote:

What is the problem? If the compiler is able to cast implicit
from ushort to short, what is the problem of casting ushort[2] 
to

short[2]?


Oh I didn't even noticed it was a signed/unsigned issue. I'm 
not sure
whether or not it's a bug. But file it anyways and someone will 
know

what to do with it.


Currently, all of array types does not allow copy-conversion like 
ushort to short for their elements.


In old D1 age, static array did not have value semantics, so the 
behavior was expected.
In D2, static array had changed to value type, but the behavior 
was not changed.


As far as I know, there was no discussion about that, but at 
least it is not fundamentally wrong.


Kenji Hara


Re: Struct with opDispatch doesn't dispatch. Is this a bug?

2013-07-05 Thread Kenji Hara

On Friday, 5 July 2013 at 03:12:44 UTC, Meta wrote:

I wasn't 100% sure the following is a bug, so I figured I'd ask.

struct Fail
{
void opDispatch(string s)()
{
static assert(false, Tried to call a method on Fail);
}
}

void main()
{
auto fail = Fail();
fail.s(); //Error: no property 's' for type 'Fail'
}


This is a compiler's diagnostic bug.
http://d.puremagic.com/issues/show_bug.cgi?id=10546

In this case, opDispatch is _actually_ instantiated. However the 
static assertion message is suppressed for later UFCS symbol 
search.
But UFCS cannot find module level function 's', then compiler 
reports irrelevant error message no property 's'


Kenji Hara


Re: How to determine if a function is implemented

2013-07-05 Thread Kenji Hara

On Friday, 5 July 2013 at 01:27:06 UTC, JS wrote:

the code

http://dpaste.dzfl.pl/25bfeeb7

attempts to implement an interface. The current issue is that I 
need to determine if the user has added the member of the 
interface to the class or if the mixin needs to add it.



so the lines

class B : A
{
A a;

//void myfunc(float a, int b, string c) { };
//@property int myvalue() { return 4; }
mixin implementInterface!a;
}

The mixin adds the two commented functions above it which 
effectively implement the interface A in B. The problem is, I 
might want to manually specify one, e.g.,



class B : A
{
A a;

void myfunc(float a, int b, string c) { };
//@property int myvalue() { return 4; }
mixin implementInterface!a;
}

So the mixin needs to be aware and not add a method that is 
already implemented.
I need some way for the mixin to distinguish the two cases 
above. e.g., isImplemented!(myfunc(float, int, string)) or 
something like that.


It's completely unnecessary. A mixed-in function cannot override 
properly declared function that has same name in the mixed-in 
scope.



interface I { int foo(); }

mixin template Foo()
{
override int foo() { return 1; }
}

class C1 : I {
mixin Foo!();
}

class C2 : I
{
int foo() { return 10; }
mixin Foo!();
// mixed-in foo is not stored in vtbl
}

void main()
{
assert(new C1().foo() == 1);
assert(new C2().foo() == 10);
}

Kenji Hara


Re: opDispatch and UFCS

2013-07-02 Thread Kenji Hara

On Tuesday, 2 July 2013 at 00:45:23 UTC, cal wrote:

import std.conv, std.stdio, std.algorithm;

struct S {
void opDispatch(string s, T...)(T t) if 
(s.startsWith(foo)) {

writeln(s);
}
}

void main() {
S s;
s.foo();
auto p = s.to!string(); // Error: s.opDispatch!(to) isn't 
a template

}

Should the constraint on opDispatch allow the UFCS to call on 
S?


That's a compiler bug.
http://d.puremagic.com/issues/show_bug.cgi?id=10526

Kenji Hara


Re: Strange error when importing std.regex

2013-06-13 Thread Kenji Hara

On Wednesday, 12 June 2013 at 18:44:12 UTC, bearophile wrote:

Dmitry Olshansky:

There is no ambiguity, 1 is not a Regex object but it seems 
like template constraint in std.regex blows up.


@Temtaime please file a bug on this.
http://d.puremagic.com/issues/

std.algorithm.splitter(arr, 1);


I think this bug already surfaced some time ago... Maybe it's 
already in Bugzilla.


Bye,
bearophile


Right now I cannot see the original code in dpaste, but the issue 
would be a same bug with 8352.

http://d.puremagic.com/issues/show_bug.cgi?id=8352

I have maintained a compiler fix for that, but unfortunately it 
is not yet merged.

https://github.com/D-Programming-Language/dmd/pull/1660

Kenji Hara


Re: Clarification of @trusted attribute?

2013-06-13 Thread Kenji Hara

On Wednesday, 12 June 2013 at 13:09:40 UTC, Gary Willoughby wrote:
So would you mark the following with @trusted? The format() 
function is not @safe but what is @trusted really trying to 
say? This method is @safe as far as i'm concerned? The 
arguments make format() @safe? I'm confused.


/**
 * Get the current timestamp for the log.
 *
 * Returns:
 * The current timestamp.
 */
private string getTimestamp() const
{
auto time = Clock.currTime();
		return format(%d/%02d/%02d %d:%02d:%02d, time.year, 
time.month, time.day, time.hour, time.minute, time.second);

}


In this case, format std.string.format function should work under 
the `safe annotation.


I recently worked to make it possible.
https://github.com/D-Programming-Language/phobos/pull/1337

Kenji Hara


Re: How to implement this?

2013-06-10 Thread Kenji Hara

On Monday, 10 June 2013 at 09:42:56 UTC, Elvis wrote:

class A
{
enum TypeID = 1;
}
class B : A
{
enum TypeID = 2;
}

class C : A
{
enum TypeID = 3;
}

class D : B
{
enum TypeID = 4;
}

...


Could anybody shed some light on how to make these TypeIDs auto 
increment at compile time?


version(A)
{
class A
{
 enum TypeID = 1;
}

template IncrementTypeID(Class)
{
class IncrementTypeID : Class
{
enum TypeID = Class.TypeID + 1;
}
}
alias B = IncrementTypeID!A;
alias C = IncrementTypeID!B;
alias D = IncrementTypeID!C;
}
version(B)  // more generative way
{
template MakeContinuousClasses(int endID)
{
static if (endID  0)
{
mixin MakeContinuousClasses!(endID - 1);

enum className = ABCDEFGHIJKLMNOPQRSTUVWXYZ[endID - 
1];

static if (endID == 1)
enum baseClass = ;
else
enum baseClass =  :  ~ 
ABCDEFGHIJKLMNOPQRSTUVWXYZ[endID - 2];


import std.conv : to;
mixin(class ~className~baseClass~ { enum TypeID = 
~endID.to!string~; });

}
}
mixin MakeContinuousClasses!4;
}

// test case
import std.traits;
pragma(msg, A.TypeID, , , BaseClassesTuple!A);  // 1, (Object)
pragma(msg, B.TypeID, , , BaseClassesTuple!B);  // 2, (A, 
Object)
pragma(msg, C.TypeID, , , BaseClassesTuple!C);  // 3, (B, A, 
Object)
pragma(msg, D.TypeID, , , BaseClassesTuple!D);  // 4, (C, B, A, 
Object)


Kenji Hara


Re: Compiler bug ?

2013-06-09 Thread Kenji Hara

On Sunday, 9 June 2013 at 13:37:45 UTC, Temtaime wrote:

Hello guys!

It seems that it is bug. And critical for me.
http://dpaste.1azy.net/b93f5776

Regards.


The code should be rejected. It's a compiler bug.
But, you can do what you want as follows.

import std.stdio, std.typetuple;

struct A {
@(1) int a;
@(2) int b;
@(3) int c;
}

auto bar(alias expr)() @property {
writeln(expr);
}

void main() {
A a;

foreach(it; __traits(allMembers, A))
{
enum tp = [__traits(getAttributes, mixin(`a.` ~ it))];
// or
alias tp = TypeTuple!(__traits(getAttributes, mixin(`a.` 
~ it)));


writeln(`passing: `, tp[0]);
bar!(tp[0])();
}
}

Kenji Hara


Re: Is this a compiler bug, or a breaking fix/enhancement?

2013-05-29 Thread Kenji Hara

On Wednesday, 29 May 2013 at 04:44:16 UTC, estew wrote:

Hi All,

I updated to dmd 2.063 today and all has been going smoothly 
until I decided to try out msgpack.d. I got an error compiling 
the msgpack.d unittest, so out of interest I decided to check 
this using dmd2.062 and it compiled and ran fine.


I admit I don't really understand whether the code should work 
or if it is broken and dmd 2.063 now correctly issues an error. 
To my untrained-D-eye the code looks OK, so any advice would be 
appreciated.



ERROR:
---
msgpack.d(3215): Error: cannot resolve type for value.as!(E).

EXAMPLE:
---
import std.stdio;
import std.traits;

enum E : int {F = -20}
struct S {
int val;
@trusted @property T as(T)()
if(is(Unqual!T == int)  !is(Unqual!T == enum))
{
return cast(T)(val);
}
@trusted @property T as(T)()
if(is(Unqual!T == enum))
{
return cast(T)as!(OriginalType!T);
}
}

void main() {
S val = S(-20);
assert(val.as!int == -20);
assert(val.as!E == E.F); // val.as!E causes a compile time 
error.

}
---


This is a compiler regression in 2.063 release.
http://d.puremagic.com/issues/show_bug.cgi?id=10197

Kenji Hara


Re: static const and user attribute

2013-05-29 Thread Kenji Hara

On Wednesday, 29 May 2013 at 14:50:36 UTC, bearophile wrote:

Dicebot:


I think this is a bug.


It will be fixed progressively in the next two or three DMD 
versions.


Bye,
bearophile


Please file it in bugzilla.

Kenji Hara


Re: Two questions about assignments

2013-05-27 Thread Kenji Hara

On Monday, 27 May 2013 at 18:00:38 UTC, bearophile wrote:
Do you know if it's OK to accept x3 assignment and refuse the 
a2 assignment?



struct Foo {
immutable(char)[4] bar;
}
Foo x1 = { AA };// No error.
immutable(char)[4] a1 = AA; // No error.
void main() {
Foo x2 = { AA };// No error.
Foo x3 = Foo(AA);   // No error.
immutable(char)[4] a2 = AA; // Error: lengths don't match
  // for array copy, 4 = 2
}


This is known static array initializing inconsistency between 
DeclDefs scope and statement scope. I think it is a bug.



-

This is a recent change in std.typecons.tuples:

// 
https://github.com/9rnsr/phobos/commit/fdcaba7226c978f281f2d237fc772c6d7913eaf3



But from this test they don't seem to be one a subtype of the 
other:



import std.typecons: Tuple;
void main() {
alias T1 = Tuple!(int, int);
alias T2 = Tuple!(int,x, int,y);
auto t1 = T1(10, 20);
auto t2 = T2(100, 200);
t1 = t2; // OK.
t2 = t1; // OK?
}


std.typecons.Tuple supports structural assignment before the 
change.

The code also works with 2.062.

Kenji Hara


Re: Two questions about assignments

2013-05-27 Thread Kenji Hara

On Tuesday, 28 May 2013 at 00:29:04 UTC, bearophile wrote:
std.typecons.Tuple supports structural assignment before the 
change.

The code also works with 2.062.


I know it's not a regression. But you say:
Named-field tuple should be a subtype of unnamed-field tuple.

You can have sub-typing, or you can have structural typing, but 
mixing the two silently seems a mess.


Also in your test cases of that commit fdcaba7226c... there is:

+Tuple!(int, int)[] arr;
+arr ~= tuple(10, 20); // OK
+arr ~= Tuple!(int, x, int, y)(10, 20); // NG - OK

If I try to do the opposite, that is to append a tuple(10, 20) 
to an array of tuples with named fields, I get an error:


import std.typecons;
void main() {
Tuple!(int, x, int, y)[] arr;
arr ~= tuple(10, 20); // Error.
}


So here there is a true sub-typing. So sometimes tuples with 
named fields are sub-types and in other situations they act in 
a structural typing way. I think this mix of behaviours is a 
little confusing.


Basically Tuple would follow structural typing. Even if it is 
impossible, it would follow true subtyping right now. That's the 
purpose of my change.


Kenji Hara


Re: Scoped import bug?

2013-05-09 Thread Kenji Hara

On Thursday, 9 May 2013 at 05:01:15 UTC, Mike Linford wrote:
I'm not sure whether or not I've encountered a bug or whether 
my understanding of scoped imports is just faulty.


blah.d:

  1 module blah;
  2
  3 version(A)
  4 {
  5import std.range;
  6 }
  7
  8 struct Blah(R)
  9 {
 10version(B)
 11{
 12   import std.range;
 13}
 14static assert(isInputRange!R);
 15
 16void blah(R r)
 17{
 18   version(C)
 19   {
 20  assert(r.front == 'h');
 21   }
 22}
 23 }
 24
 25 void main()
 26 {
 27Blah!string blah;
 28blah.blah(hello);
 29 }

Results:
rdmd -version=A -version=C blah
Compiles fine. Module-level import works for the static assert 
on line 14 and the runtime assert on line 20


rdmd -version=B blah
Compiles fine! Struct-level import works for the static assert 
on line 14


rdmd -version=B -version=C blah
Fails to compile. I get the following error messages:
blah.d(20): Error: no property 'front' for type 'string'
blah.d(27): Error: template instance blah.Blah!(string) error 
instantiating


So it appears that when my import is at the struct level like 
line 12 I'm able to use the static assert but *not* the runtime 
assert. Why cant the function Blah.blah() find the array 
implementation of front?


This is a known UFCS name look-up issue.
In 2.063dev, the bug is fixed. Please wait the release.

Kenji Hara


Re: Template alias parameter does not accept types

2013-05-09 Thread Kenji Hara

On Thursday, 9 May 2013 at 12:09:03 UTC, Dicebot wrote:

On Thursday, 9 May 2013 at 11:19:38 UTC, bearophile wrote:

It will be fixed.


Ugh, proof-link? I have always thought it is by design and that 
actually makes sense.


AFAIK, there is no plan for fix. The behavior is currently a part 
of language design.


Kenji Hara


Re: Scoped import bug?

2013-05-09 Thread Kenji Hara

On Thursday, 9 May 2013 at 18:25:39 UTC, Mike Linford wrote:

On Thursday, 9 May 2013 at 09:52:12 UTC, Kenji Hara wrote:

On Thursday, 9 May 2013 at 05:01:15 UTC, Mike Linford wrote:
I'm not sure whether or not I've encountered a bug or whether 
my understanding of scoped imports is just faulty.


blah.d:

1 module blah;
2
3 version(A)
4 {
5import std.range;
6 }
7
8 struct Blah(R)
9 {
10version(B)
11{
12   import std.range;
13}
14static assert(isInputRange!R);
15
16void blah(R r)
17{
18   version(C)
19   {
20  assert(r.front == 'h');
21   }
22}
23 }
24
25 void main()
26 {
27Blah!string blah;
28blah.blah(hello);
29 }

Results:
rdmd -version=A -version=C blah
Compiles fine. Module-level import works for the static 
assert on line 14 and the runtime assert on line 20


rdmd -version=B blah
Compiles fine! Struct-level import works for the static 
assert on line 14


rdmd -version=B -version=C blah
Fails to compile. I get the following error messages:
blah.d(20): Error: no property 'front' for type 'string'
blah.d(27): Error: template instance blah.Blah!(string) error 
instantiating


So it appears that when my import is at the struct level like 
line 12 I'm able to use the static assert but *not* the 
runtime assert. Why cant the function Blah.blah() find the 
array implementation of front?


This is a known UFCS name look-up issue.
In 2.063dev, the bug is fixed. Please wait the release.

Kenji Hara


Thank you for the explanation. Was this the issue? 
http://d.puremagic.com/issues/show_bug.cgi?id=6185


Yes, that's right!

Kenji Hara


Re: Using inout in delegate

2013-04-02 Thread Kenji Hara
On Thursday, 28 March 2013 at 14:16:27 UTC, Steven Schveighoffer 
wrote:
On Thu, 28 Mar 2013 04:34:36 -0400, Jacob Carlborg 
d...@me.com wrote:



The following code fails to compile:

void foo (inout int[] arr)
{
auto dg = {
foreach (i, e ; arr) {}
};
dg();
}

void main ()
{
auto a = [3, 4, 5];
foo(a);
}

Error message:

main.d(9): Error: variable main.foo.__lambda1.__aggr1174 inout 
variables can only be declared inside inout functions
main.d(9): Error: variable main.foo.__lambda1.e inout 
variables can only be declared inside inout functions


If I remove the delegate everything compiles. Am I doing 
something wrong?




Like Timon said, it's a bug in inout design.


I think this is not a hole of inout design. In this case, the 
lambda inside foo should capture 'inout' context pointer.


void foo (inout int[] arr)
{
auto dg = {
foreach (i, e ; arr) {}
};
pragma(msg, typeof(dg));  // should print void delegate() 
inout

dg();
}

I'm assuming the issue is that the compiler is trying to 
generate a struct to hold the stack data for foo, and struct 
members cannot be inout.


It is true, but in this case, the context which is implicitly 
captured by closure is not directly accessible from programmers. 
So qualifying it 'inout' is safe.


It is a difficult problem to solve, because inout has two 
meanings depending on whether it is a parameter/return or a 
local variable.  At some point, we need to address this, 
because inout has so much potential, but suffers from some 
large deficiencies.


And, inout closure cannot escape from enclosing inout function.

auto foo(inout int[] arr)
{
auto dg = (inout int[] a)
{
return arr;   // returns captured inout 'arr'
};
return dg;  // escape! (should be rejected statically)
}

If compiler does not reject escape...

void main()
{
const int[] a = [3, 4, 5];
auto dg = foo(a);
// typeof(dg) == inout(int[]) delegate(inout(int[]))
int[] b = dg([]);
assert(b.ptr == a.ptr);  // type-system breaking!
}

Kenji Hara


Re: isExpression with bool template parameter

2013-03-28 Thread Kenji Hara

On Tuesday, 26 March 2013 at 14:26:59 UTC, cal wrote:
I guess the tuple version is fine, it is just surprising that 
only one of the three parameter types can be directly matched. 
It is also surprising that this example from the docs works:


Because 'Tuple' is a template, not a type.
Please recall that:

struct Tuple(T...) { ... }

is a syntactic sugar of:

template Tuple(T...) { struct Tuple { ... } }


alias Tuple!(int, string) Tup;
static if (is(Tup : TX!TL, alias TX, TL...))

(matching an alias) but the alias can't be directly matched 
when it appears as a parameter of the type.


So, `alias TX` will bind the template Tuple. There is no problem.

Kenji Hara


Re: using this instead of typeof(this)

2013-02-26 Thread Kenji Hara

On Tuesday, 26 February 2013 at 16:28:59 UTC, Ivan Kazmenko wrote:

Hi!

I have recently experimented with ways to express the exact 
instantiated type of a generic struct, and found that I can in 
some cases use this as that type.


Here is a sample program (DMD 2.062) demonstrating various uses 
of this as a type:


-
import std.stdio;

struct S
{
int x = 1;
int y = 0;

void f ()
{
y = 1;
}

this (this) // postblit constructor
{
x = 10;
}

this (ref this) // not a postblit constructor
{
x = 100;
}

this (ref this, this f, typeof (this), this, ref this g)
{
x = 1000 + _param_0.x + f.x + _param_2.x + _param_3.x + g.x;
}
}

void main ()
{
S a;
a.f ();
S b = a;
S c = S (a);
S d = S (a, a, a, a, a);
writefln (%s %s, a.x, a.y); // 1 1
writefln (%s %s, b.x, b.y); // 10 1 (copied b.y = a.y)
writefln (%s %s, c.x, c.y); // 100 0 (did not copy)
	writefln (%s %s, d.x, d.y); // 1032 0 (refs add 1, non-refs 
add 10)

}
-

And so I wonder:

(1) Should I refrain from using this as a type, is it a bug?


It is definitely a bug. I cannot believe that such horrible bug 
is still there.

If you have a time, could you please file it in bugzilla?

http://d.puremagic.com/issues/

(2) A matter of style: what is the idiomatic way to take the 
exact type of a templated struct? For example, which method 
signature to return a typeof(this) value is better in which 
way if all have the same effect:

-
struct S (A, B, C)
{
...
auto method () {...}
S method () {...}
S !(theA, theB, theC) method () {...}
typeof (this) method () {...}
}
-
Note that S, theA, theB and theC can get lengthy.


Returning S, S!(...), and typeof(this) are identical. You can use 
them as you favorite.
auto return is a little different with others. To infer return 
type, the method body is aggressively analyzed in compilation. If 
the method has mutual call with another auto return function, it 
will cause 'forward reference error'.


(3) Is the usage of unnamed parameters and _param_### a 
language feature or an implementation-specific detail I should 
not ever use?


It is implementation specific. You must not rely on that.

Kenji Hara


Re: Delegate type inferred as pure

2013-01-28 Thread Kenji Hara

On Monday, 28 January 2013 at 03:16:24 UTC, cal wrote:

This fails:

void main() {
int z;
typeof((int a){return z;}) dg;
dg = (int a) {return z;};
}

Error: cannot implicitly convert expression (__lambda2) of type 
int delegate(int a) nothrow @safe to int delegate(int a) pure 
nothrow @safe


But I can't make the delegate pure:
dg = (int a) pure {return z;};
because it references z.

Is the 'typeof((int a){return z;})' getting it wrong here?


Filed:
http://d.puremagic.com/issues/show_bug.cgi?id=9415


Re: Need help with storage class definition

2013-01-14 Thread Kenji Hara

On Monday, 14 January 2013 at 14:16:32 UTC, mist wrote:
While working on 
https://github.com/D-Programming-Language/phobos/pull/863 I 
have noticed that inout breaks ParameterStorageClassTuple and 
family. I have started working on a fix but quick comparison of 
http://dlang.org/declaration.html#StorageClass vs 
http://dlang.org/phobos/std_traits.html#.ParameterStorageClassTuple 
have left me in confusion without clear understanding what 
parameter storage classes are supposed to be defined to.


There is also InOutX entry in grammar which lists some of 
storage classes and seems more relevant to parameter storage 
classes (i.e. includes ref).


Can someone give a more structured explanation: what is 
supposed to be a storage class, what is supposed to be a type 
storage class and what - a type qualifier? I'd like to update 
std.traits demanglers to the latest state of things, but 
grammar description does not seem clear enough.


http://dlang.org/declaration.html#StorageClass
InOutX is the list of 'syntactically allowed' keywords.

Among them, these four are supported as actual 'parameter storage 
classes'.


scope
out
ref
lazy

In current, 'in' is directly replaced to 'const', and it is 
treated as a part of parameter type.

'inout' is also treated as a type qualifier, and then is the same.

Kenji Hara


Re: ref return function using foreach ref result segfaults. Compiler bug?

2012-11-13 Thread Kenji Hara

On Tuesday, 13 November 2012 at 08:50:16 UTC, Rob T wrote:

Hard to describe this problem, see code and read comments below.

class A
{
   private int _v;

   this( int a_v )
   {
  _v = a_v;
   }

   @property size_t length()
   {
return 1;
   }
   int opApply( int delegate( ref int a_v ) a_dg )
   {
  int result = 0;
  for ( ulong i = 0; i  length; ++i )
  {
 result = a_dg( this.opIndex( i ) );
 if ( result ) break;
  }
  return result;
   }
   ref int opIndex( size_t a_iPos )
   {
  return _v;
   }

}

class B : A
{
   this( int a_v )
   {
  super(a_v);
   }

   ref int find( int a_What )
   {
  foreach( val; super )
  {
 if ( val == a_What )
return val;
  }
  throw new Exception(value not found);
   }
}

main()
{
auto v_B = new B(500);
writefln(Search = %d, v_B.find(500) );
return 0;
}


When the return value of find() is ref, it segfaults or returns 
garbage. If the return value is a copy it works OK.


The only oddity I can see is that 'val' goes out of scope, but 
it's a ref return value (pointer) to _v (right?), so it should 
work anyway.


This looks like a bug in the compiler to me.

What do you guys think?


This issue looks like bug8093.
http://d.puremagic.com/issues/show_bug.cgi?id=8093

And the code works correctly in git head (dmd2.061alpha). 
Therefore, I think that the bug is fixed very recently.


Kenji Hara


Re: templated static array

2012-10-15 Thread Kenji Hara

On Monday, 15 October 2012 at 17:05:30 UTC, Simen Kjaeraas wrote:

On 2012-35-15 17:10, Namespace rswhi...@googlemail.com wrote:

But bar([1, 2, 3]); not. The compiler does not realize that 
[1, 2, 3] means a static array in this context.
You have to write bar(cast(int[3]) [1, 2, 3]); but I think the 
compiler have to recognize this on it's own.


This is true. The problem is, as you say, that the compiler 
treats array
literals as dynamic rather than static arrays. I would argue 
this is the
correct default, but it's obviously not the default you want 
here.


bearophile has posted about this on numerous occasions, and 
it's among

his top thousand wanted features. :p


I think this is a bug in IFTE.
Please file it into bugzilla.

Kenji Hara


Re: offsetof + foreach

2012-09-08 Thread Kenji Hara
On Friday, 7 September 2012 at 17:32:43 UTC, Ellery Newcomer 
wrote:

On 09/07/2012 10:31 AM, Ellery Newcomer wrote:
I have a struct buffer, and I want to print out its members' 
offsetof.


This:

foreach(i,_t; buffer.tupleof) {
writefln(%s@: %s, _t.stringof, _t.offsetof);
}

complains

Error: undefined identifier 'offsetof'

what should I be doing?


nevermind, I remember tupleof + foreach has always been broken

writefln(%s@: %s, buffer.tupleof[i].stringof, 
buffer.tupleof[i].offsetof);


I think this is expected behavior.
In foreach body, _t is a copy of field value, and it's not 
buffer's field itself.


Your code is equivalent with:

foreach(i,_; buffer.tupleof) {
auto _t = buffer.tupleof[i];// _t is a normal variable
writefln(%s@: %s, _t.stringof, _t.offsetof);
}

Then you cannot get offsetof property from _t;

Regards.

Kenji Hara


Re: How to create TypeTuple/ExpressionTuple from tuple/tuples

2012-08-08 Thread Kenji Hara

On Tuesday, 7 August 2012 at 16:11:05 UTC, Andrej Mitrovic wrote:

On 8/7/12, Øivind oivind@gmail.com wrote:

How can I call this function with an already-constructed tuple
but pass the pule as an expressiontuple?

auto v = tuple(1, 2, 3);
f(v);


Use the .expand property:
f(v.expand)


You can also use slice operator instead of expand property.


import std.stdio, std.typecons;
void f(T ...)(T t) {
writeln(t.length);
}

void main(){
auto v = tuple(1, 2, 3);
f(v[]); // prints 3

auto v0 = tuple(1, 2, 3);
auto v1 = tuple(4, 5, 6);
f(v0[], v1[]);  // prints 6
}



Re: template - aliasing a member function

2012-08-08 Thread Kenji Hara
On Wednesday, 8 August 2012 at 23:21:32 UTC, Ellery Newcomer 
wrote:

say I have

template T(alias fn) {
}

class Foo {
  int i();
  void i(int);
}

alias T!(Foo.i) Biz;

Is there a way to get a handle to both of the overloads of 
Foo.i inside T?


Actually, all I really need for that is to get 'Foo.i' out of 
fn.


mangleof looks promising..


import std.typetuple : TypeTuple;
template Id(alias a) { alias a Id; }

template T(alias fn) {
alias Id!(__traits(parent, fn)) Parent;
// use Id template so we cannot alias __traits result directly
static assert(is(Parent == Foo));

enum FnName = __traits(identifier, fn);

alias TypeTuple!(__traits(getOverloads, Parent, FnName)) 
Overloads;
// use TypeTuple template so we cannot alias __traits result 
directly

pragma(msg, typeof(Overloads[0]));  // prints int()
pragma(msg, typeof(Overloads[1]));  // prints void(int)
}

class Foo {
int i();
void i(int);
}
alias T!(Foo.i) Biz;



Re: ~= call copy ctor?

2012-07-21 Thread Kenji Hara

On Friday, 20 July 2012 at 16:02:18 UTC, Namespace wrote:

If i @disable the postblit i get a strange behaviour:

[code]
struct Test {
public:
int _id;

this(int i) {
_id = i;

writeln(CTOR);
}

@disable
this(this);

~this() {
writeln(DTOR);
}
}

void main() {
Test[] _arr;

_arr ~= Test(42);

writeln(_arr[0]._id);

writeln(end main);
}
[/code]

prints:

CTOR
DTOR
42
end main

The DTor is called _before_ i write Test's id but i can still 
print the correct id.

Implicit Copy CTor? ;)


Array appending and struct postblit behavior is now broken.
I've suggested a pull request to fix these bugs.

https://github.com/D-Programming-Language/dmd/pull/1037

Bye.

Kenji Hara


Re: Literals starting with 0 will not work with UFCS

2012-07-03 Thread Kenji Hara

On Wednesday, 4 July 2012 at 01:53:40 UTC, Jonathan M Davis wrote:

On Wednesday, July 04, 2012 03:48:52 ixid wrote:

 0.writeln();
 
 This works.


It doesn't with 2.058, are we using different versions? Thanks
for adding it to the bug list, I am not knowledgeable enough
about D to judge if something is a bug or if I've just not
understood it.


2.059 is the latest release (and is already nearly 3 months 
old), but I'm

using the latest from github, so I don't know what 2.059 does.

- Jonathan M Davis


The problem was fixed in 2.060head.
http://d.puremagic.com/issues/show_bug.cgi?id=8252

Kenji Hara


Re: Stack overflow / recursive expansion with alias this

2012-06-27 Thread Kenji Hara

On Tuesday, 24 April 2012 at 20:09:32 UTC, Namespace wrote:

On Tuesday, 24 April 2012 at 19:34:26 UTC, Timon Gehr wrote:

On 04/24/2012 07:09 PM, Namespace wrote:

...
And therefore i get the same error, as if i wrote return
NotNull!(Foo)(this); instead of return 
assumeNotNull(this);, in the
_convert method of NotNull. The Output is Stack 
overflow. I think
that comes from recursive calls which fills the stack? Is 
that a bug?




Yes.


I found nothing like that. Is the bug reported?


I remember reporting a similar issue, but that one seems to 
have been fixed. Feel free to create a new ticket.


That's what I do now. Thanks a lot for your help.


Today I posted a pull to detect recursive alias this dependency.
https://github.com/D-Programming-Language/dmd/pull/1028

Bye.

Kenji Hara


Re: Problem about using struct

2012-06-25 Thread Kenji Hara

On Monday, 25 June 2012 at 06:05:34 UTC, Tongzhou Li wrote:

Hello! I'm learning D, and wrote some sample codes with D.
I wrote: http://ideone.com/VY7ES

It failed to compile; I got 2 errors:
main.d(19): Error: constructor 
main.carry!(int,int,int,int,int).carry.this (int delegate(int, 
int _param_0, int _param_1, int _param_2) _f) is not callable 
using argument types (int)
main.d(19): Error: cannot implicitly convert expression (1) 
of type int to int delegate(int, int _param_0, int _param_1, 
int _param_2)
Compiler used: DMD v2.059 (I used lambda expression which 
ideone doesn't support)


Don't know what it means, I don't call any constructor in Line 
19. Then I tried to use class instead of struct 
(http://ideone.com/ZI2Tn), it worked fine.


So what's wrong with that?
Sorry for my poor English:)


Unfortunately, this is a dmd bug that yet not fixed.
http://d.puremagic.com/issues/show_bug.cgi?id=6036

As far as I know, there is no workaround...

Kenji Hara


Re: Retain struct when using alias this and passing using the alias..?

2012-06-25 Thread Kenji Hara

On Sunday, 24 June 2012 at 13:16:53 UTC, simendsjo wrote:

import std.exception;
import std.traits;

struct Ranged(T, T min, T max) {
T _value = min;
typeof(this) opAssign(V : T)(V value) {
enforce(value = min);
enforce(value = max);
_value = value;
return this;
}
alias _value this;
}

void f(int i) {
i = 1000;
}

void g(T)(T i) if(isIntegral!T){
i = 1000;
}

void main() {
Ranged!(int, 10, 20) v;
v = 10; // ok
v = 20; // ok
f(v); // auch
g(v); // ok, exception
}

Is there a way to ensure the struct is used in f() without 
using templates as in g()?


The type of 'alias this' symbol works as like the super class of 
user defined class.
Therefore, Ranged!(...) is always implicitly convertible to int 
by 'alias _value this', and there is no way to disable such 
conversion.


Kenji Hara


Re: front doesn't compile for arrays of immutable data

2012-06-25 Thread Kenji Hara

On Monday, 25 June 2012 at 14:23:25 UTC, Roman D. Boiko wrote:

import std.range;
struct Element {
  //immutable // uncomment to break compilation
   int _i;
  this(int i) { _i = i; }
}
void main() {
  auto arr = [Element.init];
  arr.front;
}

Declaring _i immutable yields the following compilation error:

/usr/include/x86_64-linux-gnu/dmd/phobos/std/array.d(460): 
Error: a[0LU] isn't mutable
sample.d(11): Error: template instance 
std.array.front!(Element) error instantiating


Is this a bug, or I misunderstand something?


This is a bug of the compiler, and it is already filed.
http://d.puremagic.com/issues/show_bug.cgi?id=6336

I've already posted a pull request to fix the bug, but it has 
been hold a while.


Kenji Hara


Re: to!(ubyte[])()

2012-06-22 Thread Kenji Hara

On Friday, 22 June 2012 at 09:18:38 UTC, simendsjo wrote:

Bug or by design? (using dmd head)

import std.conv;
void main() {
to!(ubyte[])();
}


std/array.d(493): Attempting to fetch the front of an empty 
array of immutable(char)

[snip]

It is design. With the conversion from string to non-string type, 
std.conv.to runs parsing.


import std.conv;
void main()
{
auto arr = to!(ubyte[])([1,2,3]);
// parse given string as a representation of ubyte[] value.
assert(arr == [1,2,3]);
}

And, the representation string of a value should have one or more 
characters.

So empty string always throws exception.

Kenji Hara


Re: Object Cast

2012-06-21 Thread Kenji Hara

On Thursday, 21 June 2012 at 10:33:41 UTC, Namespace wrote:
To solve the problem of converting a Object to a specific 
template class i wrote this little function.
But the mixin disturbs me. How i can get the type (in this 
example Vector2D) without to mix a mixin and T.stringof?


[code]
T object_cast(T : Object)(Object value) {
T val = cast(T) value;

if (val !is null) {
return val;
}

// if cast fails it is a template class

import std.typetuple;

	foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, 
uint, long, ulong, float, double, real)) {

mixin(
		if (auto vec = cast( ~ T.stringof ~ !( ~ Type.stringof ~ 
))(value)) {

return cast(T) vec;
});
}

return null;
}
[/code]


If you use 2.060head (git version), you can get template from the 
instantiated type.


class Vec(T) {}

void main()
{
alias Vec!int IntVec;
static if (is(IntVec _unused : V!T, alias V, T))
{
// V is class template Vec
alias V!double DoubleVec;  // another type instantiation 
test

static assert(is(DoubleVec == Vec!double));  // equal!
}
else
static assert(0);
}



Re: Why doesn't alias this work with arrays?

2012-06-18 Thread Kenji Hara

On Monday, 18 June 2012 at 16:51:11 UTC, Andrej Mitrovic wrote:

struct Wrap
{
string wrap;
alias wrap this;
}

void main()
{
Wrap x;
x = foo;  // ok
Wrap[] y = [foo, bar];  // fail
}

Error: cannot implicitly convert expression ([foo,bar]) of 
type

string[] to Wrap[]

Any special reason why this doesn't work? I hope it's just a 
bug or

unfinished implementation.


This kind conversions should be possible with std.conv.to.

import std.conv;
struct Wrap
{
string wrap;
alias wrap this;
}
void main()
{
Wrap[] y = to!(Wrap[])([foo, bar]);  // shold work
}

If you can construct Wrap object with the syntax Wrap(foo), 
std.conv.to runs 'conversion by construction'.
And if S is convertible to T, std.conv.to!(T[])(S[] source) runs 
'element-wise array conversion'.

As a result, string[] to Wrap[] will be converted.

...but, this does not work in 2.060head, it is a bug.

Kenji Hara


Re: alias this with property enforce

2012-06-06 Thread Kenji Hara

On Wednesday, 6 June 2012 at 18:12:39 UTC, Namespace wrote:

If i have this code:

class Bar {
public:
  Foo GetFoo() {
return this._foo;
  }

  alias GetFoo this;
}

to allow access to Foo methods from Bar i get the error, that 
GetFoo isn't a property if i use -property.

Why?
The solution is to set @property before Foo GetFoo() but why 
must GetFoo a property? What if i don't want to declare GetFoo 
as a property? I cannot use it with alias this?


Because name lookup with alias this is implemented as simple 
rewriting of expressions.


  auto bar = new Bar();
  bar.hoge;

If class Bar doesn't have member hoge, it is rewritten as:

  bar.GetFoo.hoge;

After that, if Bar.GetFoo.hoge is a property, bar.GetFoo is 
converted to bar.GetFoo().hoge as like other property functions.
If Bar.GetFoo is not a property and you use -property switch, 
compiler shows not a property error because GetFoo is not a 
property.


There is no magic.


Re: How to test for equality of types?

2012-05-20 Thread Kenji Hara

On Saturday, 19 May 2012 at 18:17:16 UTC, Matthias Walter wrote:

On 2012-05-19 15:28, Philippe Sigaud wrote:

On Sat, May 19, 2012 at 12:23 PM, Matthias Walter
xa...@xammy.homelinux.net wrote:

I would open a bug report with the following code which is a 
bit smaller

than my first wrong version:

=

(...)
 pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - 
MyStruct

 pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
 static assert(is(typeof(w.aliasStruct) == AliasStruct)); // 
- true
 static assert(is(typeof(w.aliasStruct).Alias == 
AliasStruct.Alias));

// - false
}


Seems like a pb concerning whether Alias is a type or a 
symbol. See

A,B,C,D below:

void main()
{
 Wrapper w;

 pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - 
MyStruct

 pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
 static assert(is(typeof(w.aliasStruct) == AliasStruct)); // 
- true
 static assert(is(w.aliasStruct.Alias == AliasStruct.Alias)); 
// - true


 alias typeof(w.aliasStruct) A; // - OK
 //alias typeof(w.aliasStruct).Alias B; // - NOK
 //alias A.Alias C; // - NOK
 alias w.aliasStruct.Alias D; // - OK

 static assert(is(A.Alias == AliasStruct.Alias)); // - true
 //static assert(is(B == AliasStruct.Alias));
 //static assert(is(C == AliasStruct.Alias));
 static assert(is(D == AliasStruct.Alias)); // - true
}

I think A is enough for your need, but I don't get why B and C 
are not

accepted (DMD 2.059, Linux)



Using the current git version of dmd I realized that C works! 
Hence, as
a workaround it can be used by creating a local alias A and 
subsequently

using A.Alias in the is-expressions. But it seems odd that

alias typeof(X).A B; does not work but
alias typeof(X) Y; alias Y.A B; does.

Is this considered as a bug?

Best regards,

Matthias


It seems to me that is a regression by fixing bug 6475.
Now I'm trying to fix them.


Re: How to test for equality of types?

2012-05-20 Thread Kenji Hara

On Sunday, 20 May 2012 at 06:57:20 UTC, Kenji Hara wrote:

On Saturday, 19 May 2012 at 18:17:16 UTC, Matthias Walter wrote:
Using the current git version of dmd I realized that C works! 
Hence, as
a workaround it can be used by creating a local alias A and 
subsequently

using A.Alias in the is-expressions. But it seems odd that

alias typeof(X).A B; does not work but
alias typeof(X) Y; alias Y.A B; does.

Is this considered as a bug?

Best regards,

Matthias


It seems to me that is a regression by fixing bug 6475.
Now I'm trying to fix them.


I've filed the bug in bugzilla:
http://d.puremagic.com/issues/show_bug.cgi?id=8123

And posted a pull request to fix it:
https://github.com/D-Programming-Language/dmd/pull/957

Thanks.

Kenji Hara


Re: How to test for equality of types?

2012-05-20 Thread Kenji Hara

On Sunday, 20 May 2012 at 06:57:20 UTC, Kenji Hara wrote:

On Saturday, 19 May 2012 at 18:17:16 UTC, Matthias Walter wrote:

On 2012-05-19 15:28, Philippe Sigaud wrote:

On Sat, May 19, 2012 at 12:23 PM, Matthias Walter
xa...@xammy.homelinux.net wrote:

I would open a bug report with the following code which is a 
bit smaller

than my first wrong version:

=

(...)
pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - 
MyStruct

pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
static assert(is(typeof(w.aliasStruct) == AliasStruct)); // 
- true
static assert(is(typeof(w.aliasStruct).Alias == 
AliasStruct.Alias));

// - false
}


Seems like a pb concerning whether Alias is a type or a 
symbol. See

A,B,C,D below:

void main()
{
Wrapper w;

pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - 
MyStruct

pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
static assert(is(typeof(w.aliasStruct) == AliasStruct)); // 
- true
static assert(is(w.aliasStruct.Alias == AliasStruct.Alias)); 
// - true


alias typeof(w.aliasStruct) A; // - OK
//alias typeof(w.aliasStruct).Alias B; // - NOK
//alias A.Alias C; // - NOK
alias w.aliasStruct.Alias D; // - OK

static assert(is(A.Alias == AliasStruct.Alias)); // - true
//static assert(is(B == AliasStruct.Alias));
//static assert(is(C == AliasStruct.Alias));
static assert(is(D == AliasStruct.Alias)); // - true
}

I think A is enough for your need, but I don't get why B and 
C are not

accepted (DMD 2.059, Linux)



Using the current git version of dmd I realized that C works! 
Hence, as
a workaround it can be used by creating a local alias A and 
subsequently

using A.Alias in the is-expressions. But it seems odd that

alias typeof(X).A B; does not work but
alias typeof(X) Y; alias Y.A B; does.

Is this considered as a bug?

Best regards,

Matthias


It seems to me that is a regression by fixing bug 6475.
Now I'm trying to fix them.


Fixed in git head:
https://github.com/D-Programming-Language/dmd/commit/76543ef60f3b871612ddc0c87999859f427ba6f9


Re: Make all functions from std.typecons Proxy inout

2012-05-11 Thread Kenji Hara

On Thursday, 10 May 2012 at 07:32:42 UTC, Namespace wrote:
Can you explain me how TemplateThisParameter works? I read in 
the

manual but a more detail explanation would help me a lot.


Hmm, I have thought following code should work about foo, but 
doesn't.


import std.stdio;
struct Proxy
{
void foo(this T)()
{
writeln(T.stringof);
static assert(is(typeof(this) == T));
// I have thought this should pass with all cases...
}

void bar(this T)() inout
{
writeln(T.stringof);
//static assert(is(typeof(this) == T));
static assert(is(typeof(this) == inout(Proxy)));
}
void bar(this T)() shared inout
{
writeln(T.stringof);
//static assert(is(typeof(this) == T));
static assert(is(typeof(this) == shared(inout(Proxy;
}
}
void main()
{
Proxy mp;
const Proxy cp;
immutable Proxy ip;
shared Proxy sp;
shared const Proxy scp;

mp.foo();   // expects: Proxy - OK
/+
cp.foo();   // expects: const(Proxy)  - NG!
ip.foo();   // expects: immutable(Proxy)  - NG!
sp.foo();   // expects: shared(Proxy)  - NG!
scp.foo();  // expects: shared(const(Proxy))  - NG!
+/
mp.bar();   // expects: Proxy - OK
cp.bar();   // expects: const(Proxy) - OK
ip.bar();   // expects: immutable(Proxy) - OK
sp.bar();   // expects: shared(Proxy) - OK
scp.bar();  // expects: shared(const(Proxy)) - OK
}

The spec:
http://dlang.org/template#TemplateThisParameter
doesn't talk about typeof(this).

I think current behavior is less useful than I have thought.
And, current std.typecons.Proxy doesn't work as expected for 
non-mutable objects...


Re: Make all functions from std.typecons Proxy inout

2012-05-09 Thread Kenji Hara

On Wednesday, 9 May 2012 at 06:42:09 UTC, Namespace wrote:

On Wednesday, 9 May 2012 at 04:49:39 UTC, Kenji Hara wrote:

On Tuesday, 8 May 2012 at 22:58:07 UTC, Namespace wrote:
In my development of the Ref / NotNull structure, I came 
across a

problem: All the methods of Proxy aren't inout. Has this a
reason or will change? In my opinion they should all be 
inout.

I mentioned previous self fixes in my corresponding Ref /
NotNull thread already.


It is necessary. See following conceptual code:

struct S
{
   void f() {}
   void g() {}
}
struct Proxy(T)
{
   T o;
   void f()() inout { return o.f(); }
   void g(this T)() { return o.g(); }
}
void main()
{
   Proxy!S p;
   //p.f();  // inside Proxy.f, typeof(o) == inout
   p.g();
}

'Proxy' object should forward its 'this' type to original 
object.
For the purpose, TemplateThisParameter ('this T') works as 
expected.


Kenji Hara


I thought, inout is evaluated by the compiler and make the 
method either const or not

If not, then I understand, inout probably not yet complete.
But in this case you would have to offer just two methods:
void f () () {return o.f ();}
void f () () const {return o.f ();}


Yes. *In this case*, we should define two member function 'f' in 
Proxy to forward the call to original object. But, in general 
case, it is not sufficient.


struct S
{
void f() {}
void f() const{}
void f() immutable {}
void f() shared {}
void f() shared const {}
}
struct Proxy(T)
{
T o;

// forward to original f, need *five* thunks. Terrible!
void f1()()  { return o.f(); }
void f1()() const{ return o.f(); }
void f1()() immutable{ return o.f(); }
void f1()() shared   { return o.f(); }
void f1()() shared const { return o.f(); }

// cannot forward, this calls only S.f() const
void f2()() inout { return o.f(); }

// needs only one thunk. Excellent!
void f3(this T)() { return o.g(); }
}
void main()
{
Proxy!S p;
p.f1();  // call mutable f
p.f2();  // CANNOT call mutable f
p.f3();  // call mutable f
}

My first version of Proxy had such duplicates, but it was hard 
maintainable.
After that, in review phase, I've discovered the way using 
TemplateThisParameter. It makes code readable and easy 
maintainable.


After all, it is the reason why I use TempalteThisParameter 
instead of inout.


Kenji Hara


Re: Make all functions from std.typecons Proxy inout

2012-05-08 Thread Kenji Hara

On Tuesday, 8 May 2012 at 22:58:07 UTC, Namespace wrote:
In my development of the Ref / NotNull structure, I came across 
a

problem: All the methods of Proxy aren't inout. Has this a
reason or will change? In my opinion they should all be inout.
I mentioned previous self fixes in my corresponding Ref /
NotNull thread already.


It is necessary. See following conceptual code:

struct S
{
void f() {}
void g() {}
}
struct Proxy(T)
{
T o;
void f()() inout { return o.f(); }
void g(this T)() { return o.g(); }
}
void main()
{
Proxy!S p;
//p.f();  // inside Proxy.f, typeof(o) == inout
p.g();
}

'Proxy' object should forward its 'this' type to original object.
For the purpose, TemplateThisParameter ('this T') works as 
expected.


Kenji Hara


Re: Extending std.format.formattedRead

2012-04-24 Thread Kenji Hara

On Tuesday, 24 April 2012 at 21:50:03 UTC, H. S. Teoh wrote:

What's the correct way of implementing formattedRead support for
user-defined types? I tried overloading the unformatValue() 
template,
but for some reason the compiler doesn't seem to be picking it 
up.


Unfortunately, there is not yet general way.
The definition of unformatValue for user-defined type in 
different module isn't considered by std.format module. D's 
module system is closed in basic.


Kenji Hara


Re: appending newly initialized struct to array

2012-04-18 Thread Kenji Hara

On Wednesday, 18 April 2012 at 04:55:23 UTC, Ali Çehreli wrote:

On 04/17/2012 02:00 PM, simendsjo wrote:

 Sounds like a bug. C style initializers work in other cases:

I try not to use them. I think they have this 'feature' of 
leaving unspecified members uninitialized:


struct S
{
int i;
double d;
}

void main()
{
S s = { 42 };   // -- no initializer for S.d
assert(s.i == 42);
assert(s.d == double.nan);  // -- fails (may work for you)


You should use std.math.isNaN whether a floating point value is 
NaN.


  assert(isNaN(s.d));  // -- success


}

Is that a bug or a feature? I might have opened it but I don't 
remember now. :)


Ali


Bye.

Kenji Hara


Re: Metaprogramming work around

2012-04-17 Thread Kenji Hara

On Tuesday, 17 April 2012 at 12:04:44 UTC, Erèbe wrote:
[snip]


There is something I still don't understand :

mixin template Foo( T... )
{
//Code here
}

mixin Foo!( Hello, Word );  Good


T is TemplateTypeParameter, and matches any kind of template 
arguments - types, values, and symbols. The both arguments 
Hello and World are values, so you can bind them with T.


http://dlang.org/template.html#TemplateTupleParameter




mixin template Foo( A, T... )
{
//code here
}

mixin Foo!( Hello, Word ); --- Fail !
mixin Foo!( string, Word );  Good



'A' is TemplateTypeParameter, and it matches only types. In the 
first instantiation of Foo, A doesn't match with the value 
hello.
In the second instantiation, string is type, and T matches with 
it.


http://dlang.org/template.html#TemplateTypeParameter


mixin template Foo( alias A, T... )
{
//code here
}

mixin Foo!( Hello, world ); --- Good
mixin Foo!( string, world ); --- Fail !

-


'alias A' is TemplateAliasParameter, and it matches both symbols 
and values.
Then A matches with the value Hello, but doesn't with the type 
string.
(string is an aliased name of immutable(char)[], and it is 
built-in array type.)


http://dlang.org/template.html#TemplateAliasParameter

Kenji Hara


Re: appending newly initialized struct to array

2012-04-17 Thread Kenji Hara

On Tuesday, 17 April 2012 at 21:00:55 UTC, simendsjo wrote:
On Tue, 17 Apr 2012 22:28:31 +0200, maarten van damme 
maartenvd1...@gmail.com wrote:


Just for fun I decided to complete some codejam challenges in 
D. At some
point I wanted to add structs to an array but I got a compiler 
error. What

am I doing wrong?

code:
struct test{
int x;
int y;
}
void main(){
test[] why;
why~={3,5};
}

error:
wait.d(7): found '}' when expecting ';' following statement
wait.d(8): found 'EOF' when expecting ';' following statement
wait.d(8): found 'EOF' when expecting '}' following compound 
statement


Is there any reason a why this wouldn't work?


Sounds like a bug. C style initializers work in other cases:

struct S { int i; }
void main() {
S[] arr;
S s = { 1 };
arr ~= S(1);
// But the following barfs
//arr ~= { 1 };
//arr ~= { i:1 };
//arr[0] = { 1 };
}


No, it is designed. {3,5} is struct initializer:
http://dlang.org/declaration.html#StructInitializer
And it is only allowed in initializer of variable declarations.


why~={3,5};


This is concat assign expression, so you should use test(3,5)
instead of {3,5}. That is StructLiteral:
http://dlang.org/struct.html#StructLiteral
and it is an expression.

Bye.

Kenji Hara


Re: const AB c = {a,20, numbers};

2012-04-16 Thread Kenji Hara

On Monday, 16 April 2012 at 14:50:43 UTC, sclytrack wrote:


struct AB
{
int a;
int b;
int [] numbers;
}

int main()
{
int a = 300;
const int [] numbers = new int[2];
const AB c = {a,20, numbers};   // line 66
writeln(c);
return 0;
}


-debug
-unittest

src/main.d(66): Error: cannot implicitly convert expression 
(numbers) of type const(int[]) to int[]


---


const AB c;

typeof(c.a) is  const(int);
typeof(c.numbers) is const(int []);


Shouldn't the code above accept the const(int [])   ?


Should do. It is a compiler bug.

I've filed this issue in bugzilla:
http://d.puremagic.com/issues/show_bug.cgi?id=7929

And posted a pull request to fix compiler code:
https://github.com/D-Programming-Language/dmd/pull/884

Thanks.

Kenji Hara


Re: Templates in classes = what is wrong?

2012-04-16 Thread Kenji Hara

On Monday, 16 April 2012 at 18:48:52 UTC, Xan wrote:

On Sunday, 15 April 2012 at 19:30:27 UTC, Ali Çehreli wrote:

On 04/15/2012 11:39 AM, Xan wrote:
 On Sunday, 15 April 2012 at 11:23:37 UTC, John Chapman wrote:
 On Sunday, 15 April 2012 at 11:16:43 UTC, Xan wrote:

 int main(string [] args)
 {
 auto alg = Algorisme!(int,int);

 Should be:
 auto alg = new Algorisme!(int, int);

 alg.nom = Doblar;
 alg.versio = 1;
 alg.funcio = (int a) {return 2*a};

 Should be:
 alg.funcio = (int a) { return 2 * a; };
 or:
 alg.funcio = a = 2 * a;

 }


 It does not work:

 $ gdmd-4.6 algorisme.d
 algorisme.d:18: Error: variable algorisme.main.alg voids have
no value
 algorisme.d:18: Error: expression class Algorisme is void and
has no value

 with the code https://gist.github.com/2394274

 What fails now?

 Thanks,
 Xan.

Your code is still missing 'new':

auto alg = new Algorisme!(int, int);


With only this change, I receive this error:

$ gdmd-4.6 algorisme.d
algorisme.d:21: Error: cannot implicitly convert expression 
(__dgliteral1) of type int delegate(int a) pure nothrow to int 
function(int)




Unrelated recommendations:

- Return 0 from main() for successful exit, anything else by 
convention means some sort of error.


- Take advantage of constructors (and 'alias') to simplify 
syntax and risk of bugs:


import std.conv, std.stdio, std.stream, std.string;
import std.socket, std.socketstream;
import std.datetime;

class Algorisme(U,V) {
   string nom;
   uint versio;
   alias V function (U) Funcio;
   Funcio funcio;

   this(string nom, uint versio, Funcio funcio)
   {
   this.nom = nom;
   this.versio = versio;
   this.funcio = funcio;
   }
}

int main(string [] args)
{
   alias Algorisme!(int, int) MeuAlgorism;
   auto alg = new MeuAlgorism(Doblar, 1,
  (int a) { return 2 * a; });

   return 0;
}

Ali


With all of your suggestion [https://gist.github.com/2394274], 
I get:


$ gdmd-4.6 algorisme.d
algorisme.d:30: Error: constructor 
algorisme.Algorisme!(int,int).Algorisme.this (string nom, uint 
versio, int function(int) funcio) is not callable using 
argument types (string,int,int delegate(int a) pure nothrow)
algorisme.d:30: Error: cannot implicitly convert expression 
(__dgliteral1) of type int delegate(int a) pure nothrow to int 
function(int)
algorisme.d:27: Error: function D main has no return statement, 
but is expected to return a value of type int



What fails?

PS: Thanks for your recommendations...
PPS: By the other hand, I see you have learned catalan 
(MeuAlgorisme?) ;-)


Problem may be here:


alg.funcio = (int a) { return 2 * a; };


2.057 and earlier (You may use gdc 2.057 and command line wrapper 
gdmd), function literal always deduced as 'delegate'. So this 
expression raises an error about type mismatching Lhs of 'int 
function(int)' and  Rhs of 'int delegate(int) pure nothrow'.


Then, specifying explicit 'function' will resolve issue:

  alg.funcio = function(int a) { return 2 * a; };

Bye.

Kenji Hara


Re: A problem with mutable toString

2012-04-09 Thread Kenji Hara

On Monday, 9 April 2012 at 00:25:57 UTC, bearophile wrote:

Currently this code compiles and runs with no errors:

class Foo {
  override string toString() const {
  return Foo;
  }
}
void main() {
  import std.stdio;
  const Foo[] foos = [new Foo];
  writeln(foos);
}


Output, DMD 2.059beta2:

[Foo]



While this gives errors:


class Foo {
  override string toString() /*const*/ {
  return Foo;
  }
}
void main() {
  import std.stdio;
  const Foo[] foos = [new Foo];
  writeln(foos);
}


Output, DMD 2.059beta2:


[snip]

Current std.format doesn't support const class formatting with 
upcasting to mutable Object and using mutable toString().



Is this good/expected?


It is a gap between language const system and object.Object class 
interface.

I think Phobos should not break const system in basic.

Kenji Hara


Re: Problem about lambda expressions

2012-03-27 Thread Kenji Hara

On Tuesday, 27 March 2012 at 13:42:30 UTC, Tongzhou Li wrote:

Hello again! I'm learning D, and I encountered a problem.
I tried this code:
http://ideone.com/hkpT6
It works well. (Have no idea why codepad.org failed to compile 
it)
I tried to write a lambda instead of function f, but I got 
nothing printed.

Did I make something wrong?
Compiler used: DMD32 D Compiler v2.058 (Win7 SP1 x64)
Sorry for my poor English :)


(obj x, int a0, int a1) = { x.setxxx(a0); x.setyyy(a1); }

This lambda expression returns *a delegate has no parameter*.
Instead:

(obj x, int a0, int a1) = (x.setxxx(a0), x.setyyy(a1))

or:

(obj x, int a0, int a1){ x.setxxx(a0); x.setyyy(a1); }



Re: Confused by refusal to expand template

2012-03-25 Thread Kenji Hara

On Friday, 23 March 2012 at 23:01:43 UTC, Timon Gehr wrote:

On 03/23/2012 11:58 PM, David wrote:

Am 23.03.2012 23:52, schrieb H. S. Teoh:

Code:
struct S {
int f(K)(K x) {
return 1;
}
void func(K)(inout(K) x) {
auto h = f(x);
}
}
void main() {
S s;
s.func(abc); // This is line 44
}

This refuses to compile:

test2.d(44): Error: template test2.S.func(K) does not match 
any

function template declaration
test2.d(44): Error: template test2.S.func(K) cannot deduce 
template

function from argument types !()(string)

Removing 'inout' fixes the problem. But I don't understand 
why.



T

I've never really used inout, but don't you need it also for 
the

return-type?


Not any more (DMD 2.059). See 
http://d.puremagic.com/issues/show_bug.cgi?id=7105



Furthermore you don't the the inout here, since this
template does match const/immutable/nothing anyways.


His intention probably is to prevent multiple instantiation of 
a template based on different constness.


This is definitely a bug. I've filed it in bugzilla, and posted a 
pull to fix it.

http://d.puremagic.com/issues/show_bug.cgi?id=7769


Re: Regarding writefln formatting

2012-03-22 Thread Kenji Hara

On Wednesday, 21 March 2012 at 01:26:23 UTC, bearophile wrote:

import std.stdio;
void main() {
 auto mat = [[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]];

 writefln(%(%(%d %)\n%), mat);
 writeln();

 writefln([%(%(%d %)\n%)], mat);
 writeln();

 writefln([%([%(%d %)]\n%)], mat);
 writeln();
}

Prints:

1 2 3
4 5 6
7 8 9

[1 2 3
4 5 6
7 8 9]

[[1 2 3]
[4 5 6]
[7 8 9]


Do you know why the last closed square bracket is missing?


You can use %| format specifier to specify element separator.

(It was proposed in 
https://github.com/D-Programming-Language/phobos/pull/298 .

It is not yet documented, but already merged in Phobos.)

import std.stdio;
void main() {
 auto mat = [[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]];

 writefln([%([%(%d %)]%|\n%)], mat);
 // specify \n as a separator
}

Prints:

[[1 2 3]
[4 5 6]
[7 8 9]]