Re: char[] == null

2015-11-20 Thread Maxim Fomin via Digitalmars-d-learn
On Thursday, 19 November 2015 at 15:36:44 UTC, Steven 
Schveighoffer wrote:
On 11/19/15 3:30 AM, Jonathan M Davis via Digitalmars-d-learn 
wrote:
On Wednesday, November 18, 2015 22:15:19 anonymous via 
Digitalmars-d-learn wrote:

On 18.11.2015 22:02, rsw0x wrote:

slices aren't arrays
http://dlang.org/d-array-article.html


The language reference/specification [1] uses the term 
"dynamic array"
for T[] types. Let's not enforce a slang that's different 
from that.



[1] http://dlang.org/arrays.html


Exactly. T[] _is_ a dynamic array. Steven's otherwise 
wonderful article on
arrays in D ( http://dlang.org/d-array-article.html ) made the 
mistake of
calling the buffer that T[] points to on the GC heap (assuming 
that even
does point to the GC heap) the dynamic array. And per the 
language spec,

that's not true at all.


It was not a mistake :) It's how I still think of it. The spec 
is confusing, and my terminology, IMO, is a much more 
consistent (and accurate) way to think of it.


-Steve


Why formal definition of dynamic array caused confusion and is 
inconsistent? It is well consistent with static array and other 
aggregate types notions.


Consider this:

int *x = new int; // this is 'int type' ans it is 'dynamic'
int y;
int *a = // and this is not 'int type'

The problem is treating chunk of heap memory as some kind of type 
(dynamic in this case). Type of object determines an interface of 
interacting with object while storage determines memory location 
and possibly duration of lifetime. It is possible to have object 
of any type to be allocated on different storages - for example, 
slice does not necessarily points to dynamic array (in your 
terms). C and C++ established a long tradition of such standard 
notions as object, lifetime, storage and type. From system 
language perspective calling memory a type (in other words, type 
of object depends on where it was allocated) does not make much 
sense.


Re: Preventing implicit conversion

2015-11-04 Thread Maxim Fomin via Digitalmars-d-learn

On Wednesday, 4 November 2015 at 21:22:04 UTC, ixid wrote:
On Wednesday, 4 November 2015 at 19:09:42 UTC, Maxim Fomin 
wrote:

On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote:
Is there an elegant way of avoiding implicit conversion to 
int when you're using shorter types?


Only with library solution. Implicit conversions are built 
into language.


Doesn't that seem rather limiting and unnecessary?


Well, indeed it often produces confusion (this is inherited from 
C for compatibility purpose).


Re: Preventing implicit conversion

2015-11-04 Thread Maxim Fomin via Digitalmars-d-learn

On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote:
Is there an elegant way of avoiding implicit conversion to int 
when you're using shorter types?


Only with library solution. Implicit conversions are built into 
language.


Re: Overloading an imported function

2015-10-23 Thread Maxim Fomin via Digitalmars-d-learn
On Wednesday, 21 October 2015 at 12:05:27 UTC, Shriramana Sharma 
wrote:

import std.math;
real round(real val, int prec)
{
real pow = 10 ^^ prec;
return round(val * pow) / pow;
}

Trying to compile this I get:

foo.d(5): Error: function foo.round (real val, int prec) is not 
callable using argument types (real)


When I've imported std.math which contains round(real), why is 
the compiler complaining about not being able to call the 
overload function defined in *this* module?


I don't see anything in http://dlang.org/module.html that says 
I cannot define an overload of an imported function. Did I miss 
something?


My guess is that .round shadows math.round. But you can 
get desired behavior
by moving declaration of math.round inside scope of 
.round. This compiles:


real round(real val, int prec)
{
import std.math;
real pow = 10 ^^ prec;
return round(val * pow) / pow;
}




Re: Array of subclasses

2015-10-22 Thread Maxim Fomin via Digitalmars-d-learn

On Thursday, 22 October 2015 at 13:29:06 UTC, DarkRiDDeR wrote:


I don't need the base class data. How to create a array of 
subclasses objects with the derived data members?


The language is implemented in this way. You have already have 
the answer:



writeln(Core.users.name)
Out:
USERS


Re: Array of subclasses

2015-10-22 Thread Maxim Fomin via Digitalmars-d-learn

On Thursday, 22 October 2015 at 11:02:05 UTC, DarkRiDDeR wrote:


This variant works strangely. Example:

abstract class Addon
{
public string name = "0";
}
class Users: Addon
{
override
{
public string name = "USERS";
}
}
static final class Core
{
static:
public Addon[] activated;
public Users users;

public void activate()
{
users = new Users;
activated = [new Users, new Users];
}
}

Core.activate();
writeln(Core.users.name ~ "\n"  ~ Core.activated[1].name);

Out:
USERS
0


First of all, the code does not compile with override. It is 
impossible to override a data. Override should be removed.
The reason it works this way is that the first access is to base 
class data while the second is to the derived data member.


Re: Implicit conversion rules

2015-10-21 Thread Maxim Fomin via Digitalmars-d-learn

On Wednesday, 21 October 2015 at 19:49:35 UTC, Ali Çehreli wrote:

On 10/21/2015 12:37 PM, Sigg wrote:

> cause at least few more "fun" side effects.

One of those side effects would be function calls binding 
silently to another overload:


void foo(bool){/* ... */}
void foo(int) {/* ... */}

  auto a = 0;  // If the type were deduced by the value,
  foo(a);  // then this would be a call to foo(bool)...
   // until someone changed the value to 2. :)

Ali


Actually 'a' is deduced to be int, so int version is called (as 
expected?). See my example above for the VRO overload issue.


Re: Implicit conversion rules

2015-10-21 Thread Maxim Fomin via Digitalmars-d-learn

On Wednesday, 21 October 2015 at 22:49:16 UTC, Marco Leise wrote:

Am Wed, 21 Oct 2015 12:49:35 -0700
schrieb Ali Çehreli :


On 10/21/2015 12:37 PM, Sigg wrote:

 > cause at least few more "fun" side effects.

One of those side effects would be function calls binding 
silently to another overload:


void foo(bool){/* ... */}
void foo(int) {/* ... */}

   auto a = 0;  // If the type were deduced by the value,
   foo(a);  // then this would be a call to foo(bool)...
// until someone changed the value to 2. :)

Ali


God forbid anyone implement such nonsense into D !
That would be the last thing we need that we cannot rely on
the overload resolution any more. It would be as if making 'a'
const would change the overload resolution when none of the
overloads deal with constness...



AFAIK it was implemented long time ago and discussed last time 
couple of years ago with example similar to Ali's.


void foo(bool)
void foo(int)

foo(0); // bool
foo(1); // bool
foo(2); // int


Re: how come is this legal? 'void fun(int){ }' ?

2015-06-13 Thread Maxim Fomin via Digitalmars-d-learn

On Sunday, 14 June 2015 at 01:20:39 UTC, Timothee Cour wrote:
I understand this is legal for declaration wo definition (void 
fun(int);)

but why allow this:
void test(int){} ?


Actually it is void test(int _param_0) { }
You can test by compiling void test(int) { _param_0 = 0; }

Nameless parameters are simulated by providing internal symbol as 
above.


Re: Cannot Qualify Variadic Functions with Lazy Arguments as nothrow

2015-05-14 Thread Maxim Fomin via Digitalmars-d-learn

On Thursday, 14 May 2015 at 09:53:20 UTC, Per Nordlöw wrote:

At

https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L43

I've implemented a function either() with behaviour similar to 
the `or` function/operator in dynamic languages such as Python 
and Lisp.


I'm almost satisified with it except that the lazy evaluation at

https://github.com/nordlow/justd/blob/master/algorithm_ex.d#L45

cannot be made nothrow.

If I qualify the function as nothrow DMD complains as

algorithm_ex.d(45,16): Error: 'a' is not nothrow
algorithm_ex.d(46,29): Error: '_param_1' is not nothrow

I don't see a reason why any of these two cases should throw.


Lazy argument is essentially delegate/function. Currently there 
is no

way to mark it as nothrow.

The same problem occurs if I make the implementation use only 
one function and check the recursion termination case with 
`static if (bs.length == 1)` instead.


Is there a workaround for this?


One way to address is to use delegate explicitly.

int foo(lazy int a) //nothrow
{
return a;
}

int bar(int delegate() nothrow dg) nothrow
{
return dg();
}

void main() nothrow
{
int a;
bar(()=a);
}


Re: Can't modify this

2014-07-02 Thread Maxim Fomin via Digitalmars-d-learn

On Saturday, 28 June 2014 at 20:40:21 UTC, Ary Borenszweig wrote:

This doesn't work:

class Foo {
  this() {
this = new Foo;
  }
}

Error: Cannot modify 'this'

However you can do this:

class Foo {
  this() {
auto p = this;
*p = new Foo();
  }
}

It even changes the value of this!

Should that compile? I mean, it's the same as modifying 
'this'...


D language was not aimed toward preventing any attepmt to 
circumvent some hypothetical limitations (it does not even cope 
with things which it should definetely prevent). There are holes 
much - much worse. And changing value of this parameter is not a 
problem anyway, since it is possible to have typeid(this) != 
typeid of type of current method which is bigger problem than 
pointing to different value of same type.


Re: Struct constructor, opCall mess.

2014-02-25 Thread Maxim Fomin
On Monday, 24 February 2014 at 14:14:43 UTC, Tobias Pankrath 
wrote:

On Monday, 24 February 2014 at 13:56:01 UTC, Remo wrote:

Hi,

right now I am truing to figure out how the constructors 
behave in D2.


Question 1: why it is not possible to create custom ctor for 
struct?


The design of D relies on the fact that every type has a T.init 
property that is known to the compiler and used when in C++ the 
default ctor would get called. In constructors you can rely on 
(this == T.init), for example.


You need to pick one T.init or default constructors and D 
picked T.init.


The design of D relies on Andrei opinion. He is indeed convinced 
that default constructors are impossible.


However, you can write default constructor right now like:

struct S
{
   Type t;
   this(int)
   {
  t = whather_is_callable_in_CTFE();
   }
}

enum E : S
{
   A = S(0)
}

void main()
{
  E e;
  assert (e.t == whather_is_callable_in_CTFE());
}

Since compiler does this, it can also accept straight syntax and 
semantic:


struct S
{
   Type t;
   this() // proxibited default constructor now
   {
  t = whather_is_callable_in_CTFE();
   }
}

What D really lacks is ability to call function in runtime after 
struct instance creation like:


struct S
{
   @runtime this() {}
   ~this(){}
}

lowering to:
S s;
s.__runtime_ctor();

However, since compiler does this all over the place (postblits, 
copy constructors, destructors, etc.) There is no conceptual 
difference between having:


S s
s.__runtime_ctor();

and

S s;
s.__dtor();

In other words, there is no objective necessity not to have 
compile time and runtime default struct constructors since 
compiler already heavily does conceptually and technically 
similar things.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Maxim Fomin

On Monday, 24 February 2014 at 19:41:57 UTC, Remo wrote:

For Vector example this works pretty well this way.
But my main problem is more complicated.

extern(C)  int init(ref CWrapper p);
extern(C) void free(ref CWrapper p);

struct CWrapper
{
  //some data that must be the same at C side.
  Data m_data;

  this() {
 init(this);
  }
  ~this() {
 free(this);
  }
}

How to do something like this in D ?
Using class appears for me to be wrong direction.



1) Please comment after previous speaker, not before.

You can't avoid default struct constructor problem if functions 
which you call in constructors are not at least CTFEable because 
you would need to call them if you wish to define default struct 
constructor. Since this is not your case, you can do:


2) You can use static OpCall, Voldemort type or alias this. In 
case of alias this it looks like:


extern(C) int printf(const char*, ...);

extern(C)  int init(CWrapper* p) { printf(init\n); return 0; }
extern(C) void d_free(CWrapper* p) { printf(free\n); }

struct Data { void do_something(){} }

struct CWrapper
{
  //some data that must be the same at C side.
  Data m_data;
  bool m_init;

  /*this(int) {
 init(this);
  }*/
  ~this() {
 d_free(this);
  }
  Data get()
  {
  if (!m_init)
  init(this);
  return m_data;
  }
alias get this;
}


void main()
{
CWrapper cw;
cw.do_something();

}

In case of Voldermort struct some struct is defined inside 
function, so the only way (in theory) to create an instance is to 
call that function. It is inconviniet but guarantees that you 
will not have non initialzed structs (in theory).


extern(C) int printf(const char*,...);


auto make_struct()
{
struct Data{}
struct CWrapper
{
  extern(C)  int m_init(CWrapper* p){ return 0; }
  extern(C) void m_free(CWrapper* p){ printf(free\n);}
  //some data that must be the same at C side.
  Data m_data;

 this(int) {
   m_init(this);
 }
 ~this() {
   m_free(this);
 }
}

return CWrapper(0);
}

void main()
{
auto x = make_struct();
}

4) Please do not define free() function.


Re: hiding a class property behind a method

2014-02-22 Thread Maxim Fomin

On Saturday, 22 February 2014 at 17:41:58 UTC, Ali Çehreli wrote:


The code uses the two objects through the A interface and x() 
is a virtual function on that interface.


When the C interface is used then we get C.x, which happens to 
be hiding the x() function of the base class.


It looks normal to me.

Ali


Spec is silent on this, so this is indeed a question.

Actually A is not interface, so I don't understand why you 
mention it. And there is neither 'taking C interface' because 
static type is A, so A function is called, neither it hides 
function of the base class because it is base class function 
which is called. I don't understand you completely.


AFAIK this feature exists for many years, at least 3, possibly 
roots to D1. What happens is follows: since there is no function, 
base class virtual is not replaced, so virtual table of C looks 
like A, so A member function is called.


If example is modified, then

import std.stdio;

class A {
  //string x () { return A; };
string x = A;
}

class B : A {
  //override string x () { return B; };
string x = B;
}

class C : A {
  //string x = C; // should this be illegal?
string x () { return C; }
}

void main () {
  A o1 = new B();
  A o2 = new C();
  writeln(o1.x); // A
  writeln(o2.x); //A
}

so it appears that data member have priority over function.

Probably this should be filed as a spec or compiler bug.


Re: Bug with references (no casting used)

2014-02-22 Thread Maxim Fomin

On Saturday, 22 February 2014 at 17:22:51 UTC, andrea9940 wrote:

Hi everyone,
I was trying to get my vector struct to use extensively 
references for passing parameters and I found a subtle bug 
which make me lose a few hour.


A sample code that shows the bug is here 
http://pastebin.com/rvcNdjAE (fails with dmd 2.064 on linux)

I think that the code is wrong and dmd does not recognize it:
opBinary() allocates a struct on the stack which is then 
accepted by reference in opOpAssign.


I'd like to know if currently there are correct ways to pass 
rvalue structs by reference or if I should pass everything by 
value and hope the compiler optimizes all reduntant copies.


Looks like compiler bug.


Re: Array as an argument, ambiguous behaviour.

2014-01-30 Thread Maxim Fomin

On Thursday, 30 January 2014 at 09:14:43 UTC, Cooler wrote:
If you want to modify the slice and make changes visible in 
caller, you should use ref. If you don't care whether changes 
are visible in caller, you can omit any attributes and use 
plain array. This belongs to the case you are asking about. If 
you don't want to change array in callee, pass it as const 
qualified.


Now, after rethinking the issue I am inclining that don't 
care whether changes are visible for caller is not very 
wrong, but not very good design. Ideally it should be 
specified to avoid unexpected problems to pop up. So yes, it 
is better to qualify array.


Another point. This casino games of whether changes would be 
visible or not is direct consequence of how slices are 
implemented (and how runtime service them). Remember, that 
many features in D work in a strange way not because of wise 
design but as a consequence of not fully thought design (like 
array). As a result, some features work in not best way they 
should. Although many folks in newsgroups would eagerly say 
that you don't understand the lang, it wouldn't make a bad 
design a good one.


Please stop explain me how fun3() works. I know that.


This is first problem. You are being explained what is the 
*purpose* of the fun3() but you repeatedly fail to accept it.


One of the main idea of D is that things must work as planned, 
or would not compile at all.


Outcryingly wrong. Study bugzilla which shows how some things go 
wrong and read DIPs to learn that there are some issues in the 
language for which the communitty still struggles to formulate 
good solution.


First and second variants follow this idea. But fun3() can work 
not as planned on the caller side (depends on fun3() body's 
implementation).


Many things can work not as intended. Please read forums, 
bugzilla, etc. I bet passing array will not be the only thing you 
find confusing.



The question again - may be prohibit fun3() variant?


Prohibiting code like:
void foo(int[] arr) {}

would break hell of a code and pose doubts on what happens with 
arrays if so simple construction is prohibited. In addition, I 
mentioned that don't care is probably sometimes an option. 
Emitting warning here has some merits but it would be consitently 
ignored (I expect).


Re: Array as an argument, ambiguous behaviour.

2014-01-30 Thread Maxim Fomin

On Thursday, 30 January 2014 at 10:49:42 UTC, Cooler wrote:
Now I am trying to speak ideally. What ideal language should 
be, not the practical implementation.



...

Again - don't look back. Consider how we can make D better.


...
Again - stop consider current state of D implementation. 
Consider how we can make D better. I think fun3() push 
programmers to make errors.


Looks like you are overestimating yourself.

Now, try:
1) write pull request to reject the code
2) convince developers somehow that your proposal is good
3) convince Walter to accept the change
4) after merging pull convince angry maintainers that it is good 
idea to reject unqualified array passing because Cooler tries to 
make the language better


Re: Array as an argument, ambiguous behaviour.

2014-01-30 Thread Maxim Fomin

On Thursday, 30 January 2014 at 16:48:51 UTC, Cooler wrote:
On Thursday, 30 January 2014 at 16:18:33 UTC, Steven 
Schveighoffer wrote:

void foo(int x)
{
  x = 5;
}

hey, why doesn't that work! Setting a parameter to another 
value should be illegal!


-Steve


Please understand - I am not against void foo(int[] x){}
I am for predictability of behavior.


Predictability of behavior is not a principle of D and even if it 
would be, it can't be applied blindly. D is not a formal 
mathematic system.


You suggest to describe function's behavior in documentation - 
quotation from your article It is a good idea to note in the 
documentation how the passed in slice might or might not be
overwritten. My idea is that all potential errors must be 
detected as soon as possible.


It is impossible to detect all errors in D per se, let alone 
taking into account separate compilation model. In some 
circumstances compiler can guess possible ways, but particular 
case we discussing is so common, that nothing can be done to 
'fix' it. By the way, this case is not strictly speaking an 
error. It is error in context when caller cares about changes but 
this can be hardly verified at compile time (compiler need to 
read brain to know it).


The D principle - The program compile and runs as expected, or 
not compile at all.


It is all talk. Trying to apply this 'principle' in all cases is 
too naive.


If you really need to call function that can change content of 
an array, but cannot change size of an array the language 
syntax should allow express it in function signature. I 
consider void fun(int[] const x){} more error prone than 
void fun(int[] x){} and for the caller and for implemeter.




Personally this syntax is awful.

By the way, there is another similar issue in D:

import std.stdio;

void foo(int[int] aa)
{
aa[1] = 1;
}

void main()
{
int[int] aa;
foo(aa);
writeln(aa); // []
aa[0] = 0;
foo(aa);
writeln(aa); // [0:0, 1:1]
aa = null;
foo(aa);
writeln(aa); // []
}

Here changes in AA array will be visible conditional that array 
is non null. If it is null, changes will be lost. This is another 
example of situation of the caller MAY or MAY NOT see changes 
to (citing your post above). In general, such 
semivalue-semireference semantic is produced when there is 
pointer wrapped into struct (doesn't matter whether it is opaque 
lang type or user defined). This happens in some language types, 
but may be also in user defined types. I don't think that 
verifying arbitrary semantic is compiler job.


Re: Array as an argument, ambiguous behaviour.

2014-01-29 Thread Maxim Fomin

On Wednesday, 29 January 2014 at 16:26:05 UTC, Cooler wrote:
On Wednesday, 29 January 2014 at 16:15:36 UTC, Tobias Pankrath 
wrote:

On Wednesday, 29 January 2014 at 16:01:08 UTC, Cooler wrote:


Do you read my post? I am answering... why do I need fun3() 
if I already have fun1() and fun2().


fun3 guarantees that the argument has the same length for 
example.


Where argument has the same length? After function call, or 
inside function? I don't understand what my intention should be 
to push me to use fun3()?


If you want to modify the slice and make changes visible in 
caller, you should use ref. If you don't care whether changes are 
visible in caller, you can omit any attributes and use plain 
array. This belongs to the case you are asking about. If you 
don't want to change array in callee, pass it as const qualified.


Now, after rethinking the issue I am inclining that don't care 
whether changes are visible for caller is not very wrong, but 
not very good design. Ideally it should be specified to avoid 
unexpected problems to pop up. So yes, it is better to qualify 
array.


Another point. This casino games of whether changes would be 
visible or not is direct consequence of how slices are 
implemented (and how runtime service them). Remember, that many 
features in D work in a strange way not because of wise design 
but as a consequence of not fully thought design (like array). As 
a result, some features work in not best way they should. 
Although many folks in newsgroups would eagerly say that you 
don't understand the lang, it wouldn't make a bad design a good 
one.


Re: struct postblit not called, but still destructed

2014-01-20 Thread Maxim Fomin

On Sunday, 19 January 2014 at 20:46:06 UTC, monarch_dodra wrote:


I think the behavior is not *strictly* incorrect: When you 
write:

sup = a;

it triggers a postblit of a into sup. To do said postblit, 
you destroy sup. It's the way it works :/


Arguably, since it is initialization, we could avoid the 
destruction altogether, but it's not strictly *wrong*.


I'll file it as an ER, and try to get Kenji on it.


It is rather bug than ER because recently there was work to 
recognize such cases (initial assignment in constructors) as 
initialization, not just assignment. However I am not sure here 
because these changes were not documented properly.


Re: Why is string.front dchar?

2014-01-20 Thread Maxim Fomin

On Monday, 20 January 2014 at 09:58:07 UTC, Jakob Ovrum wrote:

On Thursday, 16 January 2014 at 06:59:43 UTC, Maxim Fomin wrote:
This is wrong. String in D is de facto (by implementation, 
spec may say whatever is convenient for advertising D) array 
of single bytes which can keep UTF-8 code units. No way string 
type in D is always a string in a sense of code 
points/characters. Sometimes it happens that string type 
behaves like 'string', but if you put UTF-16 or UTF-32 text it 
would remind you what string type really is.


By implementation they are also UTF strings. String literals 
use UTF, `char.init` is 0xFF and `wchar.init` is 0x, 
foreach over narrow strings with `dchar` iterator variable type 
does UTF decoding etc.


I don't think you know what you're talking about; putting 
UTF-16 or UTF-32 in `string` is utter madness and not trivially 
possible. We have `wchar`/`wstring` and `dchar`/`dstring` for 
UTF-16 and UTF-32, respectively.




import std.stdio;

void main()
{
string s = о;
writeln(s.length);
}

This compiles and prints 2. This means that string type is 
broken. It is broken in the way as I was attempting to explain.



This is attempt to explain problematic design as a wise action.


No, it's not. Please leave crappy, unsubstantiated arguments 
like this out of these forums.


Note, that I provided examples why design is problematic. The 
arguement isn't unsubstained.





[1] http://dlang.org/type


By the way, the link you provide says char is unsigned 8 bit 
type which can keep value of UTF-8 code unit.


Not *can*, but *does*. Otherwise it is an error in the program. 
The specification, compiler implementation (as shown above) and 
standard library all treat `char` as a UTF-8 code unit. Treat 
it otherwise at your own peril.




But such treating is nonsense. It is like treating integer or 
floating number as sequence of bytes. You are essentially saying 
that treating char as UTF-8 code unit is OK because language is 
treating char as UTF-8 code unit.


The only problem in the implementation here that you illustrate 
is that `['s', 'ä', 'д']` is of type `int[]`, which is a bug. 
It should be `dchar[]`. The length of `char[]` works as 
intended.


You are saying that length of char works as intended, which is 
true, but shows that design is broken.


Problems with string type can be illustrated as possible 
situation in domain of integers type. Assume that user wants 
'number' type which accepts both integers, floats and doubles 
and treats them properly. This would require either library 
solution or a new special type in a language which is 
supported by both compiler and runtime library, which performs 
operation at runtime on objects of number type according to 
their effective type.


D designers want to support such feature (to make the language 
better), but as it happens in other situations, the support is 
only limited: compiler allows to do


alias immutable(int)[] number;
number my_number = [0, 3.14, 3.14l];


I don't understand this example. The compiler does *not* allow 
that code; try it for yourself.


It does not allow because it is nonsense. However it does allows 
equivalent nonsesnce in character types.


alias immutable(int)[] number;
number my_number = [0, 3.14, 3.14l]; // does not compile

alias immutable(char)[] string;
string s = säд; // compiles, however säд should default to 
wstring or dstring


Same reasons which prevent sane person from being OK with int[] 
number = [3.14l] should prevent him from being OK with string s = 
säд


Re: Why is string.front dchar?

2014-01-15 Thread Maxim Fomin

On Thursday, 16 January 2014 at 05:56:48 UTC, Jakob Ovrum wrote:

On Tuesday, 14 January 2014 at 11:42:34 UTC, Maxim Fomin wrote:
The root of the issue is that string literals containing 
characters which do not fit into signle byte are still 
converted to char[] array. This is strictly speaking not type 
safe because it allows to reinterpret 2 or 4 byte code unit as 
sequence of characters of 1 byte size. The string type is in 
some sense problematic in D. That's why the fact that .front 
returns dhcar is a way to correct the problem, it is not an 
attempt to introduce confusion.


This assertion makes all the wrong assumptions.

`char` is a UTF-8 code unit[1], and `string` is an array of 
immutable UTF-8 code units. The whole point of UTF-8 is the 
ability to encode code points that need multiple bytes (UTF-8 
code units), so the string literal behaviour is perfectly 
regular.


This is wrong. String in D is de facto (by implementation, spec 
may say whatever is convenient for advertising D) array of single 
bytes which can keep UTF-8 code units. No way string type in D is 
always a string in a sense of code points/characters. Sometimes 
it happens that string type behaves like 'string', but if you put 
UTF-16 or UTF-32 text it would remind you what string type really 
is.


Operations on code units are rare, which is why the standard 
library instead treats strings as ranges of code points, for 
correctness by default. However, we must not prevent the user 
from being able to work on arrays of code units, as many string 
algorithms can be optimized by not doing full UTF decoding. The 
standard library does this on many occasions, and there are 
more to come.


This is attempt to explain problematic design as a wise action.

Note that the Unicode definition of an unqualified character 
is the translation of a code *point*, which is very different 
from a *glyph*, which is what people generally associate the 
word character with. Thus, `string` is not an array of 
characters (i.e. an array where each element is a character), 
but `dstring` can be said to be.


[1] http://dlang.org/type


By the way, the link you provide says char is unsigned 8 bit type 
which can keep value of UTF-8 code unit.


UTF is irrelevant because the problem is in D implementation. See 
http://forum.dlang.org/thread/hoopiiobddbapybbw...@forum.dlang.org 
(in particular 2nd page).


The root of the issue is that D does not provide 'utf' type which 
would handle correctly strings and characters irrespective of the 
format. But instead the language pretends that it supports such 
type by allowing to convert to single byte char array both 
literals sad and säд. And ['s', 'ä', 'д'] is by the way 
neither char[], no wchar[], even not dchar[] but sequence of 
integers, which compounds oddities in character types.


Problems with string type can be illustrated as possible 
situation in domain of integers type. Assume that user wants 
'number' type which accepts both integers, floats and doubles and 
treats them properly. This would require either library solution 
or a new special type in a language which is supported by both 
compiler and runtime library, which performs operation at runtime 
on objects of number type according to their effective type.


D designers want to support such feature (to make the language 
better), but as it happens in other situations, the support is 
only limited: compiler allows to do


alias immutable(int)[] number;
number my_number = [0, 3.14, 3.14l];

but there is no support in runtime library. On surface, this 
looks like language have type which supports wanted feature, but 
if you use it, you will face the problems, as my_number[2] would 
give strange integer instead of float 3.14 and length of this 
array is 4 instead of 3. In addition this is not a type safe 
approach because there is option to reinterpret double as two 
integers.


Now in order to fix this, there is number of functions in library 
which treat number type properly. Such practice (limited and 
broken language support, unsafe and illogical type, functions to 
correct design mistakes) is embedded into practice so deeply, 
that anyone who point out on this problem in newsgroup is treated 
as a fool and is sent to study IEE 754 standard.


Re: Why is string.front dchar?

2014-01-14 Thread Maxim Fomin

On Monday, 13 January 2014 at 23:10:04 UTC, TheFlyingFiddle wrote:
I'm curious, why is the .front property of narrow strings of 
type dchar?

And not the underlying character type for the string.


The root of the issue is that string literals containing 
characters which do not fit into signle byte are still converted 
to char[] array. This is strictly speaking not type safe because 
it allows to reinterpret 2 or 4 byte code unit as sequence of 
characters of 1 byte size. The string type is in some sense 
problematic in D. That's why the fact that .front returns dhcar 
is a way to correct the problem, it is not an attempt to 
introduce confusion.


Re: Question on static declaration

2014-01-11 Thread Maxim Fomin

On Saturday, 11 January 2014 at 17:50:01 UTC, Eric wrote:

Apparently the line,

static shared static int x;

will compile just fine.  Is this sort of a bug,
or does it mean something different from just

static shared int x;

?

Also, the line,

static static static int x;

will also compile.  Does this mean x is extra static?

-Eric


It is a particular example of current nonsense in attribution 
parsing. This compiles:


void main()
{
pure int i;
@disable int di;
nothrow int ni;
}

as well as more sophisticated nonsense. Issue is filed is 
bugzilla, so it will be fixed sooner or latter, current policy is 
to ignore it.


Re: Type inference and overloaded functions

2013-12-12 Thread Maxim Fomin

On Friday, 13 December 2013 at 04:13:04 UTC, Kenji Hara wrote:

On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:
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.


Kenji Hara


I think there is consensus that in @safe code this should be 
blocked.


Re: Is this reasonable?

2013-12-05 Thread Maxim Fomin

On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote:


Is this unavoidable, or could the compiler safely make the 
conversion implicitly?


It is example of notorious phenomemena called integer 
promotions and usual arithmetic conversions. It is unavoidable 
given Walter's decision to keep this C stuff in D.


Re: Is this reasonable?

2013-12-05 Thread Maxim Fomin
On Thursday, 5 December 2013 at 19:51:52 UTC, Ary Borenszweig 
wrote:


But to make array.length uint by default and have these 
surprises all of the time just because a negative length 
doesn't make sense... I don't know, I feel it's not the right 
way to do it.


Length of array type is not uint by default. This is second issue 
in array.length.


Re: Is this reasonable?

2013-12-05 Thread Maxim Fomin
On Thursday, 5 December 2013 at 18:26:48 UTC, Jonathan M Davis 
wrote:

On Thursday, December 05, 2013 19:16:29 Maxim Fomin wrote:
On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale 
wrote:

 Is this unavoidable, or could the compiler safely make the
 conversion implicitly?

It is example of notorious phenomemena called integer
promotions and usual arithmetic conversions. It is 
unavoidable

given Walter's decision to keep this C stuff in D.


To be fair, you can't solve the problem automatically. It's 
fundamentally
wrong to compare signed and unsigned values, and doing either 
the conversion
to unsigned or to signed could be wrong (or both could be 
wrong), depending on
the values. The best that could be done would be to warn about 
the comparison

or to make it an error.

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

- Jonathan M Davis


Warning would be an option, but AFAIK Walter does not like 
warnings, so it is unlikely to be implemented.


Re: enum value vs. immutable

2013-12-03 Thread Maxim Fomin

On Tuesday, 3 December 2013 at 08:28:23 UTC, Ali Çehreli wrote:


That works for some types as both enum and immutable have their 
problems:


* enum is no good for arrays and AAs as it is very likely to be 
unnecessarily slow.


* immutable is no good for types that contain mutable 
references at least during assignment:


struct S
{
int i;
int[] others;
}

void main()
{
auto a = S(42);
immutable b = a;
// Error: cannot implicitly convert expression (a) of type S to 
immutable(S)

}


Kenji is working on this
http://wiki.dlang.org/DIP49


 It is C++ism like follwoing code:

 struct S { public: this(type){} ... }

 or

 static Type t; // in module scope

Both of those do happen. ;)

Ali


Yes, this isn't good at all.


Re: Associative array references

2013-12-02 Thread Maxim Fomin

On Monday, 2 December 2013 at 13:30:44 UTC, Atila Neves wrote:

Bug or feature? This one caught me by surprise:

void main() {
{
int[string] aa[string];
aa[foo][bar] = 1;
assert(aa[foo][bar] == 1); //ok

auto aa2 = aa;
aa2[boo][dar] = 2;
assert(aa[foo][bar] == 1); //ok
}

{
int[string] aa[string]; //not set to anything yet

auto aa2 = aa;
aa2[boo][dar] = 2;
assert(aa[foo][bar] == 1); //oops
}
}

It seems that assigning an AA to another makes both point at 
the same data only if the first array has data to begin with. 
Is that the expected behaviour?


Atila


I would say it is consequence of current implementation, and, 
taking into account ongoing efforts to rewrite AA implementation, 
this special detail of null AA behavior may one day be gone.


Re: Foreach loop behaviour and manipulation

2013-12-02 Thread Maxim Fomin

On Friday, 29 November 2013 at 00:41:16 UTC, bearophile wrote:

H. S. Teoh:

Modifying the loop variable of a foreach is, in general, a 
risky move.


Right. In my opinion D programmers should learn that this is 
the preferred idiom of using foreach ranged loops:


foreach (immutable i; 0 .. n) {}

Bye,
bearophile


Unfortunately if you iterate over delegates, this may break 
immutability.


See 
http://forum.dlang.org/thread/felqszcrbvtrepjtf...@forum.dlang.org?page=1


Re: enum value vs. immutable

2013-12-01 Thread Maxim Fomin

On Monday, 2 December 2013 at 07:27:25 UTC, Ali Çehreli wrote:

On 12/01/2013 09:57 PM, CJS wrote:

 I was reading the enum page of Ali Çehreli's (excellent) D
book
 (http://ddili.org/ders/d.en/enum.html), and I'm confused by
an enum
 value (not enum type), such as
 enum secondsPerDay = 60 * 60 * 24;
 In that situation I would have used an immutable variable. Is
there any
 reason to prefer enum vs. immutable when defining constants?

After realizing the other day that even 'static const' can be 
used for template instantiations, I am not sure myself anymore. 
:)


Simple rules are great. I wanted to accept the following 
guidelines, none of which are clear cut:


1) Prefer enum first because enum values can be used for 
template instantiations.


You can instatiate templates not only with enums. Main pro for 
enums is that they are CT values.




3) Prefer const last as it erases immutable attribute if 
present. (We can't know just by looking at a reference to const 
whether the original value has been immutable or mutable.)


It is interesting to know where such advices come from. Const in 
D is useless except as as parameter qualifier, method qualifier, 
tool to alias const data and non-const data and as qualifier of 
some field - member of aggregate.


Writing code like

const int i = SOME_VALUE;

is loosing advantages of immutable or enum while gaining nothing 
in return.


It is C++ism like follwoing code:

struct S { public: this(type){} ... }

or

static Type t; // in module scope




Re: Destructors calling sequence

2013-11-29 Thread Maxim Fomin

On Friday, 29 November 2013 at 16:48:58 UTC, Temtaime wrote:

Hi !
http://dpaste.dzfl.pl/53d9a59e

How i can enforce that ~A will be called after ~B ?

I'm writing 3D engine and it's critical to me.

Thanks for yours aid !


It is impossible to do this directly given current gc 
implementation, but you can do something like that:


class A
{
   bool reset;
   void delegate dtor();
   ~this()
   {
  if (!reset)
 dtor();
   }
}

class B
{
   A a;
   bool run;
   ~this() { if (!run) a.reset = true; run = true; }
}

A a = new A;
B b = new B;
b.a = a;
b.a.dtor =  b.__dtor;


Re: From D struct to C struct

2013-11-18 Thread Maxim Fomin

On Monday, 18 November 2013 at 14:15:02 UTC, Namespace wrote:

On Monday, 18 November 2013 at 10:09:12 UTC, qznc wrote:

On Monday, 18 November 2013 at 08:32:11 UTC, Namespace wrote:
I found another approach. It avoids the GC and the Heap: A 
Circular Buffer:

http://dpaste.dzfl.pl/cf1e7afb

That should work.


It is unsafe, but might work in your specific case.

The problem is that future changes might exhibit memory 
corruption, if the limit of your buffer is too low. Would 
probably be a hell to debug.


Yes, but I know I never need more than 4 C pointer at the same 
time.


I think there is bigger problem (and bigger memory error) here. 
When you inside struct method load pointer to some field you 
cannot rely that after leaving the method, the pointer will be 
safe. Structs are almost often located in stack and there are 
movable, which means that struct stack 'this' pointer may change.


There is even issue in bugzilla with example when delegate 
touches struct field and is invoked at some point later which 
causes silent memory error because delegate pointer became 
invalid.


Re: From D struct to C struct

2013-11-18 Thread Maxim Fomin

On Monday, 18 November 2013 at 16:03:33 UTC, Namespace wrote:

On Monday, 18 November 2013 at 15:27:46 UTC, Maxim Fomin wrote:


I think there is bigger problem (and bigger memory error) 
here. When you inside struct method load pointer to some field 
you cannot rely that after leaving the method, the pointer 
will be safe. Structs are almost often located in stack and 
there are movable, which means that struct stack 'this' 
pointer may change.


There is even issue in bugzilla with example when delegate 
touches struct field and is invoked at some point later which 
causes silent memory error because delegate pointer became 
invalid.


So I should change it from C[8] to C[] = new C[8]; to be sure?


Yes.


Re: longjmp crashes on Windows

2013-11-16 Thread Maxim Fomin
On Saturday, 16 November 2013 at 14:14:24 UTC, Piotr Podsiadły 
wrote:

Hello,

I'm trying to use setjmp and longjmp on Windows with DMD 
compiler (version 2.064). When compiled as 64-bit application, 
it works, but 32-bit version crashes inside longjmp. What 
should be changed to get it to work?


I tried changing value of _JBLEN for x86 to some bigger number 
(like 1024), but it crashes too.


Code:

import std.stdio;

version(Windows)
{
version(X86)
enum _JBLEN = 64;
else version(X86_64)
enum _JBLEN = 256;
else version(IA64)
enum _JBLEN = 528;

alias ubyte[_JBLEN] jmp_buf;

extern(C)
{
int _setjmp(ref jmp_buf _Buf);
void longjmp(ref jmp_buf _Buf, int _Value);
}

alias _setjmp setjmp;
}


What kind of problem you try to solve by manual defining system 
data structures? Why not use platform independent valid 
declarations? Why did you decide that _JBLEN is 64, 256, 528 
according to version? Why did you decide that having _JBLEN bytes 
filled with zeros is a valid value of jmp_buf object? Why should 
setjmp/longjmp take buffer by reference?



void main()
{
jmp_buf env;
uint i;
if(setjmp(env)  3)
{
writeln(ping);
longjmp(env, ++i);
}
writeln(done);
}

Call stack:

c:\Users\vbox\Documents\testtest.exe
ping
object.Error: Access Violation

0x00423F78 in _local_unwind
0x004214D0 in longjmp
0x0040B300 in void rt.dmain2._d_run_main(int, char**, extern 
(C) int function(char[][])*).runAll().void __lambda1()
0x0040B2D3 in void rt.dmain2._d_run_main(int, char**, extern 
(C) int function(char[][])*).runAll()

0x0040B1EB in _d_run_main
0x0040B018 in main
0x0042142D in mainCRTStartup
0x754F3677 in BaseThreadInitThunk
0x77959F42 in RtlInitializeExceptionChain
0x77959F15 in RtlInitializeExceptionChain



Try to use proper version of setjmp/jmp_buf from druntime.
By the way, why did you decide to use it in D language in a first 
place?


Re: UFCS with constructors

2013-11-06 Thread Maxim Fomin

On Wednesday, 6 November 2013 at 17:10:34 UTC, Ali Çehreli wrote:


I would be very surprised if unary - produced a different 
type from the operand:


Ali


Operator does not produce type, it produces value of expression, 
and type of expression happens not to be the type you expected. 
But such expectations need not correspond to language rules (try 
to think from from language laywer perspective). In bearophile 
case, I guess Typedef!double overloads unary operator which 
returns double which is primary reason for such behavior.


Re: How to re-initialise an associative array.

2013-11-06 Thread Maxim Fomin

On Wednesday, 6 November 2013 at 17:49:41 UTC, H. S. Teoh wrote:


The GC will take care of cleaning up the old data.


T


Unfortunately it will not take care of calling struct destructors.


Re: UFCS with constructors

2013-11-06 Thread Maxim Fomin

On Wednesday, 6 November 2013 at 18:02:32 UTC, Ali Çehreli wrote:

 But such
 expectations need not correspond to language rules (try to
think from
 from language laywer perspective).

I still argue that the expression -expr must have the same type 
as expr.


 In bearophile case, I guess
 Typedef!double overloads unary operator which returns double
which is
 primary reason for such behavior.

That's what I deduced from qznc's post and tried to mean that 
such behavior would be confusing to programmers.


Ali


I think that reason for such behavior is the way used defined 
operator overloading functions are implemented, not the language 
per se, so programmers confuse themselves.


Re: Trait keyword.

2013-11-02 Thread Maxim Fomin

On Saturday, 2 November 2013 at 21:28:46 UTC, Adam D. Ruppe wrote:
On Saturday, 2 November 2013 at 20:45:28 UTC, TheFlyingFiddle 
wrote:
I'm basically wondering why the __traits keyword looks so 
horrible.


I think it looks beautiful and wished all the keywords used the 
leading underscores.


This is about taste and it is subjective.

The reason is that the __keywords are reserved, so they don't 
conflict with user words. __traits was added somewhat late into 
the language, so using a reserved word for it meant less broken 
code. Now you can still call your own variables traits - I'd 
love it if all keywords were this way so we could, in theory at 
least, use the anywhere.


Statement that in D __identifiers are reserved is dubious as 
nothing stops users from defining them (I was under impression 
that D really prevents but is actually was misconception). D 
incorporates substantial amount of C but does not impose similar 
limitations on reserved identifiers (__identifier is not the only 
one reserved in C). Futhermore, dmd internally generates lots of 
identifiers and does not prohibit user from 'picking up' them - 
it is huge amount of accept-invalid code. There is also a bug 
that code


struct S { void __foo(){} void bar() {} }
pragma(msg, __traits(allMembers, S));

printed only 'bar' since some commit in 2.064 (I haven't tested 
current version). Except these issues, '__identifiers' and 
'identifiers' are pretty much the same. Using the former bears 
some 'risk' that such identifiers may hijack some symbol but it 
is low.


I believe that __trais was chosen because of combination of 
unwillingness to intervene into 'identifiers' category (in some 
sense it is desire to 'stabilize the language' by pretending that 
language is 'stable') and belief that introducing new 
features/fixing existing features should not break existing code 
(but it is inconsistent policy as the same time pretty much code 
is broken each release, and there is pretty much another code 
which will very likely be broken in the future). Anyway, the 
decision seems to be within the path which was followed by C 
(_Noreturn, _Thread_local), so it is not that bad.




Re: fieldPostBlit - what is wrong with this and workarounds

2013-10-31 Thread Maxim Fomin
On Thursday, 31 October 2013 at 14:03:28 UTC, Daniel Davidson 
wrote:

Given this code:

  import plus.tvm.rate_curve;
  struct T {
RateCurve m;
  }
  struct S {
const(T) rc;
  }

I get this error: Error: mutable method 
plus.models.dossier.__unittestL42_1.T.__fieldPostBlit is not 
callable using a const object


Is this fundamentally incorrect? I abandoned immutable in hopes 
that const would be more manageable and so far it has. But 
these types of issues still crop up and stop me in my tracks.


What are the requirements on RateCurve and T for this to work?

Thanks
Dan


D language is fundamentally incorrect here. There are sufficient 
issues in bugzilla (one which bearophile provided is actually 
relevant, it shows same problem from a little bit different 
aspect) and the problem tends to pop up quire regularly. It looks 
like nothing is done because it is design issue and although 
there were attempts to come up with, no idea is viewed as final 
solution. The easiest way to solve problem is to strip const.


Re: structs holding on to reference data by pointer

2013-10-31 Thread Maxim Fomin
On Thursday, 31 October 2013 at 17:34:21 UTC, Daniel Davidson 
wrote:

On Thursday, 31 October 2013 at 16:16:36 UTC, bearophile wrote:


That's wrong code, you are escaping a reference to memory (of 
rc variable) allocated in the stack frame of foo(). The D 
compiler is not smart enough to recognize the bug. There are 
optimizations that patch and avoid this bug (like inlining, or 
allocating rc inside the stack frame of the main) but you 
can't rely on them.




Ahh ok. Because of issues with const members (copying them when 
they are composed in other classes does not work well) I'm 
trying to get around the copy by storing reference data as 
const(T) *. This is why I'm asking. So here are some follow ups:


- As I see it there is grave risk. Is the risk introduced by 
the fact that I am storing a member as const(T)*?


Risk is that pointer to local variable is escaped, not because it 
is stored in const qualified pbject.


- I assume that if I had created the RC instance on the heap 
there would be no problems. Is there a way in general to ensure 
that a const(T)* is referring to something on the heap as 
opposed to the stack (ideally at compile time).


Yes, you can explicitly allocate on heap. You can check whether 
data is on heap, stack, tls, or just global object by inspecting 
pointer at runtime. Ideally there would be such function in 
druntime. It is impossible to do this in CT (except if comiler 
support flow analysis and can prove in some scenarious that data 
is on stack or not, but due to separate compilation it is 
impossible to do in general case) (and probably shouldn't).


- What is the root problem - having a const(T)* member which 
then requires code to take address, or taking address? My first 
thought was, just never take address of local static variable - 
which is generally good advice. But once you are in a function 
that takes ref const(T) you can take the address of that as 
well - see modification below. This suffers the same problem 
but in a less obvious way.


Any suggestions welcome.

Thanks
Dan

import opmix.mix;
import plus.tvm.rate_curve;
import std.stdio;

struct RC {
  this(this) { data = data.dup; }
  int[] data;
}

struct T {
  const(RC) *rc;
  void goo() {
writeln(Data is , rc.data);
  }
}

T goo(ref RC rc) {
  return T(rc);
}

T foo() {
  RC rc = { [1,2,3] };
  writeln(Address is , rc);
  return goo(rc);
}

void main() {
  T t = foo();
  t.goo();
  writeln(Address is , t.rc);
}


Yes, this is known issue. There are lots of other tricks to break 
the language.


Re: fieldPostBlit - what is wrong with this and workarounds

2013-10-31 Thread Maxim Fomin
On Thursday, 31 October 2013 at 17:22:07 UTC, Daniel Davidson 
wrote:


I'm think you may be correct... but what specifically is 
incorrect about the language?
When I see __fieldPostBlit I get the feeling it is more an 
implementation issue than the language.


__postblit also looks like implementation detail but it is same 
problem. Field postblit means that aggregate has some members 
which have postblits so they should be called. This is same 
problem which blows in higher level.


If as you suggest, D language is fundamentally broken - is it 
possible we can just get a plan for fixing it? To me this seems 
like a huge design hole and I come back to the threads with 
questions again and again and I really don't know how others 
manage the use of const/immutable.


This is probable tenth thread about const postblits which I do 
remember for all my (only) 2 years in D. D2 (version currently in 
use) dates back to 2004 AFAIK and Andrei (helping to design the 
language) is in D since 2006, also AFAIK. Draw your own 
conclusions.


I've already given up on immutable. If I have to strip const as 
well then that is a huge pain and unfortunate since the concept 
seems sound and well argued in TDPL. Trying to mess with 
mutable/const/immutable on mostly working code is like playing 
whack a mole.


One can do: 1) revise the design to challange whether consts are 
really necessary 2a) use workarounds like const pointer 2b) use 
cast to break const or another tricks (explicit casts are better 
because holes in type system may be fixed in some point in the 
feature)


Re: structs holding on to reference data by pointer

2013-10-31 Thread Maxim Fomin

On Thursday, 31 October 2013 at 18:51:46 UTC, bearophile wrote:

Maxim Fomin:

You can check whether data is on heap, stack, tls, or just 
global object by inspecting pointer at runtime. Ideally there 
would be such function in druntime.


This seems like a nice enhancement request for Bugzilla :-) Are 
you going to open it? It seems useful for me too.




You are expert in making enhacement request :)

It is impossible to do this in CT (except if comiler support 
flow analysis and can prove in some scenarious that data is on 
stack or not, but due to separate compilation it is impossible 
to do in general case) (and probably shouldn't).


You can do it even with separate compilation (at compile time) 
if your language has different kinds of pointers as Rust. 
Perhaps in D this can be done using Phobos-defined smart 
pointers.


Bye,
bearophile


But I don't believe that D being system laguage will diverge from 
traidtional C/C++ pointer model. Right, in runtime smart pointers 
can probably do some job by guessing allocation kind looking at 
pointer.


Re: Bug in RefCounted?

2013-10-29 Thread Maxim Fomin

On Monday, 28 October 2013 at 20:43:01 UTC, Ali Çehreli wrote:


What is the purpose of writeln in that delegate? Obviously, to 
print 1. Yet it doesn't happen that way. Is this accepted to be 
a bug? Should the programmer 'new' the object instead?


Ali


In my opinion it is a corner case, a consequence of two things: 
1) need to allocate struct into heap due to lambda 2) need to put 
dtor invocation in the end as usual.


Re: Bug in RefCounted?

2013-10-29 Thread Maxim Fomin
On Tuesday, 29 October 2013 at 12:03:09 UTC, Rene Zwanenburg 
wrote:

On Monday, 28 October 2013 at 19:40:26 UTC, Maxim Fomin wrote:
The fact that structs are movable and there is too few struct 
runtime reflection makes them noncollectable. However, you can 
wrap struct inside class, in such case struct dtor will be 
called.


Yeah, if wrapping inside a class wouldn't work either we'd be 
in a whole new world of hurt.


But what do you exactly mean by noncollectable? And what does 
movability have to do with that? I think the memory will be 
reclaimed without a problem, so new-ing a struct without 
destructor would be fine. This doesn't leak:


struct S
{
int i;
}

void main()
{
while(true)
{
new S;
}
}


I would say it leaks because dtor (if defined) is not called, 
although memory is reclaimed at some point. In my opinion struct 
movability is a problem for heap struct collection because it is 
hard to say judging to struct stack/heap pointer whether it 
should be collected or not. If you look at output from previous 
example,


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

you will see that adressess are different and refer to stack, yet 
object is in the heap. By the way, there is another issue - if 
you have delegate inside struct method touching some field, than 
invoking such delegate after returning from method may break 
memory, because delegate references 'this' struct pointer, but it 
may be changed across lifetime. I am not sure whether some 
algorithm for solving heap struct collectibility can be made, but 
I don't have any idea right now.


Re: Types soup with enum and bool

2013-10-29 Thread Maxim Fomin

On Tuesday, 29 October 2013 at 12:43:17 UTC, bearophile wrote:

This code is accepted by the D compiler:


enum Foo { A, B, C }
void main() {
bool[5] bools;
auto b = bools[2] != Foo.C;
bools[2] = Foo.A;
}


Who is that likes such kind of code? What are the advantages of 
accepting such kind of code? I can see the disadvantages and 
risks.


Bye,
bearophile


Probably may be related to even worse issue:

import std.stdio;

void foo(bool b) { writeln(bool); }
void foo(long l) { writeln(long); }

void main()
{
foo(0); // bool
foo(1); // bool
foo(2); // long
int i = true;
foo(i); // long
}

If reasons for accepting yours and this example are the same, 
then this is by design (to be more precise, the part which is 
related to bool types being essentially kind of integer types + 
VRP + overloading rules).


Re: Bug in RefCounted?

2013-10-29 Thread Maxim Fomin

On Tuesday, 29 October 2013 at 17:57:01 UTC, Ali Çehreli wrote:

On 10/29/2013 08:47 AM, Maxim Fomin wrote:

On Monday, 28 October 2013 at 20:43:01 UTC, Ali Çehreli wrote:


What is the purpose of writeln in that delegate? Obviously, 
to print
1. Yet it doesn't happen that way. Is this accepted to be a 
bug?

Should the programmer 'new' the object instead?

Ali


In my opinion it is a corner case, a consequence of two 
things: 1) need

to allocate struct into heap due to lambda 2) need to put dtor
invocation in the end as usual.


As a continuation of this sub thread, I've opened the following 
thread in the D newsgroup:


  http://forum.dlang.org/post/l4osr0$2f3q$1...@digitalmars.com

Ali


I did this in 2 January 
(http://forum.dlang.org/thread/lpljpfjxwobniglwn...@forum.dlang.org) 
and received exactly zero responces.


Re: Types soup with enum and bool

2013-10-29 Thread Maxim Fomin

On Tuesday, 29 October 2013 at 18:23:03 UTC, bearophile wrote:

Ali Çehreli:


 enum Foo { A, B, C }
 void main() {
bool[5] bools;
auto b = bools[2] != Foo.C;
bools[2] = Foo.A;
 }
...
There was a long discussion about that. Walter was happy that 
bool was a integer type. Many of us had objections:


My problem is mostly with enums. I don't remember Walter 
explaining the rationale of the D enum conversion design. I 
prefer the C++11 enums.


Bye,
bearophile



Bools being integer types is reason of your problem with enums. 
Relevant lines from your code are translated to:


bool b = 0 != 2;
bools[2] = 0;

taking into account that 'bool' is integer type having capacity 
to represent values 0 and 1.


Re: Types soup with enum and bool

2013-10-29 Thread Maxim Fomin

On Tuesday, 29 October 2013 at 21:24:35 UTC, bearophile wrote:

Maxim Fomin:


Bools being integer types is reason of your problem with enums.


The reason of that problem of mine with enums is that they 
convert implicitly to integers. And I still don't know the 
original rationale of Walter of this design mistake.


Bye,
bearophile


It works according to spec: A named enum member can be 
implicitly cast to its EnumBaseType, but EnumBaseType types 
cannot be implicitly cast to an enum type. 


In this respect D enums behave like C enums.


Re: Class References

2013-10-28 Thread Maxim Fomin

On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:

Is it possible in D to create an enum of class references?
Something around the lines of:

enum ClassReferences : Interface {
CLASS1 = ClassOne,
CLASS2 = ClassTwo
}


You can define class references in module scope and initialize 
them in module constructor. This will not help if you want to 
have working classes in compile time, but may be useful in 
runtime.


Re: Class References

2013-10-28 Thread Maxim Fomin

On Monday, 28 October 2013 at 12:10:37 UTC, John Colvin wrote:

On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:

Is it possible in D to create an enum of class references?
Something around the lines of:

enum ClassReferences : Interface {
   CLASS1 = ClassOne,
   CLASS2 = ClassTwo
}


Short answer: No

Long answer: the enum values must be compile-time constants, 
that's what enums are all about. Addresses and references are 
not compile-time constants.


This is an arbitrary limitation imposed by Don and I disagree 
with him. According to opinion you presented providing classes at 
CT requires having addresses but it can be viewed other way - 
providing classes at CT requires some valid value which should be 
preserved for using in RT. For example, nobody complains that 
having enumeration constant or module scope immutable qualified 
basic type int at CT requires to have some address. Although 
int belongs to value type category, int as module variable has 
address. Example to illustrate issue:


enum E : int[] { A = [0,1] }

immutable EI = [0,1];

enum EE = [0, 1];

void main()
{
   E e1, e2;
   assert (e1 == e2  e1 == [0,1]);
   e1[0] = 1;
   assert(e2[0] == 0);
   //EI[0] = 1; // Error: cannot modify immutable expression EI[0]
   assert(EI[0] == 0);
   // EE[0] = 1; // Error: constant [0, 1][0] is not an lvalue
   assert(EE[0] == 0);
}

Dynamic arrays like classes are reference types, so there are 
addresses involved. Not only this shows that CT references are 
possible, but that dmd can support similar behavior for classes. 
Replace int[] with some class and you will arrive that there is 
something wrong about idea that enum values must be compile-time 
constants, addresses and references are not compile-time 
constants, thus reference types can't be compile-time 
expressions.


Re: Bug in RefCounted?

2013-10-28 Thread Maxim Fomin

On Monday, 28 October 2013 at 16:53:11 UTC, monarch_dodra wrote:
On Monday, 28 October 2013 at 10:07:15 UTC, Rene Zwanenburg 
wrote:
Yeah, I'd like to know this as well. I do remember structs 
allocated on the heap don't have their destructors called at 
all due to the GC not being precise, I think.


But one object allowed to be destructed multiple times? That 
sounds really bad.. If that's true a lot of my code is 
probably incorrect.


Hum... I seem to remember having replied earlier, but I guess I
forgot to hit send.

In any case, I could be mistaken, but I simply know that under
certain circumstances, it can happen.


OK


I don't know if that's a
bug though. I'll try to find the cases where it happens.



So do you *know* cases or suspect that they may exists? Or 
remember some bug issue?


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.




Re: Bug in RefCounted?

2013-10-28 Thread Maxim Fomin

On Monday, 28 October 2013 at 10:07:15 UTC, Rene Zwanenburg wrote:

On Sunday, 27 October 2013 at 23:33:55 UTC, Ali Çehreli wrote:
That's news to me. I know that objects may never be destroyed 
but why multiple times? How many lives do they have? ;)


Yeah, I'd like to know this as well. I do remember structs 
allocated on the heap don't have their destructors called at 
all due to the GC not being precise, I think.


The fact that structs are movable and there is too few struct 
runtime reflection makes them noncollectable. However, you can 
wrap struct inside class, in such case struct dtor will be called.




But one object allowed to be destructed multiple times? That 
sounds really bad.. If that's true a lot of my code is probably 
incorrect.


I think one need to be aware of this bug (no dtor), rather than 
cases when dtor is called multiple times.


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); }
}

int this_throws() { throw new Exception(); }

void foo(S s, int i) {}

void main()
{
   try { foo(S(1), this_throws); }
   catch(Exception e) {}
}


Re: Array of struct with floating point members seg faults

2013-10-26 Thread Maxim Fomin

On Saturday, 26 October 2013 at 17:46:31 UTC, Ali Çehreli wrote:

The following program seg faults:

struct Point
{
double x;
double y;
}

void main()
{
Point[1] arr;
}

Any combination of float and double members exhibit the same 
bug as long as the size of the struct is 16.


I vaguely remember seeing a similar bug before but I can't find 
it in bugzilla.


Ali


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

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


Re: Copying to an immutable array in a costructor

2013-10-24 Thread Maxim Fomin

On Thursday, 24 October 2013 at 10:58:30 UTC, bearophile wrote:

Jonathan M Davis:

It's a compiler bug. immutable data should not be initialized 
more than once.


My point was another one, regarding this refused code:


import std.algorithm: copy;
immutable int[2] data;
static this() {
[10, 20].copy(data[]); // Error.
}
void main() {}


Bye,
bearophile


Reduced:

immutable int[] data;

void foo(int[] data) {}

static this()
{
foo(data);
}


Re: Copying to an immutable array in a costructor

2013-10-24 Thread Maxim Fomin

On Thursday, 24 October 2013 at 07:02:25 UTC, bearophile wrote:

This shows a limitation of the D type system:


import std.algorithm: copy;
immutable int[2] data;
static this() {
foreach (i, x; [10, 20]) data[i] = x; // OK
data[] = [10, 20]; // OK
[10, 20].copy(data[]); // Error.
}
void main() {}


Bye,
bearophile


Because control flow check for immutable data is almost absent. I 
don't know any situation where are such checks (except 
constructors).


There is similar issue with respect to initializsing immutable 
member field in struct constructor. There is issue in bugzilla 
filed for it (it looks like it will be fixed), where Andrei 
proposed a concept of cooked object, basically implying control 
flow for initializaing immutable members. I think that the code 
you posted as an additional case for the issue.


Re: Warnings/What should I know?

2013-10-18 Thread Maxim Fomin

On Friday, 18 October 2013 at 06:56:49 UTC, monarch_dodra wrote:

On Friday, 18 October 2013 at 06:13:38 UTC, DDD wrote:
I'm learning D. I'm curious about surprises I may get. I 
typically use C++, C# and javascript


Off the top of my head, I think the biggest one is that D 
doesn't offer default constructors. Instead, it only has a 
default value initialization.


EG:

S s;
S s = S.init;
S s = S();
S s = S(5);

The first 3 lines are more or less equivalent.


Not always actually.



This can bite you in the ass if you write something like:

struct S
{
this(int i = 5)
{}
}
S s = S(); //Does *not* call the constructor with the value 5.



One can bite in the ass even more in case of

struct S { @disable this(); } and using S.init or

void foo () { int i; struct S { int bar() { return i; } } and 
also using S.init





Finally, D doesn't have copy constructor. It has something a 
bit sweeter called postblit. Basically, you first bitcopy the 
object you want to duplicate, and then, a function called 
postblit gets called, which does the work that is required 
(should any be required). What's nice about this is that the 
target object and source object never actually communicate.




How much are there threads asking what is wrong with the language 
when there are const/immutable structs and postblit :) ?





Re: does cast make an lvalue appear to be an rvalue

2013-10-16 Thread Maxim Fomin
On Wednesday, 16 October 2013 at 17:05:25 UTC, Daniel Davidson 
wrote:
The code below fails to compile due to the last line. I was 
hoping casting away immutable would allow the call to foo. I 
think it is not accepted because of the rval to ref issue. If 
that is the case, how can foo be called by casting?


I'm not a fan of casting but I'm finding cases where it is the 
only recourse to create immutable data using impure functions 
that should be pure.


Thanks
Dan

import std.conv;

struct T {
  int[] i;
  string[string] ss;
}

void foo(ref T t) {
}

void main() {
  T t1;
  auto t2 = immutable T();
  foo(t1);
  foo(cast()t2);
}


foo([cast()t2][0]);

(It would be good to have compound literals like in C)


Re: Understanding opAssign and 'alias this'

2013-10-14 Thread Maxim Fomin

On Monday, 14 October 2013 at 09:17:12 UTC, John Colvin wrote:
Everything is working fine except for the error on [2] when xxx 
== true, which I think is a bug.


minimised test:

struct A
{
void opAssign(A a) {}
}

struct B {
A a;
alias a this;
}

void main() {
A a;
B b;
b = a;
}

Error: function assign.B.opAssign (B p) is not callable using 
argument types (A)


This does not work (and need not) because compiler generates 
default function B.opAssign(B) which is really not callable using 
argument types (A).


Re: copying const struct

2013-10-14 Thread Maxim Fomin

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.


Re: copying const struct

2013-10-14 Thread Maxim Fomin

On Monday, 14 October 2013 at 13:56:58 UTC, Benjamin Thaut wrote:

Am 14.10.2013 13:54, schrieb Dicebot:
On Monday, 14 October 2013 at 11:45:30 UTC, Jack Applegame 
wrote:
On Monday, 14 October 2013 at 11:38:23 UTC, Benjamin Thaut 
wrote:

The line Bar2 b2 = bar2; would remove const from member

Seems strange, because b2.member is const by declaration.


Strange indeed and smells like a bug. `auto bar = 
Bar2(bar2.member)`

works so it should be assignable.


d.puremagic.com/issues/show_bug.cgi?id=9665


I don't see how this is related to the topic.


Re: Understanding opAssign and 'alias this'

2013-10-14 Thread Maxim Fomin

On Monday, 14 October 2013 at 10:45:26 UTC, Maurice wrote:

On Monday, 14 October 2013 at 09:32:15 UTC, Maxim Fomin wrote:

On Monday, 14 October 2013 at 09:17:12 UTC, John Colvin wrote:
Everything is working fine except for the error on [2] when 
xxx == true, which I think is a bug.


minimised test:

struct A
{
  void opAssign(A a) {}
}

struct B {
  A a;
  alias a this;
}

void main() {
  A a;
  B b;
  b = a;
}

Error: function assign.B.opAssign (B p) is not callable using 
argument types (A)


This does not work (and need not) because compiler generates 
default function B.opAssign(B) which is really not callable 
using argument types (A).


Then why does it work when replacing opAssign(A a) with 
opAssign(int)?


struct A {
void opAssign(int) {}
}

struct B {
A a;
alias a this;
}

void main() {
A a;
B b;
b = a; // This now compiles fine...
}


OK, it seems to be what actually causes the problem is implicit 
conversion from B to A. Situation depends on presence of 
A.opAssign(A ) because when compiler tries to resolve function 
call, it is confused between calling B.opAssign(B) and casting 
through alias this B to A and calling A.opAssign(A). When it 
realizes that there is no best match it throws error. Since 
argument B is casted to A, the error message looks so weird.


Re: copying const struct

2013-10-14 Thread Maxim Fomin

On Monday, 14 October 2013 at 17:38:22 UTC, Ali Çehreli wrote:

On 10/14/2013 10:33 AM, Kenji Hara wrote:

 On Monday, 14 October 2013 at 14:18:10 UTC, Maxim Fomin wrote:

 This is compilable using git head.

When I read that line ...

 Kenji Hara

... I was thinking about that person. :)

Thank you Kenji!

Ali


Right. Kenji is true D celebrity. Funniest thing happen in cases 
like this when he reports the bug himself and soon fixes it, 
later bug is hit by someone else but during reporting it is 
realized that bug is already fixed, pull is pushed to master and 
everyone salutes Kenji.


What bothers me is that some (in fact, probably many) delicate 
language cases are silently fixed by Kenji without proper 
documentation so D language has some sparse and obsolete spec, 
even more obsolete book and sporadic patches - just couple of 
developers are aware about each of them. When someone hits corner 
language case - weird compiler behavior it is general unknown 
what should compiler do, whether current behavior is bug or a fix 
for some other previous bug about which you are unaware of. When 
different parts of language interact, problem becomes even more 
complicated.


Re: Is there a way to see if .init has been set by the user?

2013-09-21 Thread Maxim Fomin

On Saturday, 21 September 2013 at 11:13:57 UTC, simendsjo wrote:
I want to know if a variable has changed .init, but I don't 
know if it's possible if the .init value is the same. Does 
anyone have a solution for this?


int a;
int b = 0;
pragma(msg, a.init); // 0
pragma(msg, b.init); // 0
// how can I see that b has = 0?


Strictly speaking this is an ill-posed question. Are talking 
about testing at runtime whether some variable was changed from 
init to some non-default value?


Re: Is there a way to see if .init has been set by the user?

2013-09-21 Thread Maxim Fomin

On Saturday, 21 September 2013 at 11:35:11 UTC, bearophile wrote:


init is part of a type and you can't change it.

Bye,
bearophile


Well, D wouldn't be D, if it did not allow something like this 
for aggregate types:


import core.stdc.string, std.stdio;

pure hack(T)(T value) if (is(T == class))
{
byte[] init_mem = new byte[T.classinfo.init.length];
memcpy(init_mem.ptr, cast(byte*)value, 
T.classinfo.init.length);

T.classinfo.init = init_mem;
}

class A
{
   int a;
}

pure foo(int val)
{
   A a = new A;
   a.a++;
   hack(a);
   return a.a + val;
}

void main()
{
   writeln(0.foo, 0.foo, 0.foo); // prints 1,2,3
}

And taking into accout some additional runtime magic, assertion 
below may fail:


class A { int i = 5; }
struct S { A a;}
S s;
assert(s.a is null);


Re: Unable to use tradional tools to find memory leaks

2013-09-21 Thread Maxim Fomin

On Saturday, 21 September 2013 at 14:30:19 UTC, Flamaros wrote:
I tried to used Valgrind (Linux) and Dr Memory (Windows) 
without success to find a big leak I have in my application.
But both tools can't launch my application without make it 
crash.


Is application crashing without these tools? Probably you have 
some bug which is detected by valgrind.


By the way, some pitfalls of using valgrind for testing D code:

1) Its implementation of float numbers at compile time is buggy 
(for example, there may be static asserts which are true when 
running under native envorionment and false under valgrind)
2) Dmd's codegen is sometimes not supported by valgrind (cannot 
execute some instructions which is rare case when something from 
D beats some tool outside)
3) It has some false positives regarding using uninitialized 
values especially during execution of GC code.


Do I need do something particular, to have a chance to see one 
of those tool working fine with my application?


If you run into #2 then you cannot fix it.

It can be really hard to find leaks manually, maybe some option 
of the gc can help me?


If you look into gc sources, you can found some testing code, but 
it needs druntime recompilation.


Re: Unable to use tradional tools to find memory leaks

2013-09-21 Thread Maxim Fomin
On Saturday, 21 September 2013 at 17:03:14 UTC, Brad Roberts 
wrote:

On 9/21/13 9:01 AM, Maxim Fomin wrote:

On Saturday, 21 September 2013 at 14:30:19 UTC, Flamaros wrote:
I tried to used Valgrind (Linux) and Dr Memory (Windows) 
without success to find a big leak I have

in my application.
But both tools can't launch my application without make it 
crash.


Is application crashing without these tools? Probably you have 
some bug which is detected by valgrind.


By the way, some pitfalls of using valgrind for testing D code:

1) Its implementation of float numbers at compile time is 
buggy (for example, there may be static
asserts which are true when running under native envorionment 
and false under valgrind)
2) Dmd's codegen is sometimes not supported by valgrind 
(cannot execute some instructions which is

rare case when something from D beats some tool outside)
3) It has some false positives regarding using uninitialized 
values especially during execution of

GC code.

Do I need do something particular, to have a chance to see 
one of those tool working fine with my

application?


If you run into #2 then you cannot fix it.


That's wrong.  Both DMD and Valgrind are software, both of 
which can be debugged and changed. Please file appropriate bug 
reports, hopefully with nicely minimized test cases.


No, that's true. DMD does produce some code which is executed by 
native envoronment but not by valrgind which is likely to be a 
valgrind bug. Sure, you can fix the issue belonging to a valgrind 
code if you are a valring developer, but this is not an option 
for most users.


Re: surrounded type modifier

2013-09-18 Thread Maxim Fomin

On Wednesday, 18 September 2013 at 13:23:10 UTC, Namespace wrote:

Code:

const { /// [1]
int a = 3;
}

void main()
{
const { /// [2]
int b = 4;
}
}


Why is [1] allowed, but not [2]?


Citing grammar:

FunctionBody:
BlockStatement
BodyStatement
InStatement BodyStatement
OutStatement BodyStatement
InStatement OutStatement BodyStatement
OutStatement InStatement BodyStatement

BlockStatement:
{ }
{ StatementList }

As you can see there is no room for attributes. Why dmd does not 
support attributes here is separate question - probably because 
such construct would be confused with lambda, but this is not a 
serious reason.


Re: surrounded type modifier

2013-09-18 Thread Maxim Fomin

On Wednesday, 18 September 2013 at 14:23:25 UTC, Namespace wrote:


Should I open an enhancement report?


Of course you are always free to open enhancement reports.


Re: User defined attributes use

2013-09-16 Thread Maxim Fomin

On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:
All your examples are great, thank you ! Is there a way to omit 
validate such that the compiler would call it implicitly ?


For example :

class C {
  ...
}

void fun(@nonNull C c) {
  ...
};

C c;
fun(c);  //compilation error since C is null


No, this isn't doable with UDAs because what you want requires 
runtime check. It is doable using other language features.


Re: User defined attributes use

2013-09-16 Thread Maxim Fomin

On Monday, 16 September 2013 at 16:50:43 UTC, Namespace wrote:
On Monday, 16 September 2013 at 15:47:36 UTC, ilya-stromberg 
wrote:
On Monday, 16 September 2013 at 15:12:05 UTC, Maxim Fomin 
wrote:

On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:
All your examples are great, thank you ! Is there a way to 
omit validate such that the compiler would call it 
implicitly ?


For example :

class C {
...
}

void fun(@nonNull C c) {
...
};

C c;
fun(c);  //compilation error since C is null


No, this isn't doable with UDAs because what you want 
requires runtime check. It is doable using other language 
features.


It's intresting how can I check that pointer is not null at 
the compile time. Can you print a example, please?
I know that we can use contract programming, but it requires 
runtime check.


That isn't possible. ;)


Similar effect can be achieved by different way. If some function 
takes S as parameter, one cannot pass directly instance of A or 
null - error will be issued which is some sort of compile-time 
protection.


class A
{   
int i;
}

struct S
{
A a;
A getA()
{
if (a is null)
a = new A;
return a;
}
alias getA this;
}

void main()
{
   S s;
   assert (s.i is 0);
   S ss = S.init;
   assert (ss.i is 0);
}

Unfortunately D does not have non-nullable classes which is a 
problem #1. Ideally structs should have default constructors 
(hello to those who miss them - problem #2) which could 
initialize class instance. Since they are absent, wrapping struct 
can be enhanced by inserting disabled constructor to ensure that 
no default struct instances with null references are created. 
However, since disabled constructors are also flawed (they don't 
prevent from producing T.init values by design and in some 
situations dmd is not smart enough to detect other cases by 
mistake) which is a problem #3, non-null classes can be simulated 
by code above using alias this + rt check. At least this works 
with two most problematic cases of struct initilialization: 
without initializer and with T.init value.


Re: User defined attributes use

2013-09-16 Thread Maxim Fomin

On Monday, 16 September 2013 at 19:21:47 UTC, H. S. Teoh wrote:

On Mon, Sep 16, 2013 at 08:56:17PM +0200, Namespace wrote:
[...]
I hate this NotNull struct hack. It is the same crap as the 
current

scope solution. BTW: I'm curious which built-in feature will be
removed next, maybe AA?

[...]

That wouldn't be a bad idea, actually. The current AA 
implementation is
so horribly broken, and so wrong in so many ways (there are at 
least 75
bugs related to AA's, some of the worst of which are 11037, 
11025,
10916, 10525, 10381, 10380, 10046, just to name a few), that it 
would do
a world of good to get rid of them altogether, and then 
reintroduce a

properly-designed library solution for them.

Of course, in the meantime everyone whose code breaks because 
of that
will form a mob to lynch me, so I'll have to survive long 
enough to get

the library solution working first. :-P


T


This demonstrates an interesting issue.

I think the primary reason why you are complaining about AAs is 
not because their implementation is flawed but because you can't 
fix it without dmd's internals knowledge :)
I always consider ability to hack dmd as important skill (at 
least in better language understanding because it is not defined 
by standard but by reference implementation) in D and that's why 
I am skeptical about many ideas proposed in form of DIPs - 
(unless they are proposed by those folks whose names often appear 
in dmd git commit log) because such proposals are not 
implementable without dmd's knowledge.
I remember one point made recently by one regular D forum 
participant that it is more important 'to know the language 
itself', 'to be abstract from one particular implementation' 
rather then knowing 'dirty implementation details' to propose 
DIPs and that those who know dmd will eventually implement DIPs - 
yet number of DIPs is close to 50 and judging by ratio 
implemented DIPs/total DIPs it obvious that such assumption 
doesn't hold.
As a result community is stuck with many features of language are 
flawed but they can be hardly fixed - plenty discussions and DIPs 
are generated but problems are not moved by an inch.
I think if a person who has druntime/phobos commits to fix some 
issue but no dmd's one should ask in a forum thread/directly 
address to Walter/Kenji for a help request (addressing Walter 
should happen without hesitation because he is the first to be 
blamed :) ).


Re: GC.collect bug ?

2013-09-15 Thread Maxim Fomin

On Friday, 13 September 2013 at 15:24:17 UTC, Temtaime wrote:

Hello for all !

I need to call all objects destructors in one place.
It's guaranted, that there is no objects instances.

I tried use GC.collect but it's produces strange results.

import std.stdio;
import core.memory;

class A {
~this() { writeln(`dtor`); };
};

void main() {
auto a = new A;
a = null;

GC.collect();
writeln(`after dtor`);
}

Output is:
after dtor
dtor

Why?

Regards.


For me it prints dtor - after dtor in case of pure compilation. 
In general it depends on compiler switches and druntime.


Re: override and package

2013-09-12 Thread Maxim Fomin

On Thursday, 12 September 2013 at 11:29:22 UTC, Jacob Carlborg
wrote:

On 2013-09-12 11:28, Namespace wrote:

But if I try to write 'override' before [1], I get this error 
message:
Error: function T4._apply cannot override a non-virtual 
function


This seems inconsistent. I really overwrite the method, and 
then I put

it in a package label.


I think the error message is pretty clear. You cannot override 
a function that isn't virtual. Private and package methods are 
not virtual.


Actually error message is misleading - it complains as T1._apply
would be non-virtual function which is wrong, it is one. The
problem is not in case of overriding non-virtual function but in
attempt to override virtual function (private) by non-virtual one
(package). I think error mesage should be something like:

Error: function T4._apply is non-virtual function and cannot
ovverride virtual function T1._apply


Re: A small and simple library for working with Qt.

2013-09-09 Thread Maxim Fomin

On Monday, 9 September 2013 at 08:06:17 UTC, MGW wrote:
I am D since the spring. Without a simple GUI to work hard. I 
tried to deal with QtD quick disconnects, but I failed. I had 
to develop its small and very simple library to work with Qt. 
The working title of QtE. Works in Windows 32 and Linux 32. A 
very simple idea. Instances of classes get through QtE.dll (in 
C++) and methods directly with Qt.




Unfortunately it sounds for me like yet attempt to build a
project which will be eventually given up. Are you sure you can
maintain the project? You wrote that you have recently read TDPL
- are you sure you are skilled enough? By the way, have you
thought about the reason why qtd doesn't work as you expected?


The source code and examples http://qte.ucoz.ru/


1) Ucoz.ru sites are notorious known for their quality. There are
some sites for projects written in D, for example dsourse.org
(probably there are others, but I don't know). By the way, if you
visit it, you will found how much projects were given up.

2) It is bad to promote something written in russian to
international group. You should definetly transalte some docs
before advertising your project.

By the way, I have read passages from main page of your site.
Something to comment:
- D is very far to be 'perfect' or even to be completed - there
are many features that either don't work or misbehave;
- D is not even close to be 'theoretically sound' (it is so on
paper rather in practice) - although it can classified as
strongly typed, its type system is compromised by many holes and
as ongoing discussions show, the language design has severe
issues.

This is important because one of D's troubles is gap between what
is promoted and what is provided which shouldn't happen.


Re: UFCS from within classes

2013-09-09 Thread Maxim Fomin

On Monday, 9 September 2013 at 17:07:59 UTC, Gyron wrote:
Hey there, I've experimented a little with UFCS today and ran 
into a problem.


My first question, which is kinda off-topic:
Why does D use the int type if you give it a number started 
with 0x(hex), shouldn't it use uint for that ?


It is not a bug, but a feature - see Decimal Literal Types table 
at http://dlang.org/lex.html



Here comes the real question:
I've extended the int by one function, which is the following 
(just to represent the problem):

public static T read(T)(int address)
{
return cast(T)1;
}

It works perfectly if the function stands alone (is global), 
but it doesn't work if I put it into a class (because I want it 
to be a bit more organized) like that:

class CMemory
{
public static T read(T)(int address)
{
return cast(T)1;
}
}

I'm not able to write something like:
0x1212.CMemory.read!bool();


So the question is, how can I make it to be able to be used 
like this:

0x1212.read!bool();

but still organized within the class ?


class CMemory
{
public static T read(T)(int address)
{
return cast(T)1;
}
}

alias CMemory.read!int CMread;

void main()
{
 0.CMread();
}

You can also use alias CMemory.read CMread; plus 0.CMread!int();


Re: Get class size of object

2013-08-11 Thread Maxim Fomin

On Sunday, 11 August 2013 at 15:28:44 UTC, JS wrote:

On Sunday, 11 August 2013 at 13:40:41 UTC, Timon Gehr wrote:

On 08/11/2013 06:25 AM, JS wrote:
Given an object, is there a built in way to get the size of 
the class

the object represents?


Yes.


Troll.


I guess he does not answer to the question as well as others do 
(including me) because of your misbehavior in D newsgroups. 
Solution to your question is obvious (built-in feature without 
any import). By the way, GC.sizeOf seems to return size of 
allocated page which is bigger than needed (for ex. it returns 16 
for a new int which is 4).




Re: Get class size of object

2013-08-11 Thread Maxim Fomin

On Sunday, 11 August 2013 at 16:16:26 UTC, bearophile wrote:

Maxim Fomin:

GC.sizeOf seems to return size of allocated page which is 
bigger than needed (for ex. it returns 16 for a new int which 
is 4).


The object instance contains a pointer to the virtual table, so 
there's a way to know what object it is. With that runtime 
information it should be possible to know the static size of 
the instance.


Bye,
bearophile


I do not know how you can calculate precisely object size by 
knowing that GC.sizeOf returns some aligned amount plus knowing 
something about virtual table. In case of simple objects (like 
ints) it does not work since int has no virtual table.


Anyway such guessing is useless since D provides feature to get 
size of class instance (if it is defined) even in comple time 
like enum S = _get_size ...


Re: Get class size of object

2013-08-11 Thread Maxim Fomin

On Sunday, 11 August 2013 at 16:36:53 UTC, Adam D. Ruppe wrote:

On Sunday, 11 August 2013 at 04:25:21 UTC, JS wrote:
Given an object, is there a built in way to get the size of 
the class the object represents?


try this:

Object obj = new Whatever();
auto size = typeid(obj).init.length;


Yes, this is answer to the question. By the way, it can be simply

enum S = typeid(Whatever).init.length;


Re: Is enum static?

2013-08-08 Thread Maxim Fomin

On Thursday, 8 August 2013 at 23:19:49 UTC, bearophile wrote:

Ali Çehreli:


More than that. :) enums are manifest constants.

Imagine that enum as being pasted into source code as is. This 
used to have surprising effects for AAs, as an enum AA would 
be instantiated from scratch everywhere that AA enum was used 
in the code.


I think that some time ago Don has proposed to disallow the 
'enum' tag for things like AAs, on the base that such behavour 
is not efficient, surprising, and maybe even not useful... I 
don't know where his proposal has gone later.


Bye,
bearophile


Enum trick is useful to workaround bug with aggregate members of 
reference types being initialized - all instances share reference 
to same data and to enable default struct constructors.


Re: Declare reference to variable ?

2013-07-29 Thread Maxim Fomin

On Monday, 29 July 2013 at 21:37:30 UTC, bearophile wrote:

Temtaime:


Why i cannot declare reference in D ?


I don't know the reasons. But maybe you can create a little 
struct with just a pointer inside and an alias this to a member 
function that returns a ref.


Bye,
bearophile


It doesn't work because alias this does not capture context 
pointer like delegate.


Re: Why is size_t unsigned?

2013-07-22 Thread Maxim Fomin

On Monday, 22 July 2013 at 15:04:25 UTC, monarch_dodra wrote:

On Monday, 22 July 2013 at 12:51:31 UTC, Andrej Mitrovic wrote:

On 7/22/13, JS js.m...@gmail.com wrote:

foreach doesn't allow you to modify the index to skip over
elements.


It does:

-
import std.stdio;

void main()
{
   int[] x = [1, 2, 3, 4, 5];
   foreach (ref i; 0 .. 5)
   {
   writeln(x[i]);
   ++i;
   }
}
-

Writes:
1
3
5


99% sure that's unspecified behavior. I wouldn't rely on 
anything like that.


Of course it is specified behavior.

ForeachStatement:
Foreach (ForeachTypeList ; Aggregate) NoScopeNonEmptyStatement

Foreach:
foreach
foreach_reverse

ForeachTypeList:
ForeachType
ForeachType , ForeachTypeList

ForeachType:
refopt BasicType Declarator
refopt Identifier

Aggregate:
Expression

This is an example of unspecified behavior:

import std.stdio;

void main()
{
int[] x = [1, 2, 3, 4, 5];
foreach (ref i; 0 .. 5)
{
__limit1631--;
writeln(x[i]);
}
}


Re: Why is size_t unsigned?

2013-07-22 Thread Maxim Fomin

On Monday, 22 July 2013 at 15:51:45 UTC, monarch_dodra wrote:
So... you are saying that if the grammar allows it, then the 
behavior is specified?




You may argue that although grammar does allows it, the feature 
is semantically not defined. However here it is known what ref 
int i means, to be more precise what you can do with objects 
marked with ref attribute.


All I see, is you iterating over references to the elements of 
an aggregate. The final behavior really depends on how said 
aggregate is implemented. If anything, if the behavior *was* 
defined, then I'd simply argue the behavior is wrong: I don't 
see why changing the values of the elements of the aggregate 
should change the amount of elements you iterate on at all. 
Also:


//
int[] x = [1, 2, 3, 4, 5];
foreach (ref i; iota(0, 5))
{
writeln(x[i]);
++i;
}
//

This also compiles, but I used a different aggregate, yet 
represents the same thing. Because it is implemented 
differently, I get a completely different result. Unless I'm 
mistaken, when a result depends on the implementation, and the 
implementation doesn't state what the result is, then that's 
what unspecified behavior is. (unspecified, not undefined).


This is different because in 0..5 ref int maps directly to 
variable modified, but in iota() it maps to value returned by 
.front property function and since it doesn't return by ref, 
refness is wiped out. Behavior is defined in both cases.



This is an example of unspecified behavior:

...


What is __limit1631 ? Doesn't compile for me.


This one may http://dpaste.dzfl.pl/3faf27ba

extern(C) int printf (const char*, ...);

void main()
{
int[] x = [1, 2, 3, 4, 5];
foreach (ref i; 0 .. 5)
{
__limit6--; // or 5  depending on dmd version
printf(%d\n, x[i]);
}
}

1
2
3

This is example of unspecified behavior (better undefined) due to 
playing with __identifiers and how dmd bug can make D code looks 
strange.


Re: foreach over split string

2013-07-17 Thread Maxim Fomin

On Wednesday, 17 July 2013 at 15:26:19 UTC, John Colvin wrote:
I think I can speak quite safely for the majority of the 
community when I say that you are only welcome here if you can 
keep your aggressive and disrespectful comments to yourself.


I think you cannot, as nobody provided you such right and I, in 
particular, do object, as saying you may ask but please without 
obscene language is not a way how public technical newsgroup 
should be organized. It is pretty obvious in this case that flow 
of obscene language will not stop. Also, your politeness does 
harm in this case rather than good.


Re: UDA's for enum values?

2013-07-14 Thread Maxim Fomin

On Sunday, 14 July 2013 at 13:38:41 UTC, Dicebot wrote:

On Sunday, 14 July 2013 at 12:33:07 UTC, JS wrote:

I would like to do something like
...


Looks like a grammar issue. UDA's are supposed to be attached 
to any symbol declaration as far as I understand, which enum 
members definitely are. Probably worth bugzilla entry.


Looks like http://d.puremagic.com/issues/show_bug.cgi?id=9701


Re: Style question

2013-07-12 Thread Maxim Fomin

On Thursday, 11 July 2013 at 20:15:52 UTC, Namespace wrote:
The whole situation looks strange. If you can change both 
files, than it is unclear what made you to write such 
inconsistent code. If you can change only one of them, then it 
should be adjusted to another (meaning importing external file 
and using that enum instead of trying to define different type 
and passing it).


Besides the problem of changing existing API:
If you change only one of those modules and use the enum from 
the other file, every user have to look into the file which 
declares the enum, to see which member the enum has.


This argument can be applied to virtually any peice of code of
any language which has import or #include.

This is almost same as direct cast in #2. Instead of making 
test2() accept B or (u)int consider making it static void 
test2 (MyClass.A a) and wipe out enum B entirely.


That's the problem I tried to describe above.
If you have those two modules as in my example code, the one 
file without the enum depends on the one with the enum. Isn't 
that a bad situation?


Any file importing map depens on std.algorithm. Isn't that a bad
situation?

A possible solution would be to change one of those functions 
which accepts different enums, that it accept an uint - nothing 
else is an enum (in this case).


Well if you consider that this is a best option nothing stops you
from doing this. In such case you can't mark functions as @safe
and may run into bugs when some integer value placed into enum
does not fit into allowed values. This problem is tackled by
final switches. By the way, in your case base type is int, not
uint.


Re: Can templated functions be used in interfaces?

2013-07-11 Thread Maxim Fomin

On Thursday, 11 July 2013 at 12:03:10 UTC, Jakob Ovrum wrote:
However, in my opinion, it's a bug that you're allowed to 
declare a function template (when using the shortcut syntax) 
without defining it, whether in an interface or not. This is a 
rather natural bug though, due to the nature of function 
templates:


void a()();

is equivalent of:

template a() { void a(); }

Perhaps it makes sense to allow the declaration without 
definition when the template and function are explicitly 
separated (can anyone think of a case where this is useful? 
Maybe mixin-related?), but when using the former syntax - the 
function template syntax - I don't think it makes any sense.




It is possible in current implementation to split template 
declaration and definition in different modules but in such case 
list of potential template arguments is limited. Disabling this 
option in general would disable D ability to hide template 
implementation (like libraries and external functions). But in 
this particular case I agree that this should be an error like in 
situation with static functions.


Re: A purity change

2013-07-11 Thread Maxim Fomin

On Thursday, 11 July 2013 at 15:25:10 UTC, bearophile wrote:

This used to compile (probably dmd 2.060):


struct Foo {
immutable int y;
void bar(TF)(TF f) pure {
f(1);
}
void spam() pure {
bar((int x) = y);
}
}
void main() {}


But now it gives:

test.d(4): Error: pure function 'test.Foo.bar!(immutable(int) 
delegate(int x) nothrow @safe).bar' cannot call impure delegate 
'f'
test.d(7): Error: template instance 
test.Foo.bar!(immutable(int) delegate(int x) nothrow @safe) 
error instantiating


Is it a correct error?

Bye,
bearophile


My guess is that before 2.063 immutable int y was implicitly 
static, but now it is per instance data which requires context 
pointer which is deduced to be impure - that why compilation 
fails (try placing static attribute). In other words, before 
2.063 this was a function and now it is a delegate. And delegates 
currently don't play well with constness/immutability.


Re: pointers, assignments, Garbage Collection Oh My?

2013-07-11 Thread Maxim Fomin

On Thursday, 11 July 2013 at 17:07:18 UTC, Ali Çehreli wrote:

On 07/11/2013 12:23 AM, Jacob Carlborg wrote:

 On 2013-07-10 20:22, Ali Çehreli wrote:

 And to be pedantic, length comes first:

 struct Array (T)
 {
  size_t length;
  T* ptr;
 }

 I thought ptr came first, that's the reason you could cast
to the
 pointer type. Not that one should do that. Perhaps there's
some
 compiler/runtime magic involved.

There must be little magic and that magic should be the same as 
getting the .ptr property. Otherwise, the value of a struct 
object cannot be casted to pointer type:


struct S
{
int *p;
}

auto s = S();
int *p = cast(int*)s;

Error: e2ir: cannot cast s of type S to type int*

Ali


In context of slices cast(int*)arr is essentially s.ptr. There is 
no magic but accessing right field of struct.


Re: A purity change

2013-07-11 Thread Maxim Fomin

On Thursday, 11 July 2013 at 17:59:22 UTC, bearophile wrote:

Maxim Fomin:

My guess is that before 2.063 immutable int y was implicitly 
static, but now it is per instance data which requires context 
pointer which is deduced to be impure - that why compilation 
fails (try placing static attribute). In other words, before 
2.063 this was a function and now it is a delegate. And 
delegates currently don't play well with 
constness/immutability.


I think you are right. So is it right to ask D to infer such 
delegate as pure?


Bye,
bearophile


I think delegate here can be allowed to be pure. However, I 
wouldn't expect this issue to be fixed soon since it touches a 
general problem of delegates vs. immutability problem. There were 
many discussions and DIP but there is still no solution.


Re: A purity change

2013-07-11 Thread Maxim Fomin

On Thursday, 11 July 2013 at 18:03:14 UTC, bearophile wrote:

Maxim Fomin:

My guess is that before 2.063 immutable int y was implicitly 
static,


Yet, in the code I used to initialize y in the normal 
constructor of Foo. If now I tag y as static, that's not 
possible any more (Error: can only initialize static const 
member scale inside static constructor), so I don't understand 
again.


Bye,
bearophile


The reason it worked in normal constructor prior the change was 
probably the same bug.
This docs covers the issue - 
http://dlang.org/changelog.html#staticfields


Re: Style question

2013-07-11 Thread Maxim Fomin

On Thursday, 11 July 2013 at 18:22:11 UTC, Namespace wrote:
I have a style question, because a friend of mine has a similar 
problem currently and I have no good advice for him.


Let's assume we have this classes:


The whole situation looks strange. If you can change both files, 
than it is unclear what made you to write such inconsistent code. 
If you can change only one of them, then it should be adjusted to 
another (meaning importing external file and using that enum 
instead of trying to define different type and passing it).




class MyClass {
public:
enum A {
Foo = 0,
Bar = 1
}

private:
A _a;
public:
this(A a) {
this._a = a;
}

void test1() {
MyStaticClass.test2(this._a);
}
}

//

enum B {
Foo = 0,
Bar = 1
}

final abstract class MyStaticClass {
public:
static void test2(B b) { }
}

void main() {

}

Prints: Error: function enum_problem.MyStaticClass.test2 (B b) 
is not callable using argument types (A)


What should he do?


Judging by MyStaticClass.test2(this._a) it seems that the first 
imports the second which is also suspicious - you are importing 
module which contains main function. From where does the code 
come from?



As far as I can see he has 3 options:
1. An external file with the enum information. Both classes 
would import it and could use the same enum. But he cannot 
change the API, so this is no real option.




It would be good to clarify which file cannot be modified, 
although it does not really matter - just use one version of enum.



2. Change test1 into this:

void test1() {
B b = cast(B) this.a;
MyStaticClass.test2(b);
}

This works fine. But is it safe? And is it good style?


It is safe but not @safe (you will have complains if try to mark 
function as @safe). Of course this is a bad style, the whole case 
is strange.



And how is this cast converted? Is it cheap?


Essentially nothing special is done. Of course it is cheap.

3. Change test2 so that it accepts (even) (u)int. But then he 
lose the Type safety.


This is almost same as direct cast in #2. Instead of making 
test2() accept B or (u)int consider making it static void test2 
(MyClass.A a) and wipe out enum B entirely.


Re: pointers, assignments, Garbage Collection Oh My?

2013-07-10 Thread Maxim Fomin

On Wednesday, 10 July 2013 at 18:22:24 UTC, Ali Çehreli wrote:

And to be pedantic, length comes first:

struct Array (T)
{
size_t length;
T* ptr;
}

Which is actually property-like because assigning to length 
does pretty complex stuff. So the member cannot be named as 
'length':


struct Array (T)
{
size_t length_;
T* ptr;
}

Anyway... :)

Ali


To be pedantic dynamic arrays are implemented in D simply as

struct Array
{
size_t length;
void* ptr;
}

and there is no type parametrization since such arrays handling 
is opaque for users (in druntime they are treated as void[]). 
Parametrization can be useful in user side since performing any 
operations with structure above (void*) will lead to errors. But 
in user side there is no point in manipulating the structure 
directly, as it can be done using usual properties/druntime 
without template bloat. By the way, the style ABI page is 
written, allows implementation to have more fields.


Re: Allocating a slice object

2013-07-04 Thread Maxim Fomin

On Thursday, 4 July 2013 at 12:02:16 UTC, monarch_dodra wrote:
This is a pretty stupid question, but how would you allocate an 
int[] on the heap? I'm not talking about the array, but the 
actual slice object. EG:


int[]* pSlice = new int[];
//Error: new can only create structs,
//dynamic arrays or class objects, not int[]'s

Is there a simple idiomatic way?

I'm currently doing it by allocating a struct that wraps one:

struct S{int[] a;}
int[]* pSlice1 = cast(int[]*) new S;
int[]* pSlice2 = (new S).a;

Note: This is also a neat way to allocate a static array on the 
heap.


Yes. This is a good example of how D type system and memory 
allocation type are different, despite many move type system 
terms into memory category.



Anybody have some better way?


Another way:

import std.stdio;

void main()
{
int[] arr;
auto x = { return arr; } ;
writeln(arr);
}


Re: Stop to! rounding?

2013-07-03 Thread Maxim Fomin

On Wednesday, 3 July 2013 at 08:23:40 UTC, monarch_dodra wrote:


My brother in law writes financial apps, and in that field, 
using floating points type is *legally* forbidden.




Really? What kind of apps?


Re: Eponymous template with full template syntax

2013-07-01 Thread Maxim Fomin

On Monday, 1 July 2013 at 18:15:06 UTC, Ali Çehreli wrote:

I think main's second line used to work:

template isSmall(T)
{
enum isSmall = (T.sizeof  12345);
}

void main()
{
static assert(isSmall!int);  // -- the usual 
syntax works


static assert(isSmall!int.isSmall);  // -- compilation 
ERROR

}

Error: template deneme.isSmall does not match any function 
template declaration. Candidates are:

   deneme.isSmall(T)
Error: template deneme.isSmall(T) cannot deduce template 
function from argument types !()(bool)


Am I imagining it? I don't have a problem with it. :) Was the 
change intentional?


Ali


I think that this probably worked as early as in the end of 2011 
but I can be wrong as don't remember exactly.


It seems that dmd recognizes isSmall!int.isSmall as potential 
UFCS property, converts isSmall!int to bool and tries to issue 
call isSmall(bool) and fails, because that template does not 
define any function.


Re: Opaque structs

2013-06-29 Thread Maxim Fomin

On Saturday, 29 June 2013 at 08:01:17 UTC, Johannes Pfau wrote:

Am Fri, 28 Jun 2013 22:16:33 +0200
schrieb Andrej Mitrovic andrej.mitrov...@gmail.com:


On 6/28/13, Johannes Pfau nos...@example.com wrote:
 A naive question: Why isn't struct S {} enough? This should 
 be a
 struct with size 0 so why do we need to disable the 
 constructor and

 postblit explicitly?

Because the user should never be able to use such a struct by 
value,

in other words a user might mistakenly write code such as:

S s2 = *s;  // copies 1 byte


But why is that legal / does that copy _one_ byte? It seems 
like that's

totally arbitrary. Shouldn't doing anything value-related on
an empty struct be invalid anyway?


It copies one byte because empty structs have one byte - 
according to D implementation. The value can be adjusted using 
align() atrribute.


Re: Scope of temporaries as function arguments

2013-06-28 Thread Maxim Fomin

On Friday, 28 June 2013 at 08:08:17 UTC, monarch_dodra wrote:


Just in case it wasn't clear from the original explanation, 
this is a bug, it *should* be perfectly safe to pass as many 
temps as you want, and expect the right amount of destructor 
called in case of a throw.


Original explanation lacks the word bug deliberately because 
this is not a bug (in a sense that dmd generates wrong code), but 
a language design problem. How could you do this:


struct S
{
   int i = 1;
}

void foo(S s)
{
   s.i = 2;
}

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

Currently there are two dtors, one which gets S(2) at the end of 
foo and second at the end of main, which gets S(1). If you move 
dtor from callee to caller, it would get S(1) object (struct is 
passed by value), but it doesn't make sense to destruct S(1) 
where you have S(2). One possible solution is to pass by pointer 
in low level, which would probably increase magnitude of problems.


Re: Scope of temporaries as function arguments

2013-06-28 Thread Maxim Fomin

On Friday, 28 June 2013 at 15:17:12 UTC, monarch_dodra wrote:


Should I have expected a different behavior?


import std.stdio;

int callme()
{
   throw new Exception();
}

struct S
{
   int i = 0;
this(int i){this.i = i; writeln(constructing: , i);}
this(this){writeln(postbliting: , i);}
~this(){writeln(destroying: , i);}
}

void foo(S s, int i)
{
   s.i = 2;
}

void main()
{
   S s = S(1);
   foo(s, callme());
}

Destructor for copied object is not called because it is placed 
in foo(). Before calling foo(), dmd makes a copy of main.s, calls 
postblit, then puts code to invoke callme() and code to invoke 
foo(). Since callme() throws, foo() is not called and destructor 
placed in foo() is also not called. A struct copy escapes 
destructor.


Now, if you try fix this by putting dtor for copy not in foo(), 
but in main immediately after foo() invocation, you will have a 
problem because destructor would get S(1) object while it should 
destroy S(2). Any modification made in foo() is lost. This can be 
possible fixed by passing copy by reference which would probably 
create new ABI problems.


  1   2   3   >