Re: Can't make inout work.

2019-03-18 Thread spir via Digitalmars-d-learn

On 17/03/2019 18:34, Kagamin via Digitalmars-d-learn wrote:

On Saturday, 16 March 2019 at 14:57:35 UTC, Paul Backus wrote:
This code fails to compile if you change `auto s2` to `const s2`--in other 
words, it has the same problem as the original example.


Maybe there's not much need for qualifiers anyway.


This is what I meant as well.
diniz


Re: Block statements and memory management

2019-03-16 Thread spir via Digitalmars-d-learn

On 16/03/2019 11:19, Dennis via Digitalmars-d-learn wrote:

On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:

Does anyone know if when I create a variable inside a scope as in
{int a = 10;}
it disappears complete from the memory when the scope finishes? Or does it 
remain in some part of the memory? I am thinking of using scopes to make 
optimized programs that consume less memory.


In general, you want variables to have no larger scope than needed, so in large 
functions reducing the scope may be useful. When it comes to efficiency however, 
doing that is neither necessary nor sufficient for the compiler to re-use 
registers / stack space. I looked at the assembly output of DMD for this:

```
void func(int a);

void main()
{
     {
     int a = 2;
     func(a);
     }
     {
     int b = 3;
     func(b);
     }
}
```
Without optimizations (the -O flag), it stores a and b on different places in 
the stack.
With optimizations, the values of a and b (2 and 3) are simply loaded in the EDI 
register before the call.

Removing the braces doesn't change anything about that.
The compiler does live variable analysis [1] as well as data-flow analysis [2] 
to figure out that it's only needed to load the values 2 and 3 just before the 
function call. This is just a trivial example, but the same applies to larger 
functions.


In any case, for better memory efficiency I'd consider looking at reducing 
dynamic allocations such as new or malloc. Memory on the stack is basically free 
compared to that, so even if adding lots of braces to your code reduces stack 
memory, chances are it's a low leverage point.


[1] https://en.wikipedia.org/wiki/Live_variable_analysis
[2] https://en.wikipedia.org/wiki/Data-flow_analysis


Just to add a bit on what has been said:
* Register allocation (see wikipedia) is a well-researched area.
* By coding that way, you force the compiler to optimise *a certain way* which 
may prevent it to perform other, more relevant optimisations.
* You cannot beat the knowledge in that domain, it is simply too big and 
complex, just be confident.

diniz



Re: Can't make inout work.

2019-03-16 Thread spir via Digitalmars-d-learn

PS: the chapter of Ali Çehreli's book on func args is great:
http://ddili.org/ders/d.en/function_parameters.html
diniz


Re: Can't make inout work.

2019-03-16 Thread spir via Digitalmars-d-learn

On 16/03/2019 04:49, Paul Backus via Digitalmars-d-learn wrote:

On Friday, 15 March 2019 at 23:57:15 UTC, aliak wrote:

Anyone knows how to make this work?


You need an explicit `inout` on the return value of `make`:

auto ref make(T)(inout auto ref T value) {
     return inout(S!T)(value);
}


I think (but may be wrong) that you don't need inout here, since a plain 'ref' 
will (and does) work. This is accepted by me (I added vars to make the code 
clearer to myself):


struct S(T) {
T value = T.init;
}

auto ref make(T)(ref T value) {
return S!T(value);
}

auto ref f(T)(ref S!T s) {
return make(s.value);
}

void main() {
class C {}
C c ;
auto s1 = S!C(c) ;
auto s2 = make!C(c) ;
auto s3 = f!C(s2) ;
}



Re: local class instance (at module-level)

2019-03-14 Thread spir via Digitalmars-d-learn

On 15/03/2019 00:45, ag0aep6g via Digitalmars-d-learn wrote:

On 14.03.19 20:43, Jacob Carlborg wrote:

class C {
 uint i ;
 this (uint i) {
 this.i = i ;
 }

 this (uint i) shared {
 this.i = i ;
 }

 this (uint i) immutable {
 this.i = i ;
 }
}

__gshared c0 = new C(0);
shared c1 = new shared C(1);
immutable c2 = new immutable C(2);

You only need one of the constructors depending on if you want a __gshared, 
shared or immutable variable.


If you make it `pure`, you can use the same constructor in all cases:


class C {
     uint i ;
     this (uint i) pure {
     this.i = i ;
     }
}

__gshared c0 = new C(0);
shared c1 = new shared C(1);
immutable c2 = new immutable C(2);



all right, thank you!



Re: bug in doc?

2019-03-14 Thread spir via Digitalmars-d-learn

On 14/03/2019 15:52, H. S. Teoh via Digitalmars-d-learn wrote:

On Thu, Mar 14, 2019 at 03:22:52PM +0100, spir via Digitalmars-d-learn wrote:

https://dlang.org/spec/hash-map.html#static_initialization:

immutable long[string] aa = [
   "foo": 5,
   "bar": 10,
   "baz": 2000
];

==> Error: non-constant expression `["foo":5L, "bar":10L, "baz":2000L]`

Also: I don't understand the error message:
* What is non-constant in the *expression*?
* And why should it be constant at all?
(Removing "immutable" does not help...)

[...]

It's a well-known limitation.  The workaround is:

immutable long[string] aa;
static this() {
aa = [
"foo" : 5,
...
];
}


All right! No language has to be perfect... (I'm joking). But the doc (the 
language ref for the matter) should definitely say what you just explained 
above, shouldn't they? I actually think clearly stating limitations is a +++. 
(Like an industry company that does not make perfect product but has great 
client support.)

diniz



Re: local class instance (at module-level)

2019-03-14 Thread spir via Digitalmars-d-learn

On 14/03/2019 12:16, H. S. Teoh via Digitalmars-d-learn wrote:

On Thu, Mar 14, 2019 at 12:05:22PM +0100, spir via Digitalmars-d-learn wrote:

I desperately try to declare/define/initialise a simple class instance
at module-level. This is a special (conceptually static and immutable)
instance used as a "marker", that just should exist and be accessible
by methods of this class and/or other classes defined in the same
module. (Thus I don't care if TLS.) I use it as a remplacement for
null, to avoid semantic confusion and unhelpful segfaults in case of
bug.


Does this work?

class C { ... }
immutable C c0;
static this() {
c0 = new C(...);
}


T


Oh yes, that was it ! Thank you very much.
diniz



bug in doc?

2019-03-14 Thread spir via Digitalmars-d-learn

https://dlang.org/spec/hash-map.html#static_initialization:

immutable long[string] aa = [
  "foo": 5,
  "bar": 10,
  "baz": 2000
];

==> Error: non-constant expression `["foo":5L, "bar":10L, "baz":2000L]`

Also: I don't understand the error message:
* What is non-constant in the *expression*?
* And why should it be constant at all?
(Removing "immutable" does not help...)

diniz


local class instance (at module-level)

2019-03-14 Thread spir via Digitalmars-d-learn
I desperately try to declare/define/initialise a simple class instance at 
module-level. This is a special (conceptually static and immutable) instance 
used as a "marker", that just should exist and be accessible by methods of this 
class and/or other classes defined in the same module. (Thus I don't care if 
TLS.) I use it as a remplacement for null, to avoid semantic confusion and 
unhelpful segfaults in case of bug.


I have tried a number of options and never manage to do it, including:
* [C/auto/static immutable c0] = new C(0) ;
* C c0 ; c0.i = 0 ;
* defining a static this()
* more...

The most confusing error is:
Error: variable `_base.c0` is a thread-local class and cannot have a static 
initializer. Use `static this()` to initialize instead.


I also could not find any information --for a while, repeatedly, since I can go 
on developing in the meantime, using null instead. I'm bluffed and confused, 
since there is nothing weird in that, is there? (the compiler can just allocate 
it in static mem and take the address)


Reduced test case:
===
class C {
uint i ;
this (uint i) {
this.i = i ;
}
}

// error
auto c0 = new C(0) ;

void main () {
// ok
auto c0 = new C(0) ;
}
===

I would enjoy an explanation (or a pointer to) in addition to a solution.

Thank you,
diniz

PS: I take the opportnity to ask if I can count on the compiler to intern 
literal strings (which my code may use in several places, including loops), esp. 
"", or should I declare and use (for instance):

static immutable s0 = "" ;


Re: Why does D language do not support BigDecimal type?

2019-03-12 Thread spir via Digitalmars-d-learn

On 12/03/2019 10:31, Boqsc via Digitalmars-d-learn wrote:
Please attach quick working examples for every sentence you write or it's just a 
waste of time. People want to see the results and direct actions first before 
anything else, it's more efficient communication. We are in the subforum of 
Dlang learn, after all.


Do not write "For Example".


Then you may help people helping you by giving examples of your own use cases, 
first.


I'm interested in writing a simple game prototype and I imagine that I would 
like to include some item parts in decimal. (100.00) To keep everything simple I 
would like to make my code as clean and simple as possible.


From this single example, you don't need "fractal" (decimal or binary) numbers 
at all, just plain ints. Look up "fixed point arithmetics" on wikipedia, the 
article is rather good. It's easy and clean in comparison, at least if you only 
need simple operations. (That's how, by the way, monetary/financial software is 
or at least used to be implemented.)


diniz


Re: Distinguish float and integer types from string

2019-03-10 Thread spir via Digitalmars-d-learn

On 09/03/2019 19:11, Jacob Shtokolov via Digitalmars-d-learn wrote:

The thing is that in PHP, for example, I would do


The thing is php needs to be able to "lexify" raw input data at runtime, while 
in D this is done at compile-time. The ompiler has the lexer to do that.


But I agree that, for user input, it would be cool to have such a feature 
available. However, this would quickly become complex because of (the reciprocal 
of) localisation, or even personalisation. Eg I like to write decimals like:

-1'234'457,098

diniz



Re: this is null

2019-03-10 Thread spir via Digitalmars-d-learn

On 09/03/2019 21:10, ANtlord via Digitalmars-d-learn wrote:

On Saturday, 9 March 2019 at 20:04:53 UTC, Paul Backus wrote:


You can end up with a null `this` reference if you dereference a null pointer 
to a struct and then call a method on the result. For example:




I can but my reference is not null before calling. Take a look at the line of 
code [0]. There is a check before the line.


https://github.com/ANtlord/deadmemory/blob/master/src/deadmemory/mem.d#L20 [0]


There is a typo in this instruction:

T* ptr = this.list.getFisrtFreeOrAdd(memViewLen).getPtr!T();
^^
rs
(may this explain your null? the compiler should complain)

diniz




Re: 2 class issues -- PS

2019-03-07 Thread spir via Digitalmars-d-learn

from [https://dlang.org/spec/attribute.html#abstract] :

---
abstract Attribute

An abstract member function must be overridden by a derived class. Only virtual 
member functions may be declared abstract; non-virtual member functions and 
free-standing functions cannot be declared abstract.


Classes become abstract if any of its virtual member functions are declared 
abstract or if they are defined within an abstract attribute. Note that an 
abstract class may also contain non-virtual member functions.


Classes defined within an abstract attribute or with abstract member functions 
cannot be instantiated directly. They can only be instantiated as a base class 
of another, non-abstract, class.


Member functions declared as abstract can still have function bodies. This is so 
that even though they must be overridden, they can still provide ‘base class 
functionality’, e.g. through super.foo() in a derived class. Note that the class 
is still abstract and cannot be instantiated directly.

---

Is there thus another way to enforce overriding of given methods? I wish to 
instantiate superclasses for special instances, as shown in previous mail. It is 
not a big deal (I can live without this enforcement, and my clients as well 
since if they wish to implement their own subclasses, they will have to 
override) but I still wish to know that for further cases.


Thank you,
diniz



2 class issues

2019-03-07 Thread spir via Digitalmars-d-learn

Hello,

First, I am not very experimented with the combination of static lang (alloc & 
typing) and OO (class-based). I'm implementing a library for lexical analysis 
(lexing), with 2 minor issues:


-1- How to enforce that subclasses implement given methods without using 
"abstract", which seems to make the whole class abstract? (no info found in doc, 
actually, the page on classes [1] does not seem to even mention abstract classes)


-2- How to have "constant" (predefined) class instances at the module-level? The 
compiler requires a "static this ()". What does this actually mean (for a 
constructor)? What are the consequences, for either my code or client code? (The 
doc on the topic [2] is rather obscure for me, and I could not find better 
elsewhere.)


I'm also bluffed by "Static constructors have empty parameter lists." Does this 
mean I should manually fill the fields? (not a big deal, but why???) This may give:

// Predefined pseudo-pattern "End-of-Text":
auto EoT = new Pattern() ;   // ???
EoT.name = "EoT" ;

// Unique lexeme "end-of-text":
auto eot = new Lexeme() ;   // ???
eot.patname = "EoT" ;
eot.slice = null ;
eot.index = uint.max ;
Then, why have a constructor at all? This would also prevent me from making 
classes immutable, while conceptually all are immutable... (no reason for a 
pattern or a lexeme to change)


Thank you,
diniz

[1] https://dlang.org/spec/class.html
[2] https://dlang.org/spec/class.html#static-constructor


Re: Beginner ?. Why does D suggest to learn java

2014-10-17 Thread spir via Digitalmars-d-learn

On 17/10/14 07:38, maarten van damme via Digitalmars-d-learn wrote:

While d can be complex, there's nothing preventing you from starting out
simple and not using all features at first.
I don't understand why it's not suitable for a beginner if you use this
approach...


For some reasons, in my view: A beginner has to learn programming in addition to 
a first lang. A beginner has to learn a first lang in addition to programming. 
We learn languages by understanding valid, meaningful input, ie here reading 
code. All static langs introduce tons of complication only due to their 
staticity. D is rather big  complex, in the field of static langs. Most code 
will use more than a theoretical minimal set of features. And this minimal set 
is far more in size, difficulty, complication than in langs partly designed  for 
ease of learning (Lua, Python, Scheme...). Even plain C is far more difficult 
than say, Lua.


d



Re: Beginner ?. Why does D suggest to learn java

2014-10-17 Thread spir via Digitalmars-d-learn

On 17/10/14 03:05, ketmar via Digitalmars-d-learn wrote:

On Fri, 17 Oct 2014 00:52:14 +
MachineCode via Digitalmars-d-learn digitalmars-d-learn@puremagic.com
wrote:


I don't understand. If at least it were C but java? why not D
itself?

C is *awful* as beginner's language. never ever let people start with
C if you don't hate 'em.

as for D... current version of D can be used, but with some
precautions. we now have excellent book by Ali. (it's great, really! i
believe that it must be featured on the front dlang.org page!) but java
has alot more books and tutorials.

not that D is bad for beginners, it's just has a smaller userbase. and
all that things with classes are reference types and structs are not,
empty array is not empty array but is empty array and so on D may be
confusing a little. it's good to have some CS background to understood
that things.


What you say here applies, I guess, to many other points. I applaud Ali for 
writing a tutorial like his but... Check it (just the first pages is enough) for 
literally the dozens of notions one must know and master for being able to 
understand, not only the features of D introduced, but even the tutorial itself. 
If I am not a programmer, and one who knows other static langs, and better of 
the mainstream procedural paradigm, if not D itself, then I do not understand 
more than few isolated words here and there. We are blind to the huge pile of 
concepts we know, I guess, because we know them, thus take them for granted...


d


Re: String created from buffer has wrong length and strip() result is incorrect

2014-10-17 Thread spir via Digitalmars-d-learn

On 17/10/14 09:29, thedeemon via Digitalmars-d-learn wrote:

On Friday, 17 October 2014 at 06:29:24 UTC, Lucas Burson wrote:


   // This is where things breaks
   {
  ubyte[] buff = new ubyte[16];
  buff[0..ATA_STR.length] = cast(ubyte[])(ATA_STR);

  // read the string back from the buffer, stripping whitespace
  string stringFromBuffer = strip(cast(string)(buff[0..16]));
  // this shows strip() doesn't remove all whitespace
  writefln(StrFromBuff is '%s'; length %d, stringFromBuffer,
stringFromBuffer.length);

  // !! FAILS. stringFromBuffer is length 15, not 3.
  assert(stringFromBuffer.length == strip(ATA_STR).length);


Unlike C, strings in D are not zero-terminated by default, they are just arrays,
i.e. a pair of pointer and size. You create an array of 16 bytes and cast it to
string, now you have a 16-chars string. You fill first few chars with data from
ATA_STR but the rest 10 bytes of the array are still part of the string, not
initialized with data, so having zeroes. Since this tail of zeroes is not
whitespace (tabs or spaces etc.) 'strip' doesn't remove it.


Side-note: since your string has those zeroes at the end, strip only removes the 
space at start (thus, final size=15), instead of at both ends.


d



Re: How to check i

2014-10-16 Thread spir via Digitalmars-d-learn

On 16/10/14 20:46, Uranuz via Digitalmars-d-learn wrote:

I have some string *str* of unicode characters. The question is how to check if
I have valid unicode code point starting at code unit *index*?
[...]


You cannot do that without decoding. Cheking whether utf-x is valid and decoding 
are the very same process. IIRC, D has a validation func which is more or less 
just an alias for the decoding func ;-). Moreover, you also need to distinguish 
word-character code points from others (punctuation, spacing, etc) which 
requires unicode code points (Unicode the consortium provide tables for such tasks).


Thus, I would recommand you to just abandon the illusion of working at the level 
of code units for such tasks, and simply operate on strings of code points. (Why 
do you think D has them builtin?)


denis


use case for alias this

2011-04-20 Thread spir

Hello,

For what it's worth, I have finally found one use case for the famous alias 
this trick for structs:


struct ScienceConstant {
float value;
string name;
alias value this;
string toString () { return this.name; }
}

unittest {
auto PI = ScienceConstant(3.14, pi);
writefln(%s/3 = %s, PI, PI/3);
// -- pi/3 = 1.04667
}

For people who don't know it: the point is that alias this implicitely 
delegates messages (here requests for arithmetic operations) to the actual 
element (here value) on which they should apply, that happens to be embedded in 
a struct object. Or rather: that's how I conceive this feature.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: A use case for fromStringz

2011-04-16 Thread spir

On 04/16/2011 06:55 AM, Andrej Mitrovic wrote:

I wonder.. in all these years.. have they ever thought about using a
convention in C where the length is embedded as a 32/64bit value at
the pointed location of a pointer, followed by the array contents?


Sometimes called Pascal strings (actually, IIRC, the length is at the address 
/before/ the one pointed by the pointer). One of the important diffs between C 
 Pascal from the practical pov.

Actually, it's the same diff as C arrays vs true arrays like D's.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Else clauses for loops

2011-04-14 Thread spir

On 04/13/2011 06:48 PM, bearophile wrote:

Bernard Helyer:


You could wrap the loop in an if clause:

 if (condition) while (true) {
 // ...
 } else {
 // ...
 }


This is the semantics of the else clause of Python for (and while) loops:

bool broken = false;
for (...) {
 if (...) {
 broken = true;
 break;
 }
}
if (!broken) {
  ...
}

I agree with BCS in the bug 2304, I'd like something more semantically descriptive 
instead of just an else.


True. Python tends to overload its keywords, which leads to weird expression.
Also weird, again using then:

try:
n = 1 + 1
except Exception, e:
print (*error*)
else:
print (n)

actually means

try:
n = 1 + 1
then:
print (n)
except Exception, e:
print (*error*)

Denis
--
_
vita es estrany
spir.wikidot.com



Re: So why doesn't popFront return an element?

2011-04-14 Thread spir

On 04/14/2011 01:00 AM, Andrej Mitrovic wrote:

I'm trying to understand the design of ranges. Why does popFront only set the 
front() property to return the next element in the range? Why not return the 
element in the call to popFront right away?

For example code like this (which doesn't work since popFront doesn't return):
void main()
{
 int[] a = [1, 2];
 auto b = a.popFront;
 assert(a == [2]);
 assert(b == 1);
}

Isn't it wasteful to have to call both popFront() and front() to simultaneously 
remove an element from a range and return it? I mean it's an extra function 
call, right?


I like to have three members (even if not quite necessary, this cleanly 
separates notions). Why I don't understand is why empty and front are methods, 
not simple data members.


Denis
--
_
vita es estrany
spir.wikidot.com



un-requested compiler optimisations

2011-04-14 Thread spir

On 04/14/2011 06:57 PM, Andrej Mitrovic wrote:

This leads me to another question I've always wanted to ask. A call such as:

auto b=map!foo(map!bar1(map!bar2(a));

This constructs a lazy range. What I'm wondering is if there are any
performance issues when constructing long chains of ranges like that,
since this basically routes one function to the next, which routes to
the next, etc. E.g:

auto a = [1, 2];
auto b = retro(a);
auto c = retro(b);
auto d = retro(c);

Under the surface, I assume calling d.front would mean the following calls:
d.front()-c.back()-b.front()-a.back()

Or another example:
auto b = retro(retro(a));

Can the compiler optimize the second case and convert b.front to just
do one field access?


If it does optimise, then it is definitely a compiler bug. Since you 
*explicitely* ask for a double reverse, it *must* just do it. Suppressing them 
is here just breaking the language's semantics!


It is not the compiler's role to interpret, meaning to guess your reasons for 
requesting that; and the compiler is certainly not in position to do it. Even 
less to *judge* that request as stupid, and thus ignore it (unlike in the army 
;-). You are the master, asking for stupid computations is both your right and 
your problem ;-)
Anyway, there are probably perfectly valid reasons to do a double reverse; at 
least (0) exploring (1) teaching (2) benchmarking.


In a similar vein:
{
long n;
static N = 10_000;
foreach (_ ; 0..N) {
n = factorial(9);
}
}

Should the compiler optimise by computing n only once? (even possibly at 
compile-time)

Then, what if I'm doing that in purpose? (be it stupid or not)

Denis
--
_
vita es estrany
spir.wikidot.com



Re: un-requested compiler optimisations

2011-04-14 Thread spir

On 04/14/2011 08:33 PM, Steven Schveighoffer wrote:

If it does optimise, then it is definitely a compiler bug. Since you
*explicitely* ask for a double reverse, it *must* just do it. Suppressing
them is here just breaking the language's semantics!


I feel like people aren't looking at my post :)


Sorry, I wrote this reply before reading yours.

denis
--
_
vita es estrany
spir.wikidot.com



Re: Range violation error in the code

2011-04-12 Thread spir

On 04/12/2011 02:20 PM, Ishan Thilina wrote:

I can compile the following code. But when I run the program it gives me a
core.exception.RangeError@untitled(34): Range violation
 error.

The code is as follows.


import std.stdio;

int main(char[][] args)
{
 struct Node{
int _value;
Node* _next,_prev,_up,_down;
}

Node*[]  pointers;
int i=0;

auto  n=new Node;
pointers[i]=n;

return 0;
}



Here's the error.


core.exception.RangeError@untitled(34): Range violation
[...]
As it seems the problem is with the line pointers[i]=n. What's wrong here? :s


There is no node in pointers as of now, thus pointers[i] can only be a range 
violation, whatever i (even 0, which should point to the *first* node).

pointers[i]=n;
would *change* the current element number i. To put a *new* node into pointers, 
if that's what you intended, use the '~' appending operator (here in version '~=');

pointers ~= n;

Denis
--
_
vita es estrany
spir.wikidot.com



strange warning at link-time

2011-04-12 Thread spir
/usr/bin/ld: Warning: size of symbol 
`_D5table14__T5TableTkTkZ5Table7opApplyMFDFKkZiZi' changed from 96 in 
/tmp/.rdmd/rdmd-table.d-403917940996C846133B5FCD56447466/table.o to 100 in 
/tmp/.rdmd/rdmd-table.d-403917940996C846133B5FCD56447466/table.o


???

Note: this is just a warning, program runs fine anyway.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Semicolon can be left out after do-while

2011-04-12 Thread spir

On 04/12/2011 09:21 PM, Steven Schveighoffer wrote:


int main(){
int a,b;
do{
scanf(%d %d,a,b);
}while(ab) //note missing semicolon here
return 0;
}

The grammar specifies this correctly, but then again, the example uses the
semicolon. (http://www.digitalmars.com/d/2.0/statement.html#DoStatement)
[...]
I think the grammar should be changed...


yop!


This is almost as bad as go's
requirement for if statement opening block to be on the same line...


why? I like Go's syntactuc diffs. (except for its multi-for)

denis
--
_
vita es estrany
spir.wikidot.com



Re: Semicolon can be left out after do-while

2011-04-12 Thread spir

On 04/12/2011 11:51 PM, Steven Schveighoffer wrote:

On Tue, 12 Apr 2011 17:21:57 -0400, spir denis.s...@gmail.com wrote:


On 04/12/2011 09:21 PM, Steven Schveighoffer wrote:


int main(){
int a,b;
do{
scanf(%d %d,a,b);
}while(ab) //note missing semicolon here
return 0;
}

The grammar specifies this correctly, but then again, the example uses the
semicolon. (http://www.digitalmars.com/d/2.0/statement.html#DoStatement)
[...]
I think the grammar should be changed...


yop!


This is almost as bad as go's
requirement for if statement opening block to be on the same line...


why? I like Go's syntactuc diffs. (except for its multi-for)


in Go, this:

if(x)
{
gosWriteRoutineThatIDontKnowTheSyntaxOf(hello)
}

is equivalent to this in D:

if(x)
{
}

writeln(hello);

This is frankly unforgivable IMO.

Of course it's fixable, but the attitude that the coder should know better
doesn't really make me comfortable with it. And I hate the brace on the same
line format (but this of course is not a real argument against it).


Oh, that's what you meant! I find this a Good Thing, in that it enforces one 
bracing style (the right one, that does not eats one more line for just a '{').
About knowing or not about this (non/mis/-)feature, it's written down, and 
clearly, in all Go docs I've read. And one cannot miss it for very long anyway 
;-) Maybe, if not done already, a line starting with an opening brace should 
generate a parsing error.


Denis
--
_
vita es estrany
spir.wikidot.com



Why tuples? [was: Why tuple Re: Why are unsigned to signed conversions implicit...?]

2011-04-11 Thread spir

On 04/11/2011 01:47 AM, Andrej Mitrovic wrote:

alias Tuple!(byte, red, byte, green, byte, blue) RGBTuple;

RGBTuple GetRGB(COLORREF cref)
{
 RGBTuple rgb;
 rgb.red   = GetRValue(cref);
 rgb.green = GetGValue(cref);
 rgb.blue  = GetBValue(cref);

 return rgb;
}


[O your T]
Hello, andrej,

I'm trying to understand why people use tuples (outside multiple return values 
and variadic typetuples). Why do you prefere the above to:


struct RGBColor { byte red, green, blue; }

RGRColor GetRGB (COLORREF cref)
{
 RGBColor rgb;
 rgb.red   = GetRValue(cref);
 rgb.green = GetGValue(cref);
 rgb.blue  = GetBValue(cref);
 return rgb;
}

?
[/O your T]

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Why are unsigned to signed conversions implicit and don't emit a warning?

2011-04-11 Thread spir

On 04/11/2011 02:42 AM, bearophile wrote:

I and Don have asked (in Bugzilla and elsewhere) to change the built-in names 
into sbyte and ubyte, to avoid the common confusions between signed and 
unsigned bytes in D, but Walter was deaf to this.


I think a good naming scheme would be:

* signed   : int8 .. int64
* unsigned : nat8 .. nat64

(since natural number more or less means unsigned integer number) already. 
What do you think?


or counting in octets:

* signed   : int1 .. int8
* unsigned : nat1 .. nat8

(I prefere the latter naming scheme in absolute, but it would be confusing 
because some languages --and LLVM, I guess-- count in bits.)


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Why are unsigned to signed conversions implicit and don't emit a warning?

2011-04-11 Thread spir

On 04/11/2011 10:10 AM, SimonM wrote:

On 2011/04/11 09:31 AM, spir wrote:

On 04/11/2011 02:42 AM, bearophile wrote:

I and Don have asked (in Bugzilla and elsewhere) to change the
built-in names into sbyte and ubyte, to avoid the common confusions
between signed and unsigned bytes in D, but Walter was deaf to this.


I think a good naming scheme would be:

* signed : int8 .. int64
* unsigned : nat8 .. nat64

(since natural number more or less means unsigned integer number)
already. What do you think?

I like the idea of removing all the different integer type names (byte, short,
int, long, cent) and replacing them with int8..int64 (I'd still prefer
uint8..uint64 though).

Then you could use just 'int' to specify using the current system's
architecture (and hopefully replace the ugly size_t type). I also think it
makes more sense to just use 'int' when you don't really care about the
specific size of the value. Unfortunately it would break backwards compatility
so it would never make it into D's current state.


Agreed. Same for uint or nat.
And no implicit cast, please ;-)

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Before and after in contracts?

2011-04-11 Thread spir

On 04/11/2011 04:36 PM, Magnus Lie Hetland wrote:

I guess I could just use a local variable (guarded by version()) and then have
an assert() near the end of the function. Probably a better solution...


If you mean coding your checking by habd inside the func's normal body, 
this seems to me the right solution. In any case, much simpler and less 
contorsed than declaring an additional attribute just for that. I would add a 
comment note telling why it's coded that way (asp. if you use contracts elsewhere).

Contracts, like any software tool, do not correctly match all possibly needs.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Before and after in contracts?

2011-04-11 Thread spir

On 04/11/2011 09:18 PM, bearophile wrote:

spir:


Contracts, like any software tool, do not correctly match all possibly needs.


This is true in general, but this isn't true in this case: here they don't 
match a basic need because D DbC misses a significant feature (prestate). If 
you take a look at other implementations of DbC in Eiffel and C# the prestate 
is present.


Right, did not know that. Thnaks for this useful info.

Denis
--
_
vita es estrany
spir.wikidot.com



optional func alias template param

2011-04-10 Thread spir

Hello,

I need a trick to allow a function template parameter be optional.
The following (reduced case) fails because D wants to call f:

uint f(uint i) { return i; }
struct S (alias func=null) {
enum bool hasFunc = !(func == null);// *** error line ***
}
unittest {
// ok
auto s1 = S!()();
writeln(s1.hasFunc);
// not ok
auto s2 = S!(f)();
writeln(s2.hasFunc);
}
==
Error: function ___.f (uint i) is not callable using argument types ()
(I consider that a bug due to f implicitely meaning f() --but this is 
another story.)


The following also fails:

// not ok
auto s3 = S1!(f)();
writeln(s3.hasFunc);
==
Error: expression  f is not a valid template value argument

Denis
--
_
vita es estrany
spir.wikidot.com



Re: optional func alias template param

2011-04-10 Thread spir

On 04/10/2011 04:10 PM, spir wrote:

Hello,

I need a trick to allow a function template parameter be optional.
The following (reduced case) fails because D wants to call f:

uint f(uint i) { return i; }
struct S (alias func=null) {
enum bool hasFunc = !(func == null); // *** error line ***
}
unittest {
// ok
auto s1 = S!()();
writeln(s1.hasFunc);
// not ok
auto s2 = S!(f)();
writeln(s2.hasFunc);
}
==
Error: function ___.f (uint i) is not callable using argument types ()
(I consider that a bug due to f implicitely meaning f() --but this is
another story.)

The following also fails:

// not ok
auto s3 = S1!(f)();
writeln(s3.hasFunc);
==
Error: expression  f is not a valid template value argument


PS: I also cannot pass a typed func:

struct S (uint delegate (uint) func=null) {
enum bool hasFunc = !(func == null);
}

==
	Error: arithmetic/string type expected for value-parameter, not uint 
delegate(uint)


--
_
vita es estrany
spir.wikidot.com



Re: optional func alias template param

2011-04-10 Thread spir

On 04/10/2011 04:10 PM, spir wrote:

Hello,

I need a trick to allow a function template parameter be optional.
The following (reduced case) fails because D wants to call f:

uint f(uint i) { return i; }
struct S (alias func=null) {
enum bool hasFunc = !(func == null); // *** error line ***
}
unittest {
// ok
auto s1 = S!()();
writeln(s1.hasFunc);
// not ok
auto s2 = S!(f)();
writeln(s2.hasFunc);
}
==
Error: function ___.f (uint i) is not callable using argument types ()
(I consider that a bug due to f implicitely meaning f() --but this is
another story.)


Found one solution using isCallable! Other tricks welcome...

uint f(uint i) { return i; }
struct S (alias func=null) {
enum bool hasFunc = isCallable!(typeof(func));
}
unittest {
auto s1 = S!()();
writeln(s1.hasFunc);
auto s2 = S!(f)();
writeln(s2.hasFunc);
}

I'd also like to know why pointer cannot be template *alias* parameters, like 
in:
auto s2 = S!(f)();
==
Error: expression  f is not a valid template value argument

Denis
--
_
vita es estrany
spir.wikidot.com



speed of low-level C funcs: example of memmove

2011-04-09 Thread spir

Hello,

To insert of delete an array slice, I tried to use C's memmove, thinking it 
would be far faster than manually copying bit per bit (by any kind of magic). 
But I still wrote a D versions just to check what the actual speed gain is. To 
my great surprise, the C-memmove and D-manual versions perform *exactly* at the 
same speed (considering measure imprecision).
Note: this remains true when elements are bigger; speed slows down slowly (eg 
dchar's take only 1/3 more time).


Any comment or explanation welcome. Below the code.

Denis

= code =
import std.date : getUTCtime, d_time;
import std.c.string : memmove;
// C interface: void *memmove(void *dest, const void *src, size_t n);

void shiftEndPartC (E) (ref E[] array, size_t source, size_t dest) {
// Record length before possible extension.
auto length = array.length;
int offset  = dest - source;

// If move up, extend array to make place.
if (offset  0)
array.length += offset;

// Shift slice.
auto pDest  = cast(void*)((array[dest]));
auto pSource= cast(void*)((array[source]));
size_t size = (length - source) * E.sizeof;
memmove(pDest, pSource, size);

// If move down, compress array.
if (offset  0)
array.length += offset;
}
void shiftEndPartD (E) (ref E[] array, size_t source, size_t dest) {
// Record length before possible extension.
auto length = array.length;
int offset  = dest - source;

// If move up, extend array  shift backwards.
if (offset  0) {
array.length += offset;
for (size_t i=length-1 ; i=source ; i--)
array[i+offset] = array[i];
}

// If move down, shift forwards  compress array.
if (offset  0) {
for (size_t i=source ; ilength ; i++)
array[i+offset] = array[i];
array.length += offset;
}
}

void testFuncs () {
char[] s;

// C memmove
s = 0123456789.dup;
writeln(s);
// Insert slice.
s.shiftEndPartC(3,5);
s[3..5] = --;
writeln(s);
// Delete slice.
s.shiftEndPartC(5,3);
writeln(s);
writeln();

// D manual
s = 0123456789.dup;
writeln(s);
// Insert slice.
s.shiftEndPartD(3,5);
s[3..5] = --;
writeln(s);
// Delete slice.
s.shiftEndPartD(5,3);
writeln(s);
writeln();
}
void chrono () {
char[] s;
d_time t;
enum N = 1_000_000;

// C memmove
s = 0123456789.dup;
t = getUTCtime();
foreach (_ ; 0..N) {
s.shiftEndPartC(3,5);
s[3..5] = --;
s.shiftEndPartC(5,3);
}
t = getUTCtime() - t;
writefln(C time: %s, t);

// D manual
s = 0123456789.dup;
t = getUTCtime();
foreach (_ ; 0..N) {
s.shiftEndPartD(3,5);
s[3..5] = --;
s.shiftEndPartD(5,3);
}
t = getUTCtime() - t;
writefln(D time: %s, t);
}

unittest {
//~ testFuncs();
chrono();
}
void main () {}
--
_
vita es estrany
spir.wikidot.com



Re: speed of low-level C funcs: example of memmove

2011-04-09 Thread spir

On 04/09/2011 07:08 PM, spir wrote:

Hello,

To insert of delete an array slice, I tried to use C's memmove, thinking it
would be far faster than manually copying bit per bit (by any kind of magic).
But I still wrote a D versions just to check what the actual speed gain is. To
my great surprise, the C-memmove and D-manual versions perform *exactly* at the
same speed (considering measure imprecision).
Note: this remains true when elements are bigger; speed slows down slowly (eg
dchar's take only 1/3 more time).


Correction: memmove can be from 5 to 10 times faster on big arrays. For 
instance, with 1_000_000 char array:


void chrono () {
char[] s;
d_time t;
enum N = 100;

// C memmove
s = (0.mult(1_000_000)).dup;
t = getUTCtime();
foreach (_ ; 0..N) {
s.shiftEndPartC(3,5);
s[3..5] = --;
s.shiftEndPartC(5,3);
}
t = getUTCtime() - t;
writefln(C time: %s, t);

// D manual
s = (0.mult(1_000_000)).dup;
t = getUTCtime();
foreach (_ ; 0..N) {
s.shiftEndPartD(3,5);
s[3..5] = --;
s.shiftEndPartD(5,3);
}
t = getUTCtime() - t;
writefln(D time: %s, t);
}

--
_
vita es estrany
spir.wikidot.com



Re: ddoc patterns

2011-04-08 Thread spir

On 04/08/2011 03:00 PM, Aleksandar Ružičić wrote:

On Thu, Apr 7, 2011 at 7:27 PM, spirdenis.s...@gmail.com  wrote:

how are we supposed to insert code phrases in the
flow of normal text?


code/code  tags should be used for that
(http://www.w3.org/TR/html401/struct/text.html#h-9.2.1).


Right, but IIUC unlike pre there is no guarantee for code contents not to 
be interpreted further. It's a semantic hint to the rendering engine (which 
is often used to perform syntax highlighting).



 But I know
nothing about ddoc so I don't know how to write macro that will use
code  instead ofpre. Although I believe it's a piece of cake :)


Yes:
Macros:
CODE = code$0/code

Denis
--
_
vita es estrany
spir.wikidot.com



Re: char[][] join == string

2011-04-07 Thread spir

On 04/07/2011 03:07 AM, Ali Çehreli wrote:

 Given an array of strings std.string.join() returns a single string:

 import std.string;
 void main() {
  string[] a1 = [hello, red];
  string j1 = join(a1,  ); // OK
 }


 But in a program I need an array of mutable arrays of chars. If I join the

arrays I get a mutable array of chars.
[...]
Finally, casting ourselves works:

 string j2 = cast(string)join(a2,  );


Oh, that's very good news! Thans Ali, I never thought at that solution. I'm 
often i/dup-ing from/to string to manipulate text due to the fact there is no 
automatic conversion.

cast() works in place, doesn't it? so this is supposed avoid to avoid copy.

PS: Checked: indeed, it works in-place. But watch the gotcha:

unittest {
string s = abc;
char[] chars = cast(char[])s;
chars ~= de;
s = cast(string) chars;
writeln(s, ' ', chars); // abcde abcde

chars[1] = 'z';
writeln(s, ' ', chars); // azcde azcde
}

s's chars are mutable ;-) So, I guess there is /really/ no reason for implicite 
casts between char[] and string no to exist. (I assumed the reason was 
precisely to avoid such traps).


Denis
--
_
vita es estrany
spir.wikidot.com



Re: char[][] join == string

2011-04-07 Thread spir

On 04/07/2011 09:52 AM, spir wrote:

On 04/07/2011 03:07 AM, Ali Çehreli wrote:

Given an array of strings std.string.join() returns a single string:

import std.string;
void main() {
string[] a1 = [hello, red];
string j1 = join(a1,  ); // OK
}


But in a program I need an array of mutable arrays of chars. If I join the

arrays I get a mutable array of chars.
[...]
Finally, casting ourselves works:

string j2 = cast(string)join(a2,  );


Oh, that's very good news! Thans Ali, I never thought at that solution. I'm
often i/dup-ing from/to string to manipulate text due to the fact there is no
automatic conversion.
cast() works in place, doesn't it? so this is supposed avoid to avoid copy.

PS: Checked: indeed, it works in-place. But watch the gotcha:

unittest {
string s = abc;
char[] chars = cast(char[])s;
chars ~= de;
s = cast(string) chars;
writeln(s, ' ', chars); // abcde abcde


Sorry: forgot this line:
assert(s.ptr == chars.ptr); // pass



chars[1] = 'z';
writeln(s, ' ', chars); // azcde azcde
}

s's chars are mutable ;-) So, I guess there is /really/ no reason for implicite
casts between char[] and string no to exist. (I assumed the reason was
precisely to avoid such traps).

Denis


--
_
vita es estrany
spir.wikidot.com



Re: char[][] join == string

2011-04-07 Thread spir

On 04/07/2011 09:52 AM, spir wrote:

On 04/07/2011 03:07 AM, Ali Çehreli wrote:

Given an array of strings std.string.join() returns a single string:

import std.string;
void main() {
string[] a1 = [hello, red];
string j1 = join(a1,  ); // OK
}


But in a program I need an array of mutable arrays of chars. If I join the

arrays I get a mutable array of chars.
[...]
Finally, casting ourselves works:

string j2 = cast(string)join(a2,  );


Oh, that's very good news! Thans Ali, I never thought at that solution. I'm
often i/dup-ing from/to string to manipulate text due to the fact there is no
automatic conversion.
cast() works in place, doesn't it? so this is supposed avoid to avoid copy.

PS: Checked: indeed, it works in-place. But watch the gotcha:

unittest {
string s = abc;
char[] chars = cast(char[])s;
chars ~= de;
s = cast(string) chars;
writeln(s, ' ', chars); // abcde abcde

chars[1] = 'z';
writeln(s, ' ', chars); // azcde azcde
}

s's chars are mutable ;-) So, I guess there is /really/ no reason for implicite
casts between char[] and string no to exist. (I assumed the reason was
precisely to avoid such traps).


After some more thought, I guess it's better to leave things as are. We have a 
way to cast without copy --which is one issue perfectly solved. The other issue 
--typing-- is small enough to keep it, since it also serves as warning to the 
programmer about the above trap.
What should definitely be done is teaching this idiom in all relevant places of 
the reference, manuals, tutorials: while this issue is often submitted on D 
lists, I had never read about it (nore thought about it myself).


Questions: did you know this idiom? if yes, have you found it yourself or read 
about it? if the latter, where?


Denis
--
_
vita es estrany
spir.wikidot.com



ddoc patterns

2011-04-07 Thread spir

Hello,

In D stdlib's ddoc the idiom $(D some d code) is constantly used. But it does 
not work by me. Not only it's not interpreted, but the contents are stripped 
out all together. (A *very* big bug of ddoc.)

First, I'd like to know why.
Second, there is another pattern $(D_CODE some d code), but it place the code 
on a separate block. Is this intended?
Third, http://www.digitalmars.com/d/2.0/ddoc.html seems to imply one can define 
new patterns. How to do that? I tried following the example, but my code ends 
up interpreted and stripped out.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: ddoc patterns

2011-04-07 Thread spir

On 04/07/2011 10:20 AM, spir wrote:

Hello,

In D stdlib's ddoc the idiom $(D some d code) is constantly used. But it does
not work by me. Not only it's not interpreted, but the contents are stripped
out all together. (A *very* big bug of ddoc.)
First, I'd like to know why.
Second, there is another pattern $(D_CODE some d code), but it place the code
on a separate block. Is this intended?
Third, http://www.digitalmars.com/d/2.0/ddoc.html seems to imply one can define
new patterns. How to do that? I tried following the example, but my code ends
up interpreted and stripped out.


OK found it: pattern defs must be places under a Macro: section title.

I take the opprtunity to ask another question: does anyone know how to tag a 
*span* of text as literal/uninterpreted (either in html or css). The issue is 
pre makes a *block*, even if not inside a div or p; I desperately need 
the same feature for inline pieces of code.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: ddoc patterns

2011-04-07 Thread spir

On 04/07/2011 12:53 PM, bearophile wrote:

spir:


I take the opprtunity to ask another question: does anyone know how to tag a
*span* of text as literal/uninterpreted (either in html or css). The issue is
pre  makes a *block*, even if not inside adiv  orp; I desperately need
the same feature for inline pieces of code.


Try:

--
code here
--

Bye,
bearophile


This makes a block --just what I don't want.

Denis
--
_
vita es estrany
spir.wikidot.com



use of C memmove

2011-04-07 Thread spir

Hello,

I'm trying to use C's memmove as a tool to delete or insert a slice from/into 
an array. But I cannot manage to do it: systematic segmentation fault.

What is wrong below?

import std.c.string : memmove;
// void *memmove(void *dest, const void *src, size_t n);

void moveEnd (E) (E[] elements, size_t start, int offset) {
// Length must be known before possible extension.
auto length = elements.length;

// If move up, extend array to make place.
if (offset  0)
elements.length += offset;

// Move slice.
auto dest = cast(void*)((elements[start + offset]));
auto source = cast(void*)((elements[start]));
size_t size = length - start;
memmove(dest, source, size);// segfault ***

// If move down, compress array.
if (offset  0)
elements.length += offset;
}

unittest {
string s = 012--3456789;
// Remove slice.
s.moveEnd(5, -2);
writeln(s);
}

Denis
--
_
vita es estrany
spir.wikidot.com



Re: ddoc patterns

2011-04-07 Thread spir

On 04/07/2011 03:32 PM, Jacob Carlborg wrote:

On 2011-04-07 12:25, spir wrote:

On 04/07/2011 10:20 AM, spir wrote:

Hello,

In D stdlib's ddoc the idiom $(D some d code) is constantly used. But
it does
not work by me. Not only it's not interpreted, but the contents are
stripped
out all together. (A *very* big bug of ddoc.)
First, I'd like to know why.
Second, there is another pattern $(D_CODE some d code), but it place
the code
on a separate block. Is this intended?
Third, http://www.digitalmars.com/d/2.0/ddoc.html seems to imply one
can define
new patterns. How to do that? I tried following the example, but my
code ends
up interpreted and stripped out.


OK found it: pattern defs must be places under a Macro: section title.

I take the opprtunity to ask another question: does anyone know how to
tag a *span* of text as literal/uninterpreted (either in html or css).
The issue is pre makes a *block*, even if not inside a div or p; I
desperately need the same feature for inline pieces of code.

Denis


Have a look at the CSS display property:
http://w3schools.com/css/pr_class_display.asp


Great, does the trick!
But is there else really no other way to suspend interpretation as pre? I 
find this strange... how are we supposed to insert code phrases in the flow 
of normal text?


Denis
--
_
vita es estrany
spir.wikidot.com



Re: use of C memmove

2011-04-07 Thread spir

On 04/07/2011 08:12 PM, Steven Schveighoffer wrote:

On Thu, 07 Apr 2011 13:09:05 -0400, spir denis.s...@gmail.com wrote:


Hello,

I'm trying to use C's memmove as a tool to delete or insert a slice from/into
an array. But I cannot manage to do it: systematic segmentation fault.
What is wrong below?

import std.c.string : memmove;
// void *memmove(void *dest, const void *src, size_t n);

void moveEnd (E) (E[] elements, size_t start, int offset) {
// Length must be known before possible extension.
auto length = elements.length;

// If move up, extend array to make place.
if (offset  0)
elements.length += offset;

// Move slice.
auto dest = cast(void*)((elements[start + offset]));
auto source = cast(void*)((elements[start]));
size_t size = length - start;
memmove(dest, source, size); // segfault ***

// If move down, compress array.
if (offset  0)
elements.length += offset;
}

unittest {
string s = 012--3456789;
// Remove slice.
s.moveEnd(5, -2);
writeln(s);
}


Two problems. One is, the memmove size_t n is number of *bytes*, not number of
elements as you have expected. You probably would have noticed this quickly if
the other problem wasn't there.

The other problem is, strings literals are immutable. On Windows, this code may
have worked, but Linux protects the pages of static data, so writing to a
string literal creates a seg fault.

Try this:

auto s = 012--3456789.dup; // convert to char[]

To fix first problem use memmove(dest, source, size * (E).sizeof);


Thank you very much, Steven!

Denis
--
_
vita es estrany
spir.wikidot.com



error Not the start of the UTF-8 sequence

2011-04-06 Thread spir

Hello,

I get this error message:
Not the start of the UTF-8 sequence
without any other comment module name or whatnot.

This happens when I just added toString to the following struct, and used it:

struct Node {
// Note: level is equal to the number of chars up to this node.
// Note: a 'path' node without entry has key=.
char ch;
uint level;
Key key;
Value value;
...
string toString() {
if (this.key != )
return format(%s %s:%s, this.ch, this.key, this.value);
else
return format(%s, this.ch);
}
}

Hints? I'm blocked :-(

Denis
--
_
vita es estrany
spir.wikidot.com



[SOLVED] [BUG?] Re: error Not the start of the UTF-8 sequence

2011-04-06 Thread spir

On 04/06/2011 11:53 AM, Kagamin wrote:

spir Wrote:


Hello,

I get this error message:
Not the start of the UTF-8 sequence
without any other comment module name or whatnot.

This happens when I just added toString to the following struct, and used it:

  struct Node {
  // Note: level is equal to the number of chars up to this node.
  // Note: a 'path' node without entry has key=.
  char ch;
  uint level;
  Key key;
  Value value;
  ...
  string toString() {
  if (this.key != )
  return format(%s %s:%s, this.ch, this.key, this.value);
  else
  return format(%s, this.ch);
  }
  }

Hints? I'm blocked :-(



  struct Node {
  // Note: level is equal to the number of chars up to this node.
  // Note: a 'path' node without entry has key=.
  dchar ch;


Sorry, no, nothing to do with the type. The error came from a special case 
where ch='\0'. Seems some routine in dmd does not like that; but no idea where 
the error comes from.

There are two points to solve, I guess:
* The error message should tell where it happens.
* '\0' is a valid code point, should pass through without error.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: The is expression

2011-04-02 Thread spir

On 04/02/2011 12:14 AM, enuhtac wrote:

template isA( T )
{
 static if( is( T U == A!( U, s ), string s ) )
 enum bool isA = true;
 else
 enum bool isA = false;
};


What does , string s do here inside the is expression?

Denis
--
_
vita es estrany
spir.wikidot.com



Re: null Vs [] return arrays

2011-04-01 Thread spir

On 04/01/2011 12:38 PM, Regan Heath wrote:

On Mon, 28 Mar 2011 17:54:29 +0100, bearophile bearophileh...@lycps.com wrote:

Steven Schveighoffer:


So essentially, you are getting the same thing, but using [] is slower.


It seems I was right then, thank you and Kagamin for the answers.


This may be slightly OT but I just wanted to raise the point that conceptually
it's nice to be able to express (exists but is empty) and (does not exist).
Pointers/references have null as a (does not exist) value and this is
incredibly useful. Try doing the same thing with 'int' .. it requires you
either use int* or pass an additional boolean to indicate existence.. yuck.

I'd suggest if someone types '[]' they mean (exists but is empty) and if they
type 'null' they mean (does not exist) and they may be relying on the .ptr
value to differentiate these cases, which is useful. If you're not interested
in the difference, and you need performance, you simply use 'null'. Everybody
is happy. :)


That's the way I understand this distinction. Unfortunately, D does not really 
allow this, by semantically treating both indifferently (eg one can put a new 
element into an null array).


Denis
--
_
vita es estrany
spir.wikidot.com



Re: We could use a hasExt function in std.path

2011-04-01 Thread spir

On 04/01/2011 11:03 PM, Andrej Mitrovic wrote:

At least on Windows, as far as I know, the casing of a file extension doesn't 
come into play. But when comparing extensions, you have to be careful to 
lowercase the result of `getExt()`, for example:

foreach (string name; dirEntries(curdir, SpanMode.shallow))
{
 if (name.isFile  name.getExt == txt)
 {
 // do something
 }
}

If the extension is cased tXt, the if block will not be entered. That's a 
silent bug in your code right there!

I think we could use a function in Phobos that returns true if an extension of 
a file matches any number of strings passed to it (a range). And an extra 
argument could be a flag (enum) or a boolean which can set the case sensitivity 
to true, but is false by default, e.g.:

bool hasExt(Range)(string fileName, Range exts, bool caseSensitive = false)
{
 static if (isSomeString!Range)
 {
 if (caseSensitive)
 {
 if (exts == fileName.getExt)
 return true;
 }
 else
 {
 if (exts.tolower == fileName.getExt.tolower)
 return true;
 }
 }
 else
 {
 foreach (ext; exts)
 {
 if (caseSensitive)
 {
 if (ext == fileName.getExt)
 return true;
 }
 else
 {
 if (ext.tolower == fileName.getExt.tolower)
 return true;
 }
 }
 }

 return false;
}

foreach (string name; dirEntries(curdir, SpanMode.shallow))
{
 if (name.isFile  name.hasExt([ini, conf]))
 {
 // do something
 }
}

Yes, that is a horrible implementation, but I can't be bothered with trying to 
make it nice and simple right now, I'm in a rush. Sorry. :)

I often have to search for files that have a certain extension. Having to 
expand the code to the following becomes ugly real fast:

foreach (string name; dirEntries(curdir, SpanMode.shallow))
{
 if (name.isFile  name.hasExt.tolower == ini ||
name.hasExt.tolower == conf))
 {
 // do something
 }
}


Would be nice eg to match a whole set of image formats at once (while also 
caring for uncased matching). But why a range?


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Contracts or Exceptions?

2011-03-30 Thread spir

On 03/30/2011 05:32 AM, Ali Çehreli wrote:

On 03/29/2011 03:40 PM, Kai Meyer wrote:


 I was given two words of advice on exceptions:
 Use exceptions for the exceptional
 Use exceptions only for the exceptional


Those advices are given by wise people: they are wise only because they leave
the definition as vague as exceptional. :)

And what do we do for the not so exceptional? Do we return error codes? So
the function implementation will be complicated and the caller code will be
complicated.

Exceptions are a great tool to eliminate the need for error codes.

Here is what I follow:

- Functions have specific tasks to do; if those tasks cannot be accomplished,
the function must throw.

In some cases the function can continue, but that behavior must be documented.
For example, if an HTML library function is responsible for making HTML
headers, of which only the levels in the range of 1-6 are valid, that function
may throw when the level is outside of the valid range, for in that case it
cannot make an HTML header; or it can document that if the level is outside
of the range, 1 or 6 will be used.

- Catch exceptions only when there is a sensible thing to do at that level: log
an error, skip that operation, go back to the user with an error code, take
corrective action, etc.

Disclaimer: That is what I follow in C++ code. I don't have experience with
exception safety in D. I don't know issues that may be specific to D.


These are sensible and well expressed guidelines, thank you.
In other languages, I happened to use exceptions as a // channel for 
side-information (eg 'nomatch' for a matching func), but in D I realised how 
'exceptionnally' (!) costly throwing  catching exceptions is, so that I do not 
do it anymore. No idea though whether this exceptional cost is perticular to D.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Memory usage of AAs?

2011-03-30 Thread spir

On 03/30/2011 03:31 PM, Steven Schveighoffer wrote:

On Tue, 29 Mar 2011 22:20:05 -0400, Nick Sabalausky a@a.a wrote:


spir denis.s...@gmail.com wrote in message
news:mailman.2909.1301443345.4748.digitalmars-d-le...@puremagic.com...

On 03/30/2011 01:24 AM, Nick Sabalausky wrote:

My understanding of hash tables is that they allocate a fixed size array
and
map keys to indicies within the range 0..predefined_length_of_the_AA.

So I've been wondering, how many elements do D's built-in AAs have? And
what's the content of each one, just a single pointer?


Each element is a data structure, often called bucket (typically a link
list), storing (key:value) pairs for which the key, once hashed and
modulo-ed, maps to the given index. That's why the famous O(1) lookup time
for hash tables is very theoretic: the constant part holds average time
for hashing which is very variable, plus another average time for linearly
traversing the bucket. The latter part depends on table load factor (=
number of elements / number of buckets) and proper statistical repartition
of keys into buckets.

The key (!) points are finding a good hash func to linearize said
repartition (which depends on actual key-data domain, not only on their
type...), but better ones rapidly eat much time (ones used in practice are
rather simple  fast); and finding optimal load factor, and growth scheme.
In practice, all of this tends to make hash tables an implementation
nightmare (for me). I'd love to find practicle alternatives, but efficient
binary trees also are complex and even more depend on kind of keys, I
guess.



Right, I know that, but that's not what I was asking. Take this hypothetical
implementation:

struct Bucket(TKey, TVal)
{
...
}

enum hashTableSize = ...;

struct Hash(TKey, TVal)
{
Bucket!(TKey, TVal)[hashTableSize] data;

TVal get(TKey key) { ... }
void set(TKey key, TVal value) { ... }
}

I assume that D's AA are something at least vaguely like that. My questions
are:

1. What does D use for hashTableSize? Or does hashTableSize vary? If it
varies, what's a typical rough ballpark size? (And just out of curiosity, if
it varies, is it decided at compile-time, or does it change even at
runtime?)


It varies. The hash table size is not constant, the load factor is. The load
factor is the number of elements in the hash divided by the number of buckets.
You never want to fill up all the spaces, because the more full you get, the
more chances for collisions there are. Essentially, the tricky part about
hashing is what to do about collisions (two elements are different, but go in
the same bucket).

So what happens is when the load factor exceeds a predefined constant (e.g. in
dcollections the load factor defaults to .75), the table rehashes, or
increases (usually logarithmically) the size of the array, and re-inserts all
its elements.

I believe there is a minimum array size, and things are increased from there. I
think also you can do a manual rehash which should adjust the size of the
array to match a certain load factor (below the maximum).


Yes, there is a rehash method.


In some implementations, hashes will even shrink when the load factor goes
below a minimum (dcollections does not do this to avoid invalidating ranges).
There are a million different ways to implement the basic hash. The most
complex part though, is usually the collision handling. In my algo book, there
are at least 3 ways to handle collisions, and I think there are countless more.
If you look up hashing on wikipedia, you'll get a much better explanation.



2. What is sizeof(Bucket(TKey, TVal))? And I mean the shallow size, not
deep size. Is it dependent on TKey or TVal? Or is it just simply a pointer
to the start of a linked list (and therefore sizeof(size_t))?


Here is the AA implementation:

https://github.com/D-Programming-Language/druntime/blob/master/src/rt/aaA.d

 From that page, you can see that AA is your bucket (note this is runtime
stuff, so there are no templates), and BB is your Hash struct. It looks like BB
has an array of AA pointers.


IIRC, this is because buckets are (minimal) link lists. Cells holding key:value 
are list nodes.



-Steve


--
_
vita es estrany
spir.wikidot.com



Re: Using opDispatch as *magic* getter/setter. Possible or not?

2011-03-30 Thread spir

On 03/31/2011 02:40 AM, Aleksandar Ružičić wrote:

2011/3/31 Aleksandar Ružičićruzicic.aleksan...@gmail.com:


Or maybe there is some other way to achive what I want and I'm not
aware of it? :-)



I know I could have used opIndex and opIndexAssign but I really want
config.section.entry syntax instead of config[section][entry]...


Agreed. And I would really have an answer to your question, since I tried to do 
the same thing. Don't understand why D does not have an 'opMember' or 'opDot'. 
Someone knows?
This would be one of the first metamethods I would introduce in a language 
(definitely before operator overloading).


denis
--
_
vita es estrany
spir.wikidot.com



Re: Container access in std.container

2011-03-29 Thread spir

On 03/29/2011 12:43 PM, Ishan Thilina wrote:


I'm using GDC because I can't use DMD in linux. I have started a seperate thread
for that.


I'm using dmd on Linux without any issue. But only stable releases (several 
versions have passed).
May I suggest you take some time to uninstall everything properly, then install 
again from scratch according to the online guidelines:

downloads: http://www.digitalmars.com/d/download.html
win: http://www.digitalmars.com/d/2.0/dmd-windows.html
linux: http://www.digitalmars.com/d/2.0/dmd-linux.html

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Memory usage of AAs?

2011-03-29 Thread spir

On 03/30/2011 01:24 AM, Nick Sabalausky wrote:

My understanding of hash tables is that they allocate a fixed size array and
map keys to indicies within the range 0..predefined_length_of_the_AA.

So I've been wondering, how many elements do D's built-in AAs have? And
what's the content of each one, just a single pointer?


Each element is a data structure, often called bucket (typically a link list), 
storing (key:value) pairs for which the key, once hashed and modulo-ed, maps to 
the given index. That's why the famous O(1) lookup time for hash tables is very 
theoretic: the constant part holds average time for hashing which is very 
variable, plus another average time for linearly traversing the bucket. The 
latter part depends on table load factor (= number of elements / number of 
buckets) and proper statistical repartition of keys into buckets.


The key (!) points are finding a good hash func to linearize said repartition 
(which depends on actual key-data domain, not only on their type...), but 
better ones rapidly eat much time (ones used in practice are rather simple  
fast); and finding optimal load factor, and growth scheme. In practice, all of 
this tends to make hash tables an implementation nightmare (for me). I'd love 
to find practicle alternatives, but efficient binary trees also are complex and 
even more depend on kind of keys, I guess.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Sample source code for D

2011-03-28 Thread spir

On 03/28/2011 05:43 AM, Ishan Thilina wrote:

@ David:

I'm looking for example code that explains specific pieces of functionality :)

@Lutger:

Those two links were really helpful :). Thank you :)


There are tutorial examples of D code at DSource; they were initially D1, but 
many of them are compatible or translated to D2; rather good place to start:

http://www.dsource.org/projects/tutorials

On the official D wiki, you'll find some useful material and links (tutorial, 
example, howto); unfortunatly, some of those materials are rather light:

http://prowiki.org/wiki4d/wiki.cgi?DevelopmentWithD
http://prowiki.org/wiki4d/wiki.cgi?D__Tutorial
http://prowiki.org/wiki4d/wiki.cgi?HowTo
http://prowiki.org/wiki4d/wiki.cgi?ExamplesRoadmap

Also useful comparisons:
http://prowiki.org/wiki4d/wiki.cgi?LanguagesVersusD
http://en.wikibooks.org/wiki/D_Transition_Guide

Denis
--
_
vita es estrany
spir.wikidot.com



Re: object.d: Error: module object is in file 'object.d' which cannot be read

2011-03-28 Thread spir

On 03/28/2011 04:49 PM, Ishan Thilina wrote:


now I get a whole lot more errors :s.


ishan@ishan-Ubu-I1464:~/Geany Projects$ dmd untitle.d
/usr/include/d/dmd/phobos/object.d(51): C-style function pointer and pointer to
array syntax is deprecated. Use 'function' to declare function pointers
/usr/include/d/dmd/phobos/std/format.d(672): no identifier for declarator
inout(fakevalue)
/usr/include/d/dmd/phobos/std/c/stdlib.d(43): C-style function pointer and 
pointer
to array syntax is deprecated. Use 'function' to declare function pointers
/usr/include/d/dmd/phobos/std/c/stdlib.d(59): C-style function pointer and 
pointer
to array syntax is deprecated. Use 'function' to declare function pointers
/usr/include/d/dmd/phobos/std/c/linux/linux.d(558): C-style function pointer and
pointer to array syntax is deprecated. Use 'function' to declare function 
pointers
/usr/include/d/dmd/phobos/std/c/linux/linux.d(574): C-style function pointer and
pointer to array syntax is deprecated. Use 'function' to declare function 
pointers


I'm trying to compile the following simple code. As you can see it should work
without any problem.


import std.stdio;



int main()

{

writefln(Hello world);



return 0;

}


I have no idea why and where your issues in using D with dmd come from. AFAIK, 
it just works out of the box if you use release versions.


Just 2 notes about the piece of code:
First, you often do not need in D a program result code (int).
Second, writefln, as opposed to writeln, expects a format string as first 
argument.

void main () {
writeln(Hello, world!);
auto userName = Otto;
writefln(Hello, %s!, userName);
}

Denis
--
_
vita es estrany
spir.wikidot.com



Re: object.d: Error: module object is in file 'object.d' which cannot be read

2011-03-27 Thread spir

On 03/27/2011 12:28 PM, Ishan Thilina wrote:

When I give dmd untitled.d command in my ubuntu maverick 64 bit laptop I get
the following error.


object.d: Error: module object is in file 'object.d' which cannot be read
import path[0] = /etc/../../src/phobos
import path[1] = /etc/../../src/druntime/import


I tried all morning to solve this problem, tried every google result I could
find. Checked the mail archive to solve this problem. But I still couldn't get
rid of that error.I anybody can help me, it would be a great help.

I followed the steps in http://www.digitalmars.com/d/2.0/dmd-linux.html .I
first used the command cp dmd2/linux/bin/dmd.conf /etc
 . Then I gave sudo apt-get install gcc-multilib g++-multilib libc6-i386
libc6-dev-i386 command.

Thank you :)


First, please always post the piece of code that provokes an error. If it's a 
big or complicated thing, then try to reduce it to the smallest and simplest 
bit possible. Usually, doing this will let you find the source of the problem ;-)


Second, this kind of error is caused by wrong import path (yes, the error 
message could mention import). Typically, when one writes eg:

import range;
instead of
import std.range;
But your case is strange. Do you know object.d is the core of D's std lib, 
which defines about all what you absolutely need to use when programming in D? 
One does not need to import it, this is automatical. Also, the message says the 
error happens in object.d itself, which is very un-probable.
I thus suspect you named one of your own modules object.d, which breaks the 
import mechanics (for D's standard object.d and possibly for other 
stdlib/phobos modules). This may be considered as a bug.


denis
--
_
vita es estrany
spir.wikidot.com



Re: object.d: Error: module object is in file 'object.d' which cannot be read

2011-03-27 Thread spir

On 03/27/2011 12:28 PM, Ishan Thilina wrote:

When I give dmd untitled.d command in my ubuntu maverick 64 bit laptop I get
the following error.


object.d: Error: module object is in file 'object.d' which cannot be read
import path[0] = /etc/../../src/phobos
import path[1] = /etc/../../src/druntime/import


I tried all morning to solve this problem, tried every google result I could
find. Checked the mail archive to solve this problem. But I still couldn't get
rid of that error.I anybody can help me, it would be a great help.

I followed the steps in http://www.digitalmars.com/d/2.0/dmd-linux.html .I
first used the command cp dmd2/linux/bin/dmd.conf /etc
 . Then I gave sudo apt-get install gcc-multilib g++-multilib libc6-i386
libc6-dev-i386 command.

Thank you :)


PS: I tried to compile an empty module called object.d. This gives me pages  
pages  pages of undefined x errors ;-)


denis
--
_
vita es estrany
spir.wikidot.com



Re: Want to help DMD bugfixing? Write a simple utility.

2011-03-24 Thread spir

On 03/24/2011 08:53 AM, Alexey Prokhin wrote:

Currently, as far as I know, there are only two lexers and two parsers for
 D: the C++ front end which dmd, gdc, and ldc use and the D front end which
 ddmd uses and which is based on the C++ front end. Both of those are under
 the GPL (which makes them useless for a lot of stuff) and both of them are
 tied to compilers. Being able to lex D code and get the list of tokens in
 a D program and being able to parse D code and get the resultant abstract
 syntax tree would be very useful for a number of programs.


I fully support this. We desperately need it, I guess, working and maintained 
along language evolution.
This is the whole purpose of the GSOC proposal D tools in D: 
http://prowiki.org/wiki4d/wiki.cgi?GSOC_2011_Ideas#DtoolsinD

Semantic analysis, introduced step by step, would be a huge plus.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Little quiz

2011-03-24 Thread spir

On 03/25/2011 01:50 AM, bearophile wrote:

A little quiz for people here: guess the output of this little D2 program (it 
compiles correctly and doesn't crash at run time, so it's a fair question):


import std.typecons: tuple;
import std.c.stdio: printf;

auto foo() {
 printf(foo\n);
 return tuple(1, 2);
}

void main() {
 foreach (x; foo().tupleof)
 printf(%d\n, x);
}


lol, would never haver guessed

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Other integral literals?

2011-03-20 Thread spir

On 03/20/2011 04:40 PM, bearophile wrote:

Do you ever desire literals for byte, ubyte, short and ushort integrals (beside 
the currently present for int, uint, long, ulong that are 10, 10U, 10L, 10UL)?

Because of the more strict typing of templates in some situations I have had to 
write things like:

cast(ubyte)100

Possible literals for byte, ubyte, short and ushort integrals (the byte ones 
aren't great):
10Y
10UY
10S
10US

Are similar suffixes useful enough to have?


I would support this gratefully. I find it a big weakness of D that its 
literals do not map to a type.


As for precise morphology, I'd prefere
* instead of cryptic suffixes like 'Y' or 'S', numerous languages simply write 
the size : 8, 16, 32, 64: much nicer! A better idea would be to count the size 
in bytes: 1, 2, 4, 8.
* else, use lowercase suffixes in std, because digits are full height (so that 
the suffix is more clearly told apart)
* for the same reason, hex literals should use uppercase digits in std and '0x' 
prefix
* ideally, I would use the sign to tell signed types apart (1 is unsigned, +1 
is signed)

* get rid of 1. and .1 horrors!
* get rif of 01 octal bug!

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Ranges

2011-03-18 Thread spir

On 03/18/2011 10:29 AM, Peter Alexander wrote:

On 13/03/11 12:05 AM, Jonathan M Davis wrote:

So, when you're using a range of char[] or wchar[], you're really using a range
of dchar. These ranges are bi-directional. They can't be sliced, and they can't
be indexed (since doing so would likely be invalid). This generally works very
well. It's exactly what you want in most cases. The problem is that that means
that the range that you're iterating over is effectively of a different type
than
the original char[] or wchar[].


This has to be the worst language design decision /ever/.

You can't just mess around with fundamental principles like the first element
in an array of T has type T for the sake of a minor convenience. How are we
supposed to do generic programming if common sense reasoning about types
doesn't hold?

This is just std::vectorbool from C++ all over again. Can we not learn from
mistakes of the past?


I partially agree, but. Compare with a simple ascii text: you could iterate 
over it chars (=codes=bytes), words, lines... Or according to specific schemes 
for your app (eg reverse order, every number in it, every word at start of 
line...). A piece of is not only a stream of codes.


The problem is there is no good decision, in the case of char[] or wchar[]. We 
should have to choose a kind of natural sense of what it means to iterate 
over a text, but there no such thing. What does it *mean*? What is the natural 
unit of a text?
Bytes or words are code units which mean nothing. Code units (- dchars) are 
not guaranteed to mean anything neither (as shown by past discussion: a code 
unit may be the base 'a', the following one be the composite '^', both in â). 
Code unit do not represent characters in the common sense. So, it is very 
clear that implicitely iterating over dchars is a wrong choice. But what else?
I would rather get rid of wchar and dchar and deal with plain stream of bytes 
supposed to represent utf8. Until we get a good solution to operate at the 
level of human characters.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Reading a line from stdin

2011-03-16 Thread spir

On 03/16/2011 06:05 AM, Ali Çehreli wrote:

I am going over some sample programs in a text of mine and replacing
std.cstream references with std.stdio. There are non-trivial differences with
formatted input.

The following program may be surprising to the novice:

import std.stdio;

void main()
{
write(What is your name? );
string name = readln();
writeln(Hi , name, !);
}

The newline character is read as a part of the input:

What is your name? Ali
Hi Ali
! -- this is outputted on the next line
because of the newline character


This is a design bug. 99% of the time one does not want the newline, which is 
not part of the string data, instead just a terminator. Even more on stdin 
where it is used by the user to say Im done!.
If the text is written back to the output /and/ newline is needed, it's easy to 
add it or use writeln.


Also, to avoid using strip --which is costly and may remove other significant 
whitespace at start and end of line, one would have to manually check for CR 
and/or LF, and remove it, *twice*. A solution may be to have a boolean param 
keepNewLine beeing false in standard.



A solution is to strip the line after reading:

import std.string;
// ...
string name = strip(readln());

Right? Is there a better way that I am missing?


Dunno.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Reading a line from stdin

2011-03-16 Thread spir

On 03/16/2011 06:41 AM, Jesse Phillips wrote:

Ali Çehreli Wrote:


Right? Is there a better way that I am missing?

Thank you,
Ali


No better way, the stated reason IIRC is that it is easier to remove the new 
line then to append it back on.


May be stated, but it is very wrong! I guess:

s = s ~ '\n';
versus
if ((str[$-1] == '\n') || (str[$-1] == '\r')) {
str = str[0..$-1];
if ((str[$-1] == '\n') || (str[$-1] == '\r')) {
str = str[0..$-1];
}
}

And it's not what programmers want in most cases, anyway. Actually, when does 
one need it?


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Help passing D strings to C libs

2011-03-14 Thread spir

On 03/14/2011 07:55 AM, Gene P. Cross wrote:

-Daniel
I tried what you said:

char* ptr = toStringz(path);
SDL_LoadBMP(ptr);

and made a check to see if the pointer is null, which it isn't, but I'm unable 
to
inspect is value, I haven't a debugger at the moment, could you recommend one ?

I also made the string a char[] and tested to see if that made a difference.

I think it may be something to do with SDL itself. I tried calling another
function, SDL_GetTicks(), and that's causing problems as well.


-Jonathan
I read the docs earlier and found the same thing about literals being null
terminated but not regular strings,
which explains why they work.
Double check after double check, I am also certain that no other code is messing
with it and changing values.


I'm surprised about your problem. There is no difference between the .ptr 
property of a null-terminated D char[] and a C string (hum). And I'm rather 
sure (not checked the code) that's precisely what toStringZ does. The issue 
must lie on some point you have not mentionned yet.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Iterating over an enum associative array

2011-03-14 Thread spir

On 03/14/2011 12:21 PM, Nebster wrote:

Hey,

I'm having some problems iterating over an enumerated associative array.
It comes up with this error at compile time:

 Internal error: e2ir.c 4835

I cut the code down to this:


 import std.stdio;

 enum int[string] assoc = [;: 0, =: 1, +: 2, -: 2, *: 3, /: 3];

 void main()
 {
 foreach(op; assoc.byKey())
 writefln(op: %s, op);
 }


What does this mean/how can I get this to work?


There are problems with associative array constants. I'm not 100% sure this is 
the source of your error, though. Anyway, the following works fine, using the 
module's static this constructor:


static int[string] assoc;
static this () {
assoc = [;: 0, =: 1, +: 2, -: 2, *: 3, /: 3];
}
static enum seq = [1,2,3];

unittest {
foreach(op ; assoc.byKey())
writefln(op: %s, op);
foreach(n ; seq)
writefln(n: %s, n);
}
==
op: *
op: +
op: -
op: /
op: ;
op: =
n: 1
n: 2
n: 3

You can use this trick each time you need a D module to hold predefined and/or 
precomputed data (meaning, you need D to play the role of a data description 
language).
This is not needed if said data is plain simple literal values. As you see, dmd 
does not consider an associative array to be plain simple literal, even when it 
obviously is; but a sequential array, yes.



A side note: constant struct data can be directly defined at the module 
top-level, at least in simple cases. But (for any reason), dmd in fact does not 
create a single constant value that will be used everywhere you write its name. 
Instead, it re-creates the constant value at each place you write it. Aside the 
possible cost (?), this can create bugs if you count on it be unique:


struct S { int i; }
enum S* ps0 = (S(0)), ps1 = (S(1));

unittest {
S* ps;
if (true) ps = ps0; else ps= ps1;
assert (*ps == *ps0);   // indeed
//~ assert (ps == ps0); // fail !!!
writefln(%s != %s, ps,ps0);   // BFC95FE4 != BFC95FF0
}

The trick of using the module's static this clause also solves this issue.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Ranges

2011-03-13 Thread spir

On 03/13/2011 01:05 AM, Jonathan M Davis wrote:

If you were to try and iterate over a char[] by char, then you would be looking
at code units rather than code points which is _rarely_ what you want. If you're
dealing with anything other than pure ASCII, you _will_ have bugs if you do
that. You're supposed to use dchar with foreach and character arrays. That way,
each value you process is a valid character. Ranges do the same, only you don't
give them an iteration type, so they're _always_ iterating over dchar.


Side-note: you can be sure the source is pure ASCII if, and only if, it is 
mechanically produced. (As soon as an end-user touches it, it may hold 
anything, since OSes and apps offer users means to introduces characters which 
are not on their keyboards).
This can also easily be checked in utf-8 (which has been designed for that): 
all ASCII chars are coded using the same code as in ASCII, thus all codes 
should be  128.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: foo.bar !in baz not allowed?

2011-03-13 Thread spir

On 03/13/2011 07:58 PM, Magnus Lie Hetland wrote:

For some reason, it seems like expressions of the form foo.bar !in baz aren't
allowed. I suspect this is a grammar/parser problem -- the bang is interpreted
as a template argument operator, rather than a negation operator, and there's
really no need to make that interpretation when it is immediately followed by
in. This suspicion is strengthened by the fact that bar !in baz is fine, as
is (foo.bar) !in baz.

Should I file this as a bug?

Small sample program:

struct Foo {
uint bar;
}

struct Baz {
bool opIn_r(uint e) {
return false;
}
}

void main() {
Baz baz;
Foo foo;
auto res = (foo.bar) !in baz;
res = !(foo.bar in baz);
// res = foo.bar !in baz; // Not OK...
uint frozz;
res = frozz !in baz;
}


Would be nice to copy the error, wouldn't it?
template argument expected following !

Anyway, this is definitely a bug in my opinion.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Commenting out a print slows my code?

2011-03-10 Thread spir

On 03/10/2011 01:44 AM, Charles McAnany wrote:

Hi, all. I'm in college, taking a freshman-level CS class. (I'm actually a
senior chemist with free time.)
Anyhoo, the warm-up assignment was Hardy Taxi problem, phrased like this:
[Exposition removed.] 1729 is the smallest number such that for
(a!=b!=c!=d)0, there exists a combination of a, b, c, and d where a^3+b^3 =
1729 = c^3+d^3.
The task was to find all other numbers with this property less than 25,000.
The code is basically

for (int iters = 1; iters= 25_000; iters++){
if(isTaxiNumber(iters)){
   writefln(%s is a taxi number, iters);
}
}

(There's also a StopWatch timing things, and isTaxiNumber returns a struct,
not a bool. See attached code.)
This code runs in about 0.09 seconds.
If I comment out the writefln, it takes 0.11 seconds.
(These are collected from about 20 runs of each. Times are very consistent.)
Any ideas why commenting out the write makes things slower?


No idea.

But more idiomatic D would rather b:
foreach (n ; 1..25000)
{...}

Also I don't understand why your loop var is called 'iters'.

Finally, the attachment is not readible by me: see below.

Denis


begin 644 taxi.d
M:6UP;W)T('-T9YD871E=EM93L@+R\@9F]R('1H92!3=]P5V%T8V@@W1R
M=6-T+B`-FEM]R=!S=0NW1R:6YG.R`O+V9OB!T:4@9F]R;6%T*DN
M(`T*:6UP;W)T('-T9YS=1I;SL@+R]PFEN=EN9RX@#0HO+R\@02!S=')U
M8W0@=AA=!R97!R97-E;G1S($@8V%B+B!)=!D;V5S;B=T(1O('1H92!C
M:5C:VEN9R!T:%T('1H92!O;F4@:6X@=AE(%SVEG;FUE;G0@9]ERP@
M=AO=6=H+B`-G-TG5C=!T87AI0V%BPT*6EN=!T87AI3G5M8F5R.PT*
M6EN=!A+!B+!C+!D.PD-@ES=')I;F@=]3=')I;FH*7L-@D)F5T
M=7)N(9OFUA=@B8V%R(5S(#T@6R5S(5S(5S(5S72(L=%X:4YU;6)E
MBP@82P@8BP@8RP@9D[#0H)?0T*?0T*#0HO*BH-BH@4')O9W)A;2!T:%T
M(UE87-UF5S('1H92!T:6UE(ET('1A:V5S('1O(1E=5R;6EN92!T:4@
M=%X:2!N=6UB97)S(QEW,@=AA;B`R-3`P,X@#0HJ($%U=AOCH@0VAA
MFQER!-8T%N86YY#0HJ#0HJ+PT*=F]I9!M86EN*E[#0H)4W1O%=A=-H
M('-W.PT*7-W+G-T87)T.PT*69OB`H:6YT(ET97)S(#T@,#L@:71EG,\
M(#(U,#`P.R!I=5RRLK*7L-@D)=%X:4-A8B!C86))1`](ES5%X:2AI
M=5RRD[#0H)6EF*-A8DE$+F,@(3T@,E[#0H)0EWFET96QN*-A8DE$
M*3L-@D)?0T*7T-@ES=RYS=]P.PT*51I8VMS('1I;65486ME;B`]('-W
M+G!E96L[#0H)=W)I=5F;XH(B5S7'0ER(L,C4P,#`L=EM951A:V5N+G1O
M4V5C;VYDR%F;]A=D[#0H)WNF5S970[#0H-GT-@T*+RHJ#0HJ(ES
M5%X:2!D971EFUI;F5S(EF(%N(EN=5G97(@%SV5D('1O(ET(ES
M($@=%X:2!N=6UB97(L('1H870@:7,L('1H97)E(5X:7-TPT**B!A;B!A
M+!B+!C+!A;F0@9P@;F]N92!O9B!T:5M('1H92!S86UE+!S=6-H('1H
M870@#0HJ(%,RMB7C,@/2!N(#UC7C,@*V1,RX@#0HJ(')E='5R;G,Z(`T*
M*B!A('1AE#86(@W1R=6-T+!W:71H($L((L(,L(%N9!D(EF(9O
M=6YD+B!I9B!O;FQY(]N92!S;VQU=EO;B!T;R!X7C,K5XS('=AR!F;W5N
M9P@#0HJ(,@86YD(0@=VEL;!B92!Z97)O+B!)9B!N;VYE('=EF4@9F]U
M;F0L('1H96X@82!A;F0@8B!W:6QL()E('IEF\@87,@=V5L;X@#0HJ('!A
MF%M971EG,Z(`T**B!N(ES(%N(EN=5G97(@=AA=!IR!T;R!B92!C
M:5C:V5D(9OB!T87AI(YU;6)EBUN97-S+B`-BHO#0IT87AI0V%B(ES
M5%X:2AI;G0@;BE[#0H):6YT(QI;6ET(#T@8W5B95)O;W1;]OBAN*2`M
M(#$[#0H):6YT(AI=',@/2`P.R`-@EI;G1;72!R97-U;'1S(#T@6S`L,PP
M+#!=.PT*69OB`H:6YT(D@/2`P.R!I(#P@;EM:70[(DK*RD@PT*0EI
M;G0@F5S(#T@;B`M(DJ:2II.PT*0ED;W5B;4@8W5B95)O;W0@/2!R97-
M7B@Q+S,N,D[#0H)6EN=!N96%R97-T26YT(#T@8V%S=AI;G0I(AC=6)E
M4F]O=`K(#`N-2D[#0H)61O=6)L92!D:69F(#T@*-U8F52;V]T(T@;F5A
MF5S=$EN=D@*B`H8W5B95)O;W0@+2!N96%R97-T26YT*3L-@D):68@*1I
M9F8@/`Q92TQ,D@PT*0D):68@*AI=',@/`R(8F(')EW5L='-;,5T@
M(3T@:2D@PT*0D)7)EW5L='-;:ETR`J(#)=(#T@:3L-@D)0ER97-U
M;'1S6VAI=',@*B`R(L@,5T@/2!N96%R97-T26YT.PT*0D)?0T*0D):ET
MRLK.PT*0E]#0H)?0T*7)E='5R;B!T87AI0V%B*XLF5S=6QTULP72QR
M97-U;'1S6S%=+')EW5L='-;,ETLF5S=6QTULS72D[#0I]#0H-B\O+R!F
M:6YDR!T:4@;%R9V5S=!I;G1E9V5R('@@W5C:!T:%T('A,R`\(X@
M#0II;G0@8W5B95)O;W1;]OBAI;G0@;BE[#0H)9]U8FQE(-U8F52;V]T
M(#T@;B!7B`H,2\S+C`I.PT*6EN=!CD9L(#T@8V%S=AI;G0I(-U8F52
6;V]T.PT*7)E='5R;B!CD9L.PT*?0``
`
end


--
_
vita es estrany
spir.wikidot.com



Re: Best way in D2 to rotate a ubyte[4] array

2011-03-09 Thread spir

On 03/10/2011 12:55 AM, Jonathan M Davis wrote:

I don't know of anything more efficient than:
ubyte[4] bytes = [1,2,3,4];
bytes = bytes[$-1] ~ bytes[0..$-1]; // Rotate left

I'm stunned that this works. I'd even consider reporting it as a bug. You're
concatenating a ubyte[] ont a ubyte...


This works for other arrays as well. dmd understands.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: I seem to be able to crash writefln

2011-03-09 Thread spir

On 03/10/2011 12:19 AM, Joel Christensen wrote:

This is on Windows 7. Using a def file to stop the terminal window coming up.

win.def
EXETYPE NT
SUBSYSTEM WINDOWS

bug.d
import std.stdio;
import std.string;

void main() {
auto f = File( z.txt, w );
scope( exit )
f.close;
string foo = bar;
foreach( n; 0 .. 10 ) {
writefln( %s, foo );
f.write( format( count duck-u-lar: %s\n, n ) );
}
}

output (from in z.txt):
count duck-u-lar: 0


What do you mean, crashing writefln? What do you get on the terminal?
About the file, there seems to be a bug --but unrelated to writefln. The file 
is closed, I guess because of scope(exit), before the output stream is flushed. 
If this is the right interpretation, then there is a precedence issue; scope's 
action should not be performed before the func's own action is actually completed.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: using enums as key in associative array

2011-03-08 Thread spir

On 03/08/2011 09:26 AM, Wilfried Kirschenmann wrote:

enum deviceType {cpu, gpu}
auto execDeviceSuffix = [deviceType.cpu:.cpu, deviceType.gpu:.gpu];



The way to get what you want to work in this case is to use a module
constructor. So, you'd do something like this:

string[deviceType] execDeviceSuffix;

static this()
{
execDeviceSuffix[deviceType.cpu] = cpu;
execDeviceSuffix[deviceType.gpu] = gpu;
}

The module constructor will be run before main does, so execDeviceSuffix will be
properly filled in by then.


I didn't get to the point where module constructors are introduced in
Andrei's book yet. I really like this idea !
I found a similar workaround which used an useless class so that I
could use the static constructor but this is even better !


This is a very nice feature, yes. But I personly see it as a workaround for the 
limitation that dmd, apparently, is not able to correctly evaluate many kinds 
of assignment expressions. And it's ugly when one has hordes of definitions -- 
the module is (mainly) a piece of data description: all symbols must first be 
declared /outside/, then redefined /inside/ static this(). Else, D would be a 
great data-definition language, in addition to its other qualities, thank to 
its literals for everything (and conversely its standard to!string for 
everything, which needs improvements). Think a static Lua.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: using enums as key in associative array

2011-03-08 Thread spir

On 03/08/2011 03:48 PM, Jonathan M Davis wrote:

I really don't understand your problem with module constructors. They're
fantastic.


I may be wrong, but I think this point of view is a where I can from 
statement. C's char* are fantastic when you have never used a PL with builtin 
strings. There are languages in which you don't need to list twice everything 
just to have them available at import time.


// data definition
X foo;
Y bar;
Z baz;
...
static this {
   foo = ...;
   bar = ...;
   baz = ...;
   ...
}

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Templated struct doesn't need the parameterized type in return type definitions?

2011-03-08 Thread spir

On 03/08/2011 06:20 PM, Steven Schveighoffer wrote:

On Tue, 08 Mar 2011 12:06:08 -0500, Andrej Mitrovic n...@none.none wrote:


import std.stdio;
import std.traits;
import std.exception;

struct CheckedInt(N) if (isIntegral!N)
{
private N value;
ref CheckedInt opUnary(string op)() if (op == ++)
{
enforce(value != value.max);
++value;
return this;
}
this(N _value)
{
value = _value;
}
}

I didn't know you could define a return type of a templated struct without
defining the type it is parameterized on. I mean this line:

ref CheckedInt opUnary(string op)() if (op == ++)

I thought for sure I always had to write the parameterized type like so:

ref CheckedInt!(N) opUnary(string op)() if (op == ++)

So I guess this really isn't a question but more of a oh, I didn't know you
could do that. In fact I rarely see this kind of code in Phobos, most of the
time the parameterized type is specified in these types of cases. Is this
feature described somewhere, because I must have missed it if it is?


It is described, but not directly.

Look on this page:

http://www.digitalmars.com/d/2.0/template.html

 From there we have these two descriptions:



If a template has exactly one member in it, and the name of that member is
the same as the template name, that member is assumed to be referred to in
a template instantiation:
template Foo(T)
{
T Foo; // declare variable Foo of type T
}

void test()
{
Foo!(int) = 6; // instead of Foo!(int).Foo
}



If a template declares exactly one member, and that member is a class with
the same name as the template:
template Bar(T)
{
class Bar
{
T member;
}
}

then the semantic equivalent, called a ClassTemplateDeclaration can be
written as:
class Bar(T)
{
T member;
}



Also note that structs have the same description.

So if you think about it, your code is equivalent to:

template CheckedInt(N) if(isIntegral!N)
{
struct CheckedInt
{
...
}
}

If you look at it this way, it makes complete sense that within the struct
that's within the template, the struct can refer to itself without the specific
instantiation parameters.

I think this should really be laid out properly in the docs. I discovered this
trick while writing dcollections by accident and thought it so awesome that I
changed all my code which self-returned (quite a bit).

-Steve


I don't share your enthusiasm, Steven, for this feature (which I did not know). 
In fact, I tend to consider it a mis-feature. Yet another syntactic 
special-case for special cases in the language. In this case, there are even 3 
ways to write the same thing:

CheckedInt
CheckedInt!N
CheckedInt!(N)
And note these variants are low-level ones, morphological rather than syntactic 
properly speaking.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Empty field doesn't exist for arrays, right?

2011-03-08 Thread spir

On 03/08/2011 06:56 PM, Andrej Mitrovic wrote:

module test;

struct MyArray(T)
{
 private T[] data;

 bool opCast(T)() if (is(T == bool))
 {
 return !data.empty;
 }
}

void main()
{
 auto foo = MyArray!(int)();
 auto state = foo ? true : false;
}

test.d(13): Error: undefined identifier module test.empty
test.d(20): Error: template instance test.MyArray!(int).MyArray.opCast!(bool) 
error instantiating

This is straight from the book. Did .empty exist for arrays before? Perhaps 
this was just a typo in the book, and it was supposed to be:

 bool opCast(T)() if (is(T == bool))
 {
 return data.length != 0;
 }

Also, that error message *really* needs to improve. It's not module 'test' 
which is missing the method, it's 'data'. This is one of the most confusing 
error messages that I know of and it pops up all the time.


Agreed. But do you understand why dmd throws that error, anyway? I'm not sure, 
the following may be plain shit. My guess is, since UFCS (universal function 
call syntax) exists for arrays, when dmd decodes data.empty and does not find 
any empty slot on 'data' or on its type, it tries rewriting it into 
empty(data). Right? then, to execute that, it looks for an empty func in 
the module, which it does not find... thus the message.
Note that if one of your imports happened to hold an empty func, either it 
would execute by plain chance, or you would get a type error!

HTH

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Static Associative Array

2011-03-06 Thread spir

On 03/07/2011 03:22 AM, Peter Lundgren wrote:

== Quote from Jonathan M Davis (jmdavisp...@gmx.com)'s article

On Sunday 06 March 2011 14:05:04 Peter Lundgren wrote:

Can you define an associative array in a way that can be evaluated at
compile time like you can with non-associative arrays?

I'm pretty sure not. I think that it's currently suffering the same fate as 
stuff
like classes and is not yet able to be CTFEed. Some day...
- Jonathan M Davis


If not, then what is the D way to initialize a static field of a struct or 
class a
la Java's static initializer blocks? I don't mind constructing the associative
array at run-time if I have to, but I can't afford to do it more than the once 
needed.


Use the module's static this () {...} clause:

int[string] aa;
static this () { aa = [a:1, b:2, c:3]; }

unittest {
foreach (k,v ; aa)
writefln(%s -- %s, k,v);
}

Note: you can have as many such ckauses as you like.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Template type parameters with their own type parameters

2011-03-05 Thread spir

On 03/05/2011 04:02 AM, Peter Lundgren wrote:

I have a function that I think should look something like this:

MyStruct!T myFunc(T)(MyStruct!T x, ...) {
...
return MyStruct!T(...);
}

and the closest I can get to is:

T myFunc(T)(T x, ...) {
...
return T(...);
}

which works, but doesn't make clear the intended use and gets in the way of
overloading. How can I express the intent of the first version.


Maybe I do not exactly understand your problem; anyway, the following runs fine 
by me:


struct S (T) {
T v;
}

S!T inc (T) (S!T s) {
return S!T(s.v + 1);
}

unittest {
auto s1 = S!int(1);
auto s2 = inc(s1);
assert ( s2.v == 2 );
}

Could you provide (1) context (2) example (3) errors?

Denis
--
_
vita es estrany
spir.wikidot.com



Re: in/out with -release

2011-03-05 Thread spir

On 03/05/2011 01:58 PM, bearophile wrote:

Jonathan M Davis:


Asserts are for
debugging, testing, and verifying code when developing, not for code which is
released.


If you take a look at the dmd compiler, it's released with asserts in, and they 
give all those nice error messages I put in Bugzilla :-)


lol!
I have a similar problem in designing the implementation of a toy language: the 
issue is that users of the runtime are, for instance, lib developpers, which 
own users are developpers in the source language beeing implemented, for their 
own final users...
This makes it rather abstract to think at what is, or should be, the 
realisation of an error spit by the runtime. It cannot be a normal error from 
the implementation language, and also not an error of the source language. I 
had to write my own // error system.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Overriding in operator

2011-03-04 Thread spir

On 03/04/2011 05:01 PM, Magnus Lie Hetland wrote:

I'm writing a collection with functionality for membership checking. I thought
it would be nice to use the in operator. In the docs for std.collections I
surmise that this is the standard way to go. From the source code, I see
there's no special opIn, but that it can be done with the more general...

bool opBinary(string op)(T k) if (op == in) {
...
}

Here T is, of course, a compile-time argument of the surrounding struct or 
class.

So ... this is used in the the Phobos source in the DMD 2.052 distro (if I'm
not mistaken), but I can't get dmd 2.052 to accept it? I keep getting the error
message Error: rvalue of in expression must be an associative array, not
Foo!(uint).

I guess either that this is a recent feature -- I didn't see it mentioned in
Andrei's book -- and that my Phobos source is too recent for my dmd ... or that
I'm doing something wrong elsewhere in my code, preventing the operator
overloading to take force. Suggestions/solutions?-)


Didn't even know 'in' can be defined with opBinary...
I use opIn_r ('r' for right side, since the container stand on the right of the 
expression) everywhere, and it works fine.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Overriding iteration

2011-03-04 Thread spir

On 03/04/2011 05:43 PM, Steven Schveighoffer wrote:

On Fri, 04 Mar 2011 11:29:08 -0500, Magnus Lie Hetland mag...@hetland.org 
wrote:


From what I understand, when you override iteration, you can either implement
the basic range primitives, permitting foreach to destructively iterate over
your object, or you can implement a custom method that's called, and that
must perform the iteration. The destructiveness of the first option can, of
course, be mitigated if you use a struct rather than a class, and make sure
that anything that would be destroyed by popFront() is copied.

What I'm wondering is whether there is a way to do what Python does -- to
construct/return an iterator (or, in this case, a range) that is used during
the iteration, rather than the object itself?


That's exactly how to do it.



I'm thinking about when you iterate directly over the object here. As far as
I can see, the solution used in the std.container is to use opSlice() for
this functionality. In other words, in order to iterate over container foo,
you need to use foreach(e; foo[])? Is there no way to get this functionality
directly (i.e., for foreach(e; foo))?


I believe someone has filed a bug for this, because TDPL has said this should
be possible.

But with the current compiler, you can use opApply to achieve that behavior.


opApply should work but it is supposed to be slower.
Defining range primitives directly on the object/container cannot work as of 
now, unfortunately, because of a pair of bugs (conflicts in formatValue 
template definitions between struct/class on one hand and ranges on the other).


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Overriding iteration

2011-03-04 Thread spir

On 03/04/2011 07:06 PM, Jonathan M Davis wrote:

On Friday, March 04, 2011 09:13:34 spir wrote:

On 03/04/2011 05:43 PM, Steven Schveighoffer wrote:

On Fri, 04 Mar 2011 11:29:08 -0500, Magnus Lie Hetlandmag...@hetland.org

wrote:

 From what I understand, when you override iteration, you can either
implement the basic range primitives, permitting foreach to
destructively iterate over your object, or you can implement a custom
method that's called, and that must perform the iteration. The
destructiveness of the first option can, of course, be mitigated if you
use a struct rather than a class, and make sure that anything that
would be destroyed by popFront() is copied.

What I'm wondering is whether there is a way to do what Python does --
to construct/return an iterator (or, in this case, a range) that is
used during the iteration, rather than the object itself?


That's exactly how to do it.


I'm thinking about when you iterate directly over the object here. As
far as I can see, the solution used in the std.container is to use
opSlice() for this functionality. In other words, in order to iterate
over container foo, you need to use foreach(e; foo[])? Is there no way
to get this functionality directly (i.e., for foreach(e; foo))?


I believe someone has filed a bug for this, because TDPL has said this
should be possible.

But with the current compiler, you can use opApply to achieve that
behavior.


opApply should work but it is supposed to be slower.
Defining range primitives directly on the object/container cannot work as
of now, unfortunately, because of a pair of bugs (conflicts in formatValue
template definitions between struct/class on one hand and ranges on the
other).


You don't _want_ range primitives directly on the container. That would mean
that everything in your container goes away when you process it. Every
popFront() call would be removing an element from your container. So, for
insteance, you try and call find() on your container and everything before what
you were looking isn't in the container anymore - and if it isn't there at all,
you have an empty container. You _want_ to have a separate type which is a slice
of our container and has the range primitives.


Certainly, as long as, on an array-like container, you implement popFront as
this = this[1..$];
or
this.elements = this.elements[1..$];
then, yes, iterating on it shrinks it. (Note this works only on array-like 
containers; how would you shrink a tree?) But I prefere using a private index 
an have popFront do:

++ this.index;

This is a more general iteration mechanism solution, based on current state of 
the object beeing iterated on. For many kinds of sequences, you needs state 
anyway. How else iterate over the sequence of multiples of 3, or squares of 
natural numbers?



Now, it could very well be that

foreach(v; container)

should be calling opSlice on the container, allowing you to feed the container
to foreach directly instead of having to slice it yourself

foreach(v; container[])

but that's just syntactic sugar. You don't want to actually treat your container
like a range. Ranges should be slices of containers, not containers themselves.


I agree slices should be an alternate iteration mechanism (as said in TDPL). 
But one cannot slice a tree that easily :-) (where's my chain saw?)


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Parameterized Structs

2011-03-03 Thread spir

On 03/03/2011 12:25 PM, bearophile wrote:

Ali Çehreli:


quote
Template value parameter types can be any type which can be statically
initialized at compile time, and the value argument can be any
expression which can be evaluated at compile time. This includes
integers, floating point types, and strings.
/quote


I have needed arrays as template specialization arguments few times (I have 
used alias to solve the problem). Allowing strings but not arrays is one 
limitation that I don't understand.

Bye,
bearophile


That may be because strings are immutable?

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Parameterized Structs

2011-03-03 Thread spir

On 03/03/2011 05:56 AM, Peter Lundgren wrote:

Where can I go to learn about parameterized structs? I can't seem to find any
literature on the subject. In particular, what are you allowed to use as a
parameter? I would like to define a struct like so:

struct MyStruct(T, T[] a) {
 ...
}

but I receive the following error:

Error: arithmetic/string type expected for value-parameter, not T[]

Are arrays not allowed?


Finally managed to do it, I guess :-)


bool[E] set (E : E[]) (E[] elements) {
bool[E] set;
foreach (element ; elements)
set[element] = true;
return set;
}

struct String (C : C[], alias characters) {
alias typeof(characters) S;
//~ alias ElementType!S C;  // BUG! returns dchar
bool[C] klass = null;
private C[] s;

this (S s) {
this.klass = set!S(characters);
this.def(s);
}
void def (S s = null) {
if (s.length == 0) {
this.s = s;
return;
}
foreach (ch ; s) {
if (ch !in this.klass) {
auto message = format(
'%s' not in allowed class of characters
, ch);
throw new Exception(message);
}
}
this.s = s;
}

string toString () {
return format(String!(%s,\%s\)(\%s\),
S.stringof, characters, this.s);
}
}

unittest {
auto s = String!(string, abcde)();
writeln(s);
s.def(eca);
writeln(s);
s = String!(string, abcde)(ace);
writeln(s);
s = String!(string, abcde)(fgh);// -- error
writeln(s);
}


Some notes:

* set is here to speed up character lookup among allowed klass (else, O(N) in 
array).


* C: C[] in struct template is redondant, since C[] is typeof(characters). It 
is only needed to declare the set 'klass', because of a bug: ElementType!string 
returns dchar!!! Thus, it is would not be possible, I guess, to declare klass's 
type in the struct definition.


* You must pass an init string (even if ) to call this() and construct klass. 
Because of another bug: there cannot be parameter-less constructors for 
structs. Also, set cannot be defined on toplevel of the struct def

auto klass = set!S(characters);
because it's not a constant according to dmd. (It is, in fact). Thus, I guess 
we must construct it inside this().


Denis
--
_
vita es estrany
spir.wikidot.com



Re: comparing pointers passed to and returned from funcs

2011-03-02 Thread spir

On 03/02/2011 02:24 PM, Steven Schveighoffer wrote:

On Tue, 01 Mar 2011 18:11:00 -0500, bearophile bearophileh...@lycos.com wrote:


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


I think there is a general bug where any time the compiler uses an enum, it
simply replaces the expression declared for the enum.

So basically

enum TRUE = new DElement(true);

void main()
{
auto delem1 = TRUE;
auto delem2 = TRUE;
assert(delem1 is delem2); // fails
}

gets morphed into this:

void main()
{
auto delem1 = new Delement(true);
auto delem2 = new Delement(true);
assert(delem1 is delem2); // fails
}

Obviously this works great when the enum is a value type or a string literal
(which is created at compile time). However, it is not so great for things like
AAs, array literals, objects, or structs.

I think there are a few of these bugs in bugzilla, and there should be at least
a tracker, and if not, they should all be combined. This is a serious problem
in D, and really creates havoc (both performance-wise and semantically). I
don't anticipate there is an easy fix.

Essentially, I'd say enum is completely useless except for builtin types and
strings.


Thank you Steven  Bearophile. This solves my problem.
I first did not get Bearophile's answer about run/compile-time constants (I 
mean enums). I thought the time when they are created is irrelevant, isn't it?
Anyway, placing the constant defs inside a module's static this () {...} 
block does what I mean. It does, in fact, ensure *unicity*. But I don't really 
understand the relation with Steven's explanation above: why/how does the fact 
that a constant's def is inside static this() prevent the compiler to rewrite 
it like shown above? Also, I basically don't understand why dmd does that 
anyway: it's obviously un-ecological ;-)


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Mixins: to!string cannot be interpreted at compile time

2011-03-01 Thread spir

On 03/01/2011 07:58 AM, Peter Lundgren wrote:

I'm trying to use mixins to generate an array of numbers that are coprime to a
statically known value. I've tried the following, but I receive the error:

Error: to(i) ~ ,  cannot be interpreted at compile time


string makePossibleAValues(string name, byte m) {
string result = immutable byte[] ~name~ = [;
foreach (i; 0 .. m) {
if (coprime(i, m)) {
result ~= to!string(i) ~ , ;
}
}
return result ~ ];;
}

bool coprime(ulong a, ulong b) {
return gcd(a, b) == 1;
}

ulong gcd(ulong a, ulong b) {
while (b) {
auto t = b;
b = a % b;
a = t;
}
return a;
}

mixin(makePossibleAValues(aValues, 26));


makePossibleAValues(aValues, 26) produces the correct result, immutable
byte[] aValues = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25, ];, at runtime
and I know to!string can be used in mixins. Any idea as to why this particular
code is having trouble with to!string?


Not sure because I never use string mixins, but I guess the answer is precisely 
what the error says. Why don't you believe it?
makePossibleAValues() obviously returns a runtime value, so mixin() cannot 
evaluate it, I guess.


Denis
--
_
vita es estrany
spir.wikidot.com



comparing pointers passed to and returned from funcs

2011-03-01 Thread spir

Hello,

It seems to be the kind of stupid issue that will make you laugh about me. But 
I cannot grasp and want to move forward anyway; so, let us be bold and take the 
risk ;-)


I'm modeling a little dynamic language. Elements (values, objects) are pointers 
to structs (actually tagged unions) allocated on the heap. I have a problem in 
passing and returning those pointers to and from primitive procedures.


Precisely, unlike in D, Logical (boolean) operations only accept Logical 
elements true/false (called TRUE/FALSE on implementation side for obvious reason):

enum TRUE = new DElement(true);
enum FALSE = new DElement(false);

 So, I thought I could write those operations by comparing pointers directly, 
eg:
Element not (Element operand) {
// checks type
operand.checkLogical()
return (operand == TRUE) ? FALSE : TRUE;
}
...
assert ( not(TRUE) == FALSE );

This fails! It even fails doubly...
When I call not(TRUE), TRUE (the pointer) inside the func is not equal to the 
global constant. Thus, not always returns FALSE. And in fact this is also 
wrong, because I have the same problem on the return value as well: the FALSE 
returned is not equal to the global FALSE.


But the pointed structs are ok. Each one holds a D boolean of the correct value 
(a member called 'logical'). Thus, the following succeeds:


Element not (Element operand) {
// checks type  returns the 'logical' member
auto log = operand.checkLogical();
return (log) ? FALSE : TRUE;
}
...
assert ( not(TRUE).logical == false );

Here, I operate on the structs instead of on the pointers, both to perform the 
operation and in the assert. What I understand is: all happens like if D would 
copy the pointed structs on parameter passing and on return. I thought D would 
only copy the pointers (in both directions), which would let me compare said 
pointers directly.

What do I miss?

It is not a serious problem since the workaround is easy and not very costly. 
But I wish to understand why I cannot operate on constant 'identity'. As said 
above, this must a trivial issue I simply cannot guess...


Thank you,
Denis
--
_
vita es estrany
spir.wikidot.com



type set

2011-02-28 Thread spir

Hello,

I have a template condition that looks like this:

T check (T) () if (
is(T == DLogical) ||
is(T == DNumber) ||
is(T == DText) ||
is(T == DList) ||
is(T == DUnit)
) {
...
}

Is there a way to factor out such an expression using a kind of type set? If 
only for cleaning the code; but also because such a set may get long.


T check (T) () if (is (T in validTypeSet)) {
...
}

Denis
--
_
vita es estrany
spir.wikidot.com



Re: type set

2011-02-28 Thread spir

On 02/28/2011 02:32 PM, Steven Schveighoffer wrote:

On Mon, 28 Feb 2011 08:22:58 -0500, spir denis.s...@gmail.com wrote:


Hello,

I have a template condition that looks like this:

T check (T) () if (
is(T == DLogical) ||
is(T == DNumber) ||
is(T == DText) ||
is(T == DList) ||
is(T == DUnit)
) {
...
}

Is there a way to factor out such an expression using a kind of type set?
If only for cleaning the code; but also because such a set may get long.

T check (T) () if (is (T in validTypeSet)) {
...
}


This should probably work:

template isOneOf(X, T...)
{
static if(!T.length)
enum bool isOneOf = false;
else static if(is(X == T[0]))
enum bool isOneOf = true;
else
enum bool isOneOf = isOneOf!(X, T[1..$]);
}

T check(T) () if(isOneOf!(T, DLogical, DNumber, DText, TList, DUnit))
{
...
}

Not sure if this exists in std.traits or not, but that's where I'd look.

-Steve


Waow, great anyway! Didn't even know one can write variadic type/template param 
lists.


By the way, the block of the function is a series of static if-s, one for each 
allowed type. Is there any static switch? Or any other nicer way to write it than:


T check (T) () if (
is(T == DLogical) ||
is(T == DNumber) ||
is(T == DText) ||
is(T == DList) ||
is(T == DUnit)
) {
TypeCode type;

static if (is(T == DLogical))
if (this.code == LOGICAL)
return this.logical;
else
type == LOGICAL;
static if (is(T == DNumber))
if (this.code == NUMBER)
return this.number;
else
type == NUMBER;
static if (is(T == DText))
if (this.code == TEXT)
return this.text;
else
type == TEXT;
static if (is(T == DList))
if (this.code == LOGICAL)
return this.list;
else
type == LOGICAL;
static if (is(T == DUnit))
if (this.code == UNIT)
return this.unit;
else
type == UNIT;

// type error
throw new TypeError(type, this);
}

This func type-checks and returns the current value of a tagged union. I would 
be very pleased with a mapping from types to type codes (tags). I can't do 
without the type param, I guess, because it's the return value's type... or can 
I? But the discriminating code of the union cannot be the type itself (*), 
instead it's a plain code.
I thought at using TypeInfo-s as codes, which can then be mapped from types 
using typeid(). But according to sizeof, this makes the code weigh 1 word 
instead of one byte.


Denis

(*) Indeed. Else it would be a template generating N distinct types, which is 
precisely the opposite of what a union provides.

--
_
vita es estrany
spir.wikidot.com



Re: type set

2011-02-28 Thread spir

On 02/28/2011 03:50 PM, Steven Schveighoffer wrote:

On Mon, 28 Feb 2011 09:27:36 -0500, spir denis.s...@gmail.com wrote:


By the way, the block of the function is a series of static if-s, one for
each allowed type. Is there any static switch? Or any other nicer way to
write it than:

T check (T) () if (
is(T == DLogical) ||
is(T == DNumber) ||
is(T == DText) ||
is(T == DList) ||
is(T == DUnit)
) {
TypeCode type;

static if (is(T == DLogical))
if (this.code == LOGICAL)
return this.logical;
else
type == LOGICAL;
static if (is(T == DNumber))
if (this.code == NUMBER)
return this.number;
else
type == NUMBER;
static if (is(T == DText))
if (this.code == TEXT)
return this.text;
else
type == TEXT;
static if (is(T == DList))
if (this.code == LOGICAL)
return this.list;
else
type == LOGICAL;
static if (is(T == DUnit))
if (this.code == UNIT)
return this.unit;
else
type == UNIT;

// type error
throw new TypeError(type, this);
}


There is a final switch, but I don't know if that works on types. You may be
stuck with static if.

When doing things like this, I'd recommend using a mapping template. For 
example:

private template typeCode(T)
{
static if(is(T == DLogical)) enum typeCode = LOGICAL;
else static if(is(T == DNumber)) enum typeCode = NUMBER;
...
else static assert(0);
}

then you almost can use this to generate the right code:

if(this.code == typeCode!T)
{
static if(is(T == DUnit)) return this.unit;
else static if(...
}


That's it! This actually builds an the equivalent of an AA which keys are 
types. I was looking for such a functionality for a while already.
I am in fact *contantly* annoyed in D by the fact there are no types (I mean at 
runtime). On the other hand, this forces me looking for workaround, to express 
my models in distorted ways, which lets me discover unusual features and 
idioms in D's semantic dark corners ;-)



You can probably replace the inner static if with a mixin, if you name your
union members properly (i.e. if you can generate the name of the union member
based on its type name or code, like DUnit dunit_val).


Yeah, I could, as shown by the code above: lang type Xyz -- code XYZ -- D 
impl type DXyz -- union member xyz.

Could not be more regular, I guess ;-)
But as you may know, I 100% against string mixins. I prefere keeping the 
mapping explicite without string sorcery.
(Precisely, in the toy lang I'm starting to realise, one could do that 
trivially by manipulating the AST, without any dark magic. But this is another 
story...)



But at least it gives you an idea of how this can be done efficiently.

Plus avoiding large repetitive static ifs can save you from tedious
copy-pasting bugs like the one in your DList branch ;)


Good catch, Steve! And thank you again.

PS: Is it your email client that eats whitespace (see my code above)?

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Multiple assignment

2011-02-26 Thread spir

On 02/26/2011 01:56 AM, bearophile wrote:

Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
 int i;
 int[2] x;
 i, x[i] = 1;
 assert(x == [1, 0]); // OK

 int j;
 int[2] y;
 y[j], j = 1;
 assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].


I'm far to be a C expert, but that looks like very normal C semantics, ain't 
it? with all its stupidity, indeed...

I would enjoy an error in both cases. (not enough rvalues)

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Multiple assignment

2011-02-26 Thread spir

On 02/26/2011 04:26 AM, Steven Schveighoffer wrote:

Let me fix that for you:

func(j++, y[j])


That should be illegal: a statement used as expression, but keeping it's effect 
anyway, and not the least kind of, namely an assignment, meaning a change of 
the program state.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: How do you test pre-/post-conditions and invariants?

2011-02-26 Thread spir

On 02/26/2011 12:24 PM, Magnus Lie Hetland wrote:

However, I could always add a call to my unit test, run it, and see it crash --
and then comment it out. Doesn't seem like the prettiest way to handle things,
but it's OK, I guess together with the idea of making the contracts
super-simple (and to test any functionality they use separately).


With named unittests, you could also have one of them check failure cases, and 
just comment out its call.


Denis
--
_
vita es estrany
spir.wikidot.com



override to!string

2011-02-25 Thread spir

Hello,

Imagine I have the following custom type:
alias float[] Numbers;

Is it possible to override to!string for Numbers so that it outputs eg like;
(1.1 2.2 3.3)
?

I can indeed override/specialise toImpl or formatValue for the custom type, but 
those overrides are simply ignored (tested).


Denis
--
_
vita es estrany
spir.wikidot.com



implicite deref on array element access? (indexing)

2011-02-25 Thread spir

Hello,

I thought it worked, just like implicite deref on (struct, class) member 
access. But I cannot have it work:


auto a = [1,2,3];
auto pa = a;
writeln((*pa)[2]);  // ok
writeln(pa[2]); // segfault

Denis
--
_
vita es estrany
spir.wikidot.com



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread spir

On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in my
preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is what
assert() throws -- so what's the standard way of writing unit tests for
preconditions that use assert? (I.e., test that they will, in fact, throw when
you break them.)


See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: implicite deref on array element access? (indexing)

2011-02-25 Thread spir

On 02/25/2011 04:43 PM, Steven Schveighoffer wrote:

On Fri, 25 Feb 2011 10:15:52 -0500, spir denis.s...@gmail.com wrote:


Hello,

I thought it worked, just like implicite deref on (struct, class) member
access. But I cannot have it work:

auto a = [1,2,3];
auto pa = a;
writeln((*pa)[2]); // ok
writeln(pa[2]); // segfault


Because indexing a pointer like ptr[n] is the equivalent of *(ptr + n).

This is how it is in C.

Fun fact, you can avoid array bounds checks (if you know the index is valid) by
doing arr.ptr[n]


All right! This is what I did not get. Thank you, Steve.
Too bad. Anyway, in the meanwhile I have opted for another approach. (FWIW, in 
Oberon implicite deref works on array indexing just like on struct [record] 
member access.)


Denis
--
_
vita es estrany
spir.wikidot.com



  1   2   3   4   >