Re: if Condition expression can't have function?

2014-04-25 Thread Matthias Walter via Digitalmars-d
On 04/25/2014 09:14 AM, FrankLike via Digitalmars-d wrote:
 Hi,everyone,
 Here has a error after run:  main.exe 11  or  main.exe 10 :
 template find(T)
 {
 size_t find(T[] Array,T Element)
 {

find returns a size_t being a nonnegativ number.

 return -1;

But here it returns -1.

In your main code you check find() = 0, so maybe the compiler
simplifies it in some situations because a size_t value is always = 0.

Matthias


Re: Testing presence of member functions with same name but different signature.

2014-02-08 Thread Matthias Walter
On 02/06/2014 10:44 PM, Timon Gehr wrote:
 On 02/06/2014 10:32 PM, Matthias Walter wrote:
 Is this a bug?
 
 Yes.

Okay, added a ticket: http://d.puremagic.com/issues/show_bug.cgi?id=12102



Testing presence of member functions with same name but different signature.

2014-02-06 Thread Matthias Walter
Hi,

I realized the following behavior and want to ask whether this is
expected behavior and if yes, I'd like to know a reason.

The check of MyClass.func(MyClass.A) and MyClass.func(MyClass.B) in the
main() function succeeds, but the alias line *in* the class definition
fails with template instance main.ConditionalUse!(MyClass) does not
match template declaration ConditionalUse(T) if (hasFuncs!T).

If I rename func to funcA and funcB (making the name unambiguous), both
checks succeed.

Is this a bug?

template hasFuncs(T) // Checks presence of T.func(T.A) and T.func(T.B)
{
  enum bool hasFuncs =
  is(typeof((T t, T.A a){ t.func(a); }))

  is(typeof((T t, T.B b){ t.func(b); }));
}

struct ConditionalUse(T) if (hasFuncs!T) { }

// This line fails with
//
// template instance main.ConditionalUse!(MyClass) does not
// match template declaration ConditionalUse(T) if (hasFuncs!T)

class MyClass
{
  struct A {}
  struct B {}

  alias ConditionalUse!MyClass Foo;

  void func(A a) { }
  void func(B b) { }
}

int main(char[][] args)
{
  static assert(hasFuncs!MyClass); // This assert is fine.
  return 0;
}

Best regards,

Matthias


inout type constructor applied to this-reference

2014-01-10 Thread Matthias Walter
Hi,

I read about inout functions in the language documentation which allows
to use inout in order to set the constness of the return type based on
the constness of some argument. What is not mentioned is that this also
works for the this-reference by marking the function itself inout:

So instead of

class C
{
  OtherClass foo;

  const(OtherClass) getOther() const { return foo; }
  OtherClass getOther() { return foo; }
}

we can write

class C
{
  OtherClass foo;

  inout(OtherClass) getOther() inout { return foo; }
}

Since the documentation only talks about marking arguments inout, can I
nevertheless rely on its behavior? Anyways, I think it is worth to be
included in the docs.

Best regards,

Matthias


Member-assignment for std.container.Array!Struct

2014-01-09 Thread Matthias Walter
Hi,

about 2 years ago I stopped using D for my projects since there were too
many bugs that hindered me from making quick progress. Since I got
several mails from bugzilla about those bugs being fixed I wanted to
give it another try. Unfortunately, the following non-working code made
me think to stop using it once again:

struct S
{
  int i;
}
Array!S array = [ S(0) ];
array[0].i = 1;

The reason is certainly that the change only affects a copy and not the
true array-member. I remember that there was a discussion about sealed
containers and returning references, etc.

My question is now: Has there been any progress in this direction? I
know that the design of ref's semantics is a nontrivial topic, but on
the other hand in my opinion std.container.Array is completely useless
if not even the above code works as one would expect!

Best regards,

Matthias


Re: Initialization of std.typecons.RefCounted objects

2012-07-19 Thread Matthias Walter
On 07/18/2012 03:32 PM, Christophe Travert wrote:
 Matthias Walter , dans le message (digitalmars.D:172673), a écrit :
 I looked at Bug #6153 (Array!(Array!int) failure) and found that the

 This exactly is what makes the following code fail:

 Array!(Array!int) array2d;
 array2d.length = 1;
 array2d[0].insert(1);

 The inner array array2d[0] was not initialized and hence the reference
 pointer is null. Since Array.opIndex returns by value, the 'insert'
 method is called on a temporary object and does not affect the inner
 array (still being empty) which is stored in the outer array.

 What do you think about this?

 Must the user ensure that the Array container is always initialized
 explicitly? If yes, how shall this happen since the only constructor
 takes a (non-empty) tuple of new elements. Or shall opIndex return by
 reference?
 
 I think opIndex should return by reference. opIndexAssign is of no help 
 when the user want to use a function that takes a reference (here 
 Array.insert). It is normal that Array uses default construction when 
 someone increases the array's length.

Okay, I fully agree here.

 Besides that point, I don't see why default-constructed Array have an 
 uninitialised Payload. This makes uninitialised Array behaves 
 unexpectedly, because making a copy and using the copy will not affect 
 the original, which is not the intended reference value behavior.

Well the reason is that no user-defined function is called when a struct
is default-constructed and then copied into another variable (the first
one is this(this) which only known the new variable). Hence no user code
can be written that would initialize the payload. Do we need a paradigm
to perform explicit initialization of structs?

Best regards,

Matthias


Re: Initialization of std.typecons.RefCounted objects

2012-07-19 Thread Matthias Walter
On 07/19/2012 10:14 AM, Christophe Travert wrote:
 monarch_dodra , dans le message (digitalmars.D:172700), a écrit :
 I think it would be better to initialize on copy, rather than 
 default initialize. There are too many cases an empty array is 
 created, then initialized on the next line, or passed to 
 something else that does the initialization proper.
 
 Not default-initializing Array has a cost for every legitimate use of an 
 Array. I think people use Array more often than they create 
 uninitialized ones that are not going to be used before an other Array 
 instance is assigned to them, so Array would be more efficient if it was 
 default initialized and never check it is initialized again. But that's 
 just speculation.

I agree here. Additionally my question: Is it possible (at the moment)
to really do initialize on copy? As far as I see it, the only way to
interact here is to implement 'this(this)' which is called after
bit-copying and hence cannot access the source of the copy process.





Re: Initialization of std.typecons.RefCounted objects

2012-07-19 Thread Matthias Walter
On 07/19/2012 02:16 PM, Christophe Travert wrote:
 monarch_dodra , dans le message (digitalmars.D:172710), a écrit :
 One of the reason the implementation doesn't let you escape a 
 reference is that that reference may become (_unverifiably_) 
 invalid.
 
 The same applies to a dynamic array: it is undistinguishable from a 
 sliced static array. More generally, as long as you allow variables on 
 the stack with no escaped reference tracking, you can't ensure 
 references remain valid. Even in safe code.
 
 If I want my references to remain valid, I use dynamic array and garbage 
 collection. If I use Array, I accept that my references may die. Array 
 that protects the validity of their references are awesome. But, IMHO, 
 not at that cost.
 
 ...That said, I see no reason for the other containers (SList, 
 I'm looking at you), not to expose references.
 
 I'm against not exposing reference, but all containers will be 
 implemented with custom allocator someday.
 
 The current work around? Copy-Extract, manipulate, re-insert. 
 Sucks.
 
 IMO, what sucks even more is that arr[0].insert(foo) compiles while it 
 has no effect. arr[0] is a R-value, but applying method to R-value is 
 allowed. I don't know the state of debates about forbiding to call 
 non-const methods on R-values. I think this would break too much code.

As it seems the issue really should be resolved by making opIndex return
by reference and press thumbs hard that something like a 'scope ref'
will be implemented?

Furthermore, since RefCounted objects do not behave like reference types
until initialized, they *must* be initialized before anything else
happens and hence I propose to change std.container.Array like
Christophe said: Replace 'isInitialized()' checks by assertions and add
a method with which the user explicitly initialized the reference counter.

Or is there a reasonable alternative?

Best regards,

Matthias Walter


Re: Getting a range over a const Container

2012-07-19 Thread Matthias Walter
On 07/19/2012 06:44 AM, Jonathan M Davis wrote:
 On Thursday, July 19, 2012 04:39:26 Francisco Soulignac wrote:
 So, my question is how can I (correctly) traverse a const SList,
 const DList, etc?
 
 Right now? I'm pretty sure that that's impossible. Hopefully that will 
 change, 
 but getting const and ranges to work together can be rather difficult, and 
 std.container needs more work in that regard.

Well it doesn't work yet. But in principle it could since we can always
copy a const pointer to a non-const one to const data:

Node* actual; // but 'this' is const and hence the type is const(Node*)

const(Node)* i_will_traverse = actual;

Best regards,

Matthias


Re: ~= call copy ctor?

2012-07-19 Thread Matthias Walter
On 07/19/2012 02:27 PM, Namespace wrote:
 I have a 2 questions.
 
 I have this code:
 
 [code]
 import std.stdio;
 
 struct Test {
 public:
 this(int i = 0) {
 writeln(Test CTor.);
 }
 
 this(this) {
 writeln(Test Copy CTor);
 }
 
 ~this() {
 writeln(Test DTor);
 }
 }
 
 Test[] _arr;
 
 void copy_save(Test t) {
 _arr ~= t;
 }
 
 void by_ref_save(ref Test t) {
 _arr ~= t;
 }
 
 [/code]
 
 Why get i with
 
 [code]
 void main() {
 Test t = 42;
 
 by_ref_save(t);
 }
 [/code]
 
 this output:
 
 Test CTor.
 Test Copy CTor
 Test DTor

As you mentioned in the subject the copy constructor is not called while
the struct is passed by reference but on array concatenation.
But this must occur since the array has its memory region and the
original variable t in main() also has. Since they are different, at
some point the struct must be copied from t in main() into the array.
The ref only ensures that it is passed via reference (a pointer to the
memory of t in main()) to the function by_ref_save().

 And the same if i have this:
 
 [code]
 void main() {
 Test t = 42;
 
 copy_save(t);
 }
 [/code]
 
 t is already a clone. Why it is copied again?

Here it is once copied from t in main() into the local variable t in
copy_save() and then copied (as in your 1st example) into the array.
Imagine the copy_save routine is in a different module and only its
signature is exposed to main. When calling the function, the compiler
does not know what happens inside copy_save but it must put the variable
onto the stack at the position of the first parameter (well, in this
case it is probably put into a CPU register, but that doesn't matter here).

Then, when copy_save is invoked it only knows the local variable which
it then copies into the array memory (after enlarging the array).

It *may* be the when you enable compiler optimizations (-O -inline) that
copy_save gets inlined and hence the compiler can optimize one of the
copy calls away. But that I don't know for sure.

Best regards,

Matthias


Re: ~= call copy ctor?

2012-07-19 Thread Matthias Walter
On 07/19/2012 03:00 PM, Namespace wrote:
 Is there any way to avoid the implizit copy ctor by array concatenation?
 Or is the only way to use a pointer?

Yes, in some way you have to. If you want to not copy a lot of data (or
avoid additional on-copy effort) you either have to you pointers
explicitly (Test*[]) or implicitly. The latter works e.g. by making Test
a class which means that the variable actually does store a pointer to
the instance.

Note that for struct pointers you should not escape them, i.e. have a
variable local in a function, puts its address into some array and
returning that array. Since the local variable is gone, the pointer is
invalid as well. (Nothing happens if you do not access it).

Best regards,

Matthias


Initialization of std.typecons.RefCounted objects

2012-07-18 Thread Matthias Walter
Hi,

I looked at Bug #6153 (Array!(Array!int) failure) and found that the
reason is the following behavior:

Given some type T you wrap as RefCounted!T object, then proper use of
the auto-initialization feature or manual initialization on demand
ensures that no null-pointer dereference will happen. But the other
problem is that as long as the wrapped object is uninitialized, the
object behaves like a value type instead of a reference type.

This exactly is what makes the following code fail:

Array!(Array!int) array2d;
array2d.length = 1;
array2d[0].insert(1);

The inner array array2d[0] was not initialized and hence the reference
pointer is null. Since Array.opIndex returns by value, the 'insert'
method is called on a temporary object and does not affect the inner
array (still being empty) which is stored in the outer array.

What do you think about this?

Must the user ensure that the Array container is always initialized
explicitly? If yes, how shall this happen since the only constructor
takes a (non-empty) tuple of new elements. Or shall opIndex return by
reference?

The problem arises in the same way if Array was a class - but then the
user typically knows that after enlarging the outer array, the inner
array is a null pointer which must be created by new.

Best regards,

Matthias Walter


Progress on std.container

2012-07-16 Thread Matthias Walter
Hi,

I'd like to know who is currently working on std.container - at some
point I read that Andrei works on user-controlled allocation and then
the issues of container structures will be addressed. Unforntunately, at
the moment std.container.Array is unusable for me because of missing
const Range (8248) and impossible arrays of arrays (6153).

Is there a way to see how far this development is? Can one contribute
somehow? I would offer to contribute but only on a basis where the
general design is fixed (e.g. there is a reference implementation for a
certain container) to add other missing containers.

Best regards,

Matthias


Re: Progress on std.container

2012-07-16 Thread Matthias Walter
On 07/17/2012 12:41 AM, Andrei Alexandrescu wrote:
 On 7/16/12 4:19 AM, Matthias Walter wrote:
 Hi,

 I'd like to know who is currently working on std.container - at some
 point I read that Andrei works on user-controlled allocation and then
 the issues of container structures will be addressed. Unforntunately, at
 the moment std.container.Array is unusable for me because of missing
 const Range (8248) and impossible arrays of arrays (6153).

 Is there a way to see how far this development is? Can one contribute
 somehow? I would offer to contribute but only on a basis where the
 general design is fixed (e.g. there is a reference implementation for a
 certain container) to add other missing containers.
 
 I'm the bottleneck for that. My list of actual work (aside from my
 duties as phobos/druntime/tools/dlang.org curator) is:
 
 1. Put std.benchmark through the review process
 
 2. Define allocators
 
 3. Integrate allocators with std.container
 
 If you have fixes for std.container that are faraway from allocation
 issues, I think it's safe to propose them as pull requests. I assume the
 advent of allocators will be a uniform additive changes for all containers.

That's good news - despite the fact the you have loads of work. I will
probably work on these things.

Thank you!


Re: foreach syntax

2012-06-29 Thread Matthias Walter
On 06/29/2012 12:47 PM, Namespace wrote:
 A friend of mine ask me why D's foreach isn't like C#
 
 Means, why is it like
 int[] arr = [1, 2, 3];
 
 foreach (int val; arr) {
 
 and not
 foreach (int val in arr) {
 
 which it is more intuitive.
 
 I could give him no clever answer to, so maybe someone here knows the
 reasons.
 

I suppose it is because the usual 'for' loop is a relative of 'foreach'.
And there we (and the C world) uses ';'.


Re: Primary Ranges of Containers

2012-06-20 Thread Matthias Walter
On 06/19/2012 04:04 PM, Timon Gehr wrote:
 On 06/19/2012 02:54 PM, Christophe Travert wrote:
 Jonathan M Davis , dans le message (digitalmars.D:170054), a écrit :
 I'd propose to always add a bool template parameter (maybe isConst?) to
 the range since most of the write-functionality can be removed by a
 static if statement in order to make the range read-only.

 Any suggestions?

 Boolean parameters are very obscure.
 How do you guess what is the meaning of false in:
 Range!false;

 Range!IsConst.no would be better.

 struct ArrayRange(bool isConst) {...}
 alias ArrayRange!false Range;
 alias ArrayRange!true ConstRange;

 Range and ConstRange seems a good thing to have, just like c++
 containers have iterator and const_iterator.

 
 Something along these lines seems to be a superior design:
 
 struct ArrayRange(T){ ... }
 
 class Array(T){
 ...
 ArrayRange!T opSlice(){ ... }
 ArrayRange!(const(T)) opSlice()const{ ... }
 ArrayRange!(immutable(T)) opSlice()immutable{ ... }
 ...
 }
 
 (Where the opSlice functions can be generated automatically.)

I like the design. I looked at the actual implementation of
std.container.Array and realized the following problem:

The payload is stored in a RefCounted object. The range returned by
opSlice() const must obviously somehow access the payload. By
documentation of RefCounted, no references to the payload should be
escaped outside the RefCounted object. which implies that we need to
create a copy of the RefCounted variable to have proper access.

On the other hand, given the constness of opSlice() we only have access
to a const version of the RefCounted variable which cannot be used to
create another reference since the reference counter is const as well.

So how can a ConstRange be implemented *somehow*?

Matthias


Re: Primary Ranges of Containers

2012-06-19 Thread Matthias Walter
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 06/18/2012 01:08 PM, Jonathan M Davis wrote:
 On Monday, June 18, 2012 10:06:44 Matthias Walter wrote:
 Hi,
 
 last week I realized that a const version of 
 std.container.Array.opSlice() is missing. Now I looked at the
 code and I think that it is a general design problem.
 
 The docs state that c.Range is The primary range type
 associated with the container.. I think we really always need
 two Range types (one for const view and one for non-const view)
 by design.
 
 I'd propose to always add a bool template parameter (maybe
 isConst?) to the range since most of the write-functionality can
 be removed by a static if statement in order to make the range
 read-only.
 
 Any suggestions?
 
 Yeah, it'll probably have to be templated. C++ already has to do
 something similar with iterators and const_iterators. But since you
 don't normally use the type of a range explicitly, it shouldn't be
 a big deal. The one downside that might pose a problem though is
 that if someone _does_ use the type explicitly, their code will
 break if the type gets templated. We could make a second type
 (ConstRange?) for the iterating over a const Array, but I'd be 
 tempted to just templatize the thing and let it break any code that
 it breaks. std.container is already likely to break stuff to at
 least some extent when the custom allocators get added anyway. I
 suppose that we could just rename the type and then create an alias
 for the current type
 
 struct ArrayRange(bool isConst) {...} alias ArrayRange!false
 Range; alias ArrayRange!true ConstRange;
 
 but that might be overkill. I don't know. Regardless, it _is_
 likely that the range type will have to be templatized to fix the
 problem. Ranges and range- based functions in general need to be
 cleaned up a bit to deal with const, since the way that they're
 designed doesn't work with const very well, and we need to make it
 work. I think that it _can_ work, but it takes more effort to do
 so.

I fully agree with all that. In order to migrate older code we may
make isConst have a default value of false.

Best regards,

Matthias

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJP4B8OAAoJEPdcuJbq5/sR7h0H/jeJ+KPUMoiP9SqiamE0qv4V
IantID2fzML8b55CWGQ2ZU7YbhQqOPIIEVtRriNAUIA4sHqWXQA03YgFrDk7XZZy
jrhx9VCUkiMeIuHhSdXQIwAWH+dkfnQoOS9EwbbiwZjBG+zU5iH/s9tduRzKadTr
Bb4QLAx7hEjlsvgRArj0O5z88YeGWbLhUzTz70utoE+1VgROuVF4WzJL9S803ZWX
ZZR1HOx0ktE60jvBTMoK2TzSfB5/JjiDQSWjK8ikEQGSw8QR3M3DWD3WkFucOAaL
3K6xH/yoDTBMOT+IVjkfVOsnv0iBB7ARpJKxOD2r+bJOoGWCQ1YQAoyY8rwrez0=
=yhaM
-END PGP SIGNATURE-


Re: How to break const

2012-06-18 Thread Matthias Walter
On 06/18/2012 07:36 AM, Mehrdad wrote:
 Is it just me, or did I subvert the type system here?
 
 
 import std.stdio;
 
 struct Const
 {
 this(void delegate() increment)
 { this.increment = increment; }
 int a;
 void delegate() increment;
 void oops() const { this.increment(); }
 }
 
 void main()
 {
 Const c;
 c = Const({ c.a++; });
 writeln(c.a);
 c.oops();
 writeln(c.a);
 }
 

I don't think so. When calling oops you have two references to the object c:

- The this-pointer of the object itself which is not allowed to change
the object in the const-call.
- The reference from within main which is allowed to change it and can
be reached via the frame pointer of the delegate.

I see this as perfectly valid code. Of course, opinions may differ here.

Matthias


Re: How to break const

2012-06-18 Thread Matthias Walter
On 06/18/2012 08:04 AM, Mehrdad wrote:
 On Monday, 18 June 2012 at 06:00:11 UTC, Matthias Walter wrote:
 On 06/18/2012 07:36 AM, Mehrdad wrote:
 Is it just me, or did I subvert the type system here?


 import std.stdio;

 struct Const
 {
 this(void delegate() increment)
 { this.increment = increment; }
 int a;
 void delegate() increment;
 void oops() const { this.increment(); }
 }

 void main()
 {
 Const c;
 c = Const({ c.a++; });
 writeln(c.a);
 c.oops();
 writeln(c.a);
 }


 I don't think so. When calling oops you have two references to the
 object c:

 - The this-pointer of the object itself which is not allowed to change
 the object in the const-call.
 - The reference from within main which is allowed to change it and can
 be reached via the frame pointer of the delegate.

 I see this as perfectly valid code. Of course, opinions may differ here.

 Matthias
 
 
 
 My trouble isn't with the delegate, it's with the const method.
 
 It's with the idea that you can tell something about the code just by
 looking at it.
 
 The way I understood it, you can assume that a `const` method cannot
 modify an object, but... that doesn't seem to be the case here.
 
 What am I misunderstanding?

Its not, that a const method cannot modify an object, it just ensures
that the const method cannot modify the object *by using the this-pointer*.

Other things cannot be ensured with const: For example, a const method
could wake up a 2nd thread and proceed with a longer computation. Then
this 2nd thread may have a reference to the object and may change it
while your computation is going on.


Re: How to break const

2012-06-18 Thread Matthias Walter
On 06/18/2012 08:19 AM, Mehrdad wrote:
 On Monday, 18 June 2012 at 06:14:22 UTC, Matthias Walter wrote:
 Its not, that a const method cannot modify an object, it just
 ensures that the const method cannot modify the object *by using
 the this-pointer*.
 
 
 
 I see...
 
 
 So that means you /can't/ tell something just by looking at a part
 of the code, right?
 
 (Just mentioning this since this idea seemed to be emphasized a lot
 by D.)

Yes, you are right with that.



Primary Ranges of Containers

2012-06-18 Thread Matthias Walter
Hi,

last week I realized that a const version of
std.container.Array.opSlice() is missing. Now I looked at the code and I
think that it is a general design problem.

The docs state that c.Range is The primary range type associated with
the container.. I think we really always need two Range types (one for
const view and one for non-const view) by design.

I'd propose to always add a bool template parameter (maybe isConst?) to
the range since most of the write-functionality can be removed by a
static if statement in order to make the range read-only.

Any suggestions?

Best regards,

Matthias


Getting a range over a const Container

2012-06-15 Thread Matthias Walter
Hi,

I have a const std.container object (e.g., a const(Array!int)) of which
I'd like to have a range which can traverse that container having
read-only access. This does not seem to be possible with opSlice(). Is
there an alternative?

Best regards,

Matthias


Re: const version for foreach/opApply

2012-06-11 Thread Matthias Walter
On 06/10/2012 12:30 AM, Era Scarecrow wrote:
 On Saturday, 9 June 2012 at 10:09:25 UTC, Matthias Walter wrote:
 First, thank you for your answer. I've already made some tiny
 modifications in order to make BitArray work for my purposes:

 https://github.com/xammy/phobos/commit/eb46d99217f2bf1e6d173964e2954248b08146d6


 If you plan to create pull requests for your changes - please consider
 my changes as well. When do you expect to finish, I.e., create a pull
 request for phobos?
 
  Curious... Almost all of the changes you proposed I've already added in
 my version, the toHash is the only one missing and I don't know if I can
 work that very well. The new version is going to include 'slice-like'
 features, which is mostly a couple extra numbers specifying the offset
 in bits from the beginning to the end; The problem with that is hashing
 would have a huge speed drop.
 
  I'm adding an 'realign' function that handles those cases, but the
 downside is shared slices where you would want to make changes may or
 may not work. Caching the result would also be useful... Hmmm...
 
  I don't suppose you have a toHash where I can enter the odd bits and
 then also bulk ones and have the hash return the same could you? I can

I see the problem. I don't know whether my hash function is a good one -
I just needed it to make AAs work with BitArray as a key type.

But the question is interesting. Finding a good hash function for bit
arrays which is invariant under realignment.

 see xor easily having this type of effect...
 
  Anyways, here's some things I can do so far; Got a few improvements
 left to do, but not many. (const  immutable friendly of course :) )
 
 -- 
 
 const BitArray ba = BitArray([1,1,0,0,1]);
 const BitArray slice = ba[1 .. ba.length];
 BitArray m = slice.dup;
 immutable BitArray im = slice.idup;
 
 assert(slice == ba[1 .. ba.length]);
 assert(slice == [1,0,0,1]);
 assert(slice == m);
 assert(slice == im);
 
 assert(slice.isCompact);
 writeln(GC not used);
 

Looks interesting!




Re: const version for foreach/opApply

2012-06-09 Thread Matthias Walter
On 2012-06-08 22:47, Era Scarecrow wrote:
 On Friday, 8 June 2012 at 16:33:28 UTC, Matthias Walter wrote:
 Hi,

 trying to traverse the entries of a std.bitmanip.BitArray I stumbled
 upon the following problem:

 In case I want to accept const(BitArray) objects, it shall look like
 the following (maybe using ref const(bool) for the delegate
 parameter?):

 int opApply(scope int delegate(bool) dg) const
 

 Can one glue both things together into a single routine (using inout
 magic or whatever)?
 
  I want to say you can't, because ref bool. If you ignore the reference,
 you don't need the non-const version (I think).
 
  I am currently working on BitArray updates, and it is const/immutable
 friendly according to as many tests as I could come up with for valid
 usage; This has taught me a lot on using templates, traits, constraints
 and how inout actually works. I haven't tried for a bit but I can try
 once more to send my code to GitHub, then you can give it a try.

First, thank you for your answer. I've already made some tiny
modifications in order to make BitArray work for my purposes:

https://github.com/xammy/phobos/commit/eb46d99217f2bf1e6d173964e2954248b08146d6

If you plan to create pull requests for your changes - please consider
my changes as well. When do you expect to finish, i.e., create a pull
request for phobos?


const version for foreach/opApply

2012-06-08 Thread Matthias Walter
Hi,

trying to traverse the entries of a std.bitmanip.BitArray I stumbled
upon the following problem:

The original code is as follows:

int opApply(scope int delegate(ref bool) dg)
{
  int result;
  for (size_t i = 0; i  len; i++)
  {
bool b = opIndex(i);
result = dg(b);
this[i] = b;
if (result)
  break;
  }
  return result;
}

In case I want to accept const(BitArray) objects, it shall look like the
following (maybe using ref const(bool) for the delegate parameter?):

int opApply(scope int delegate(bool) dg) const
{
  int result;
  for (size_t i = 0; i  len; i++)
  {
bool b = opIndex(i);
result = dg(b);
if (result)
  break;
  }
  return result;
}

Can one glue both things together into a single routine (using inout
magic or whatever)?

Best regards,

Matthias Walter


Re: Website

2012-06-01 Thread Matthias Walter
On 06/01/2012 07:42 AM, d coder wrote:
 Why am I being taken to Digital Daemon when I goto http://dlang.org ?

Seems like the DNS entry points still to the original IP address. That's
all I could find out.

 Where can I find official D language site now?

http://erdani.com/d/web/index.html exists but don't know how old this
version is.

best regards,

Matthias


Re: How to test for equality of types?

2012-05-19 Thread Matthias Walter
On 2012-05-19 09:05, Philippe Sigaud wrote:
 On Fri, May 18, 2012 at 11:51 PM, Simen Kjaeraas simen.kja...@gmail.com 
 wrote:
 
 Because Wrapper!(AliasStruct).Wrap does not exist. And _error_ is not
 equal to any other type.
 
 Yes. Wrap is included in the complete template name (Wrapper!(Wrap))
 and has no independent existence.
 You _can_ get access to it by exposing it as an alias, as you do in 
 AliasStruct:
 
 struct Wrapper(Wrap)
 {
 alias Wrap Wrapped; // cannot call it 'Wrap'
  ...
 
 }

Yes, of course you are right. This was my fault - after exposing it via
an alias, it prints true.

 (third case)
 false


 And here I disagree. This prints true on 2.059. Regression?
 
 AFAICT, this should print true.
 
 And, concerning Artur questio, on 2.059 (Linux):
 
  pragma(msg, is(w._wrap.Alias == AliasStruct.Alias));//   - true
  pragma(msg, typeof(w._wrap).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct

I would open a bug report with the following code which is a bit smaller
than my first wrong version:

=
module main;

struct MyStruct { }

struct AliasStruct
{
  alias MyStruct Alias;
}

struct Wrapper
{
  AliasStruct aliasStruct;
}

void main()
{
  Wrapper w;

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

Best regards,

Matthias


Re: How to test for equality of types?

2012-05-19 Thread Matthias Walter
On 2012-05-19 15:28, Philippe Sigaud wrote:
 On Sat, May 19, 2012 at 12:23 PM, Matthias Walter
 xa...@xammy.homelinux.net wrote:
 
 I would open a bug report with the following code which is a bit smaller
 than my first wrong version:

 =
 (...)
  pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
  static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true
  static assert(is(typeof(w.aliasStruct).Alias == AliasStruct.Alias));
 // - false
 }
 
 Seems like a pb concerning whether Alias is a type or a symbol. See
 A,B,C,D below:
 
 void main()
 {
  Wrapper w;
 
  pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
  static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true
  static assert(is(w.aliasStruct.Alias == AliasStruct.Alias)); // - true
 
  alias typeof(w.aliasStruct) A; // - OK
  //alias typeof(w.aliasStruct).Alias B; // - NOK
  //alias A.Alias C; // - NOK
  alias w.aliasStruct.Alias D; // - OK
 
  static assert(is(A.Alias == AliasStruct.Alias)); // - true
  //static assert(is(B == AliasStruct.Alias));
  //static assert(is(C == AliasStruct.Alias));
  static assert(is(D == AliasStruct.Alias)); // - true
 }
 
 I think A is enough for your need, but I don't get why B and C are not
 accepted (DMD 2.059, Linux)
 

Using the current git version of dmd I realized that C works! Hence, as
a workaround it can be used by creating a local alias A and subsequently
using A.Alias in the is-expressions. But it seems odd that

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

Is this considered as a bug?

Best regards,

Matthias


How to test for equality of types?

2012-05-18 Thread Matthias Walter
Hi,

how do I test two types for equality? Suppose I have A and B aliasing
some type(s), how do I find out if they are aliases the same thing?

I tried the is(A == B) expression, but this does not always work (tell
me if I shall give an example).

On the other hand, according to the spec the IsExpression is not
supposed to compare two aliases with each other.

Best regards,

Matthias


Re: How to test for equality of types?

2012-05-18 Thread Matthias Walter


On 2012-05-18 16:12, Steven Schveighoffer wrote:
 On Fri, 18 May 2012 06:06:45 -0400, Matthias Walter wrote:
 how do I test two types for equality? Suppose I have A and B aliasing
 some type(s), how do I find out if they are aliases the same thing?

 I tried the is(A == B) expression, but this does not always work (tell
 me if I shall give an example).
 
 I would expect this to work.  What situation does it not (maybe you
 aren't actually testing for equality there).
 
 It could be a bug...

=

struct MyStruct { }

struct Wrapper(Wrap)
{
  Wrap _wrap;

  this(Wrap wrap)
  {
_wrap = wrap;
  }
}


struct AliasStruct
{
public:
  alias MyStruct Alias;
}


int main(char[][] args)
{
  auto w = Wrapper!(AliasStruct)(AliasStruct.init);
  pragma(msg, is(Wrapper!(AliasStruct).Wrap == AliasStruct) ? true :
false);
  pragma(msg, is(typeof(w._wrap) == AliasStruct) ? true : false);
  pragma(msg, is(typeof(w._wrap).Alias == AliasStruct.Alias) ? true :
false);


  return 0;
}
=

prints out

false
true
false

during compilation using current git version of dmd. In my application I
used the third case, i.e., wanted to find out whether they alias the
same thing.

 On the other hand, according to the spec the IsExpression is not
 supposed to compare two aliases with each other.
 
 where does it say that?

Okay, this seems to be my fault. It states different cases for the RHS
operator of is(LHS == RHS), e.g., Type == TypeSpecialization, but
nothing like Type == Type. But TypeSpecialization includes Type as well...

Best regards,

Matthias


Re: Keyword arguments / Named parameters library implementation

2012-03-20 Thread Matthias Walter
On 03/19/2012 08:21 PM, Andrej Mitrovic wrote:
 On 3/19/12, Matthias Walter xa...@xammy.homelinux.net wrote:
 Hi,

 I've written a small module (at the moment called utils.keywordargs)
 which simulates keyword arguments (aka named parameters).
 
 Cool. A small tip (in case you didn't already know):
 
 You can use allSatisfy from std.typetuple when checking a single
 constraint on multiple parameters: static
 assert(allSatisfy!(isKeywordArgument, H, V));

Didn't know that - thanks a lot!





Re: Keyword arguments / Named parameters library implementation

2012-03-20 Thread Matthias Walter
On 03/19/2012 07:53 PM, bearophile wrote:
 Matthias Walter:
 
 I've written a small module (at the moment called utils.keywordargs)
 which simulates keyword arguments (aka named parameters). The
 documentation can be found here,
 
 Regardless the implementation quality of your code, I wait for the real thing 
 :-)

I understand the real thing as a language implementation of keyword
arguments instead of a library workaround, right?



Keyword arguments / Named parameters library implementation

2012-03-19 Thread Matthias Walter
Hi,

I've written a small module (at the moment called utils.keywordargs)
which simulates keyword arguments (aka named parameters). The
documentation can be found here,

http://xammy.xammy.homelinux.net/~xammy/utils_keywordargs.html

while the code is at

http://xammy.xammy.homelinux.net/~xammy/keywordargs.d

or in a better readable format: http://pastebin.com/AfqKKziW


There was some discussion about introducing them in the language a while
ago. One argument against keyword arguments was that the names become
part of the interface. This wouldn't be different when using my
implementation, but as the names are compile-time strings, handling
different versions of a library is just a matter of putting the right
string constant into the keyword argument template.

Any comments? Is something like that interesting for phobos? If yes, I'd
suggest to put it on github to make further work easier.

Best regards,

Matthias



Remarks on std.container

2012-03-08 Thread Matthias Walter
Hi,

I wanted to have a binary heap where I can update entries and restore
the heap structure.

1. First I observed that due to the implementation of
std.container.BinaryHeap, keeping track of the position of a certain
value in the heap cannot be done directly, but it would be helpful to
pass a Swapper object (or function) to the methods that may change the
order of the elements such that this Swapper is called for every swap()
operation such that the user of the BinaryHeap can keep track of the
permutation.

2. I tried to create a heap structure on my own, using
std.container.Array as a store. Of course, it I also needs to perform
swap operations, but the following did not work:

std.algorithm.swap(arrayInstance[i], arrayInstance[j]);

Also there is no usable swap() method of Array. So do I really have to
perform the swap on my own? I mean, 3 lines of code aren't that much but
I really expected an easy way.

3. For my structure I wanted to check the heap structure in an
invariant(). Unfortunately, accessing stored elements of Array is no
const operation, hence I could not implement such an invariant.

Maybe I'm not using it correctly, so any help or comments would be nice.

Best regards,

Matthias


Named parameters workaround

2012-02-09 Thread Matthias Walter
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Hi,

named parameters have been discussed awhile ago and it seems to me
that they won't get into the language soon. I came up with a
workaround that makes it possible to use them with some extra typing.

Suppose we have a function

foo(int a, int b, string c, MyStruct d, MyClass e);

and want to call with with named parameters. It is possible to write a
wrapper function as follows

foo(N)(N n)
{
  foo(
n.has!a() ? n.get!a() : 42, // 42 is the default parameter
n.get!b(), // Complain if b is not given
n.has!c() ? n.get!c() : foo,
n.has!d() ? n.get!d() : MyStruct(),
n.has!e() ? n.get!e() : new MyClass()
 );
}

and then call it

foo(named!c,b,e(Foo, 0, new MyClass()));

With some more work we could also allow

foo(named!c(Foo), named!b(0), named!e(new MyClass()));

All this can be handled by a templated Wrapper-Object that is created
by named()(). When doing the code generation of the wrapper object via
a mixin, we could also allow ref parameters (with named!ref
e(my_class) and by storing a pointer).

Of course, the code for the wrapper can be inlined because the
presence of every parameter can be decided at compile time.

Any ideas?

Best regards,

Matthias
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJPM5SOAAoJEPdcuJbq5/sRr/MIAL0tJBGWdkhrPUbaS5gqb9ho
jkyKW8u+akVMnlTW4BKQ7lHSkJBySZxn4Ty/zIJEmqoIHrlsI308z26miSy5bDeK
XcNAx1M+3wUuvYPoJpg3nlARofez9R0n1opfS6DnDYHGYLZH9AK924bwKyChFfP9
a/6mEyPHsMem/+2CWIWJjsLzEBkc+OacgCmzj7dGZfoJBhmF/EjxZgdwYpnA8q3N
KYIl28gqyf+JBkmdzVhhDuBMUb1PlqqqnbXS66EaYcQIA7bUESPc8dKJKIQTKVy3
Lq5MSg8BuvMdnIXYVn0HK4R2LWTshZn5kXkfy7EX8Xw4yyT4e6VIkcwDOyy8iMQ=
=T4UD
-END PGP SIGNATURE-


Mixture of type tuple and expression tuple

2012-02-06 Thread Matthias Walter
Hi,

I'd like to have a function foo which shall depend on several
compile-time expressions (e.g. strings) and gets several arguments whose
types are templatized. Here, several means in both cases that the
number of expressions/arguments are to be determined at compile-time.
Here is an example:

foo!(a, b, c)(42, new MyClass(), 7.0);

At compile-time, some template parameters (strings a, b and c)
shall be given explicitly and some more template parameters (types of
arguments int, MyClass, double) shall be deduced from the function
arguments.

Is that possible? Of course, I cannot setup two TemplateTupleParameters.

Best regards,

Matthias



dup method const or not?

2011-11-27 Thread Matthias Walter
Hi,

Recently, I realized that several dup methods in D2's phobos are
declared like the one for BitArray:

@property BitArray dup()

My question is why it is declared without const? Is it a bug or is
there a reason for it? I can think of a case where one only has
implemented a shallow copy and wants to omit the const due to the
involved transitivity, but this shouldn't be the case for BitArray (the
underlying array is dup'ed). Is there a general rule/recommendation when
to make a dup method const and when not? My problem arises in a copy
constructor for a struct S which takes a const(S) instance. But as S has
a BitArray member, duping is not allowed, so I need a way to duplicate a
const(BitArray) object.

Matthias


Re: dup method const or not?

2011-11-27 Thread Matthias Walter
On 2011-11-27 23:48, mta`chrono wrote:
 that's a real good question. it fails with the following error:
 
 Error: function std.bitmanip.BitArray.dup () is not callable using
 argument types () const
 
 
 here is a hack:
 
 ---
 import std.bitmanip;
 import core.stdc.string;
 
 void main()
 {
 const(BitArray) foo;
 BitArray bar;
 
 memcpy(bar, foo, BitArray.sizeof);
 }

Well, this hack doesn't even work - as it does a shallow copy only,
immediately setting bits of bar also changes bits of foo!

Matthias


Stable sort in std.algorithm throws Range violation

2011-04-08 Thread Matthias Walter
Hi,

when using the most recent D2/32bit version from github of
dmd+druntime+phobos I get a Range violation from the following code:

| import std.algorithm;
|
| void main(char[][] args)
| {
|   sort!(a  b, SwapStrategy.stable)([1,0, 3, 2]);
| }

Can anybody confirm this? Shall I file a bug?

best regards,

Matthias Walter


Re: greatest common divisor implementation

2011-02-14 Thread Matthias Walter

 1. Are there any further suggestions on the implementations / Did I
 forget something?
 Are benchmarks done with BigInt and long too? (If you test bigints you 
 need bigger numbers too, and to test that the results are correct).
Yeah, so I did tests for long now, too. Unfortunately with gdc I was
unable to generate uniform long numbers (UniformIntGenerator.popFront
not implemented for large ranges). Interestingly, with DMD it works...

The dmd-only results of long as type, with random long values:

SimpleRecursive!(long):  0.134
SimpleIterative!(long):  0.127
BinaryRecursive!(long):  1.727
BinaryIterative!(long):  0.345
BoostIterative!(long):   0.136
BoostBinary!(long):  0.575
gcdSteinTable!(long, 1): 0.594
gcdSteinTable!(long, 2): 0.527
gcdSteinTable!(long, 3): 0.489
gcdSteinTable!(long, 4): 0.536
gcdSteinTable!(long, 5): 0.489
gcdSteinTable!(long, 6): 0.531
gcdSteinTable!(long, 7): 0.498
gcdSteinTable!(long, 8): 0.542
gcdSteinTable!(long, 9): 0.491
gcdSteinTable!(long,10): 0.539
gcdSteinTable!(long,11): 0.494
gcdSteinTable!(long,12): 0.538

The results for dmd and gdc with long as type, but random int values:

SimpleRecursive!(long):  0.110 0.143
SimpleIterative!(long):  0.100 0.136
BinaryRecursive!(long):  0.661 0.208
BinaryIterative!(long):  0.166 0.133
BoostIterative!(long):   0.104 0.142
BoostBinary!(long):  0.277 0.174
gcdSteinTable!(long, 1): 0.275 0.134
gcdSteinTable!(long, 2): 0.259 0.130
gcdSteinTable!(long, 3): 0.249 0.108
gcdSteinTable!(long, 4): 0.253 0.095
gcdSteinTable!(long, 5): 0.243 0.089
gcdSteinTable!(long, 6): 0.243 0.086
gcdSteinTable!(long, 7): 0.245 0.084
gcdSteinTable!(long, 8): 0.245 0.082
gcdSteinTable!(long, 9): 0.246 0.081
gcdSteinTable!(long,10): 0.245 0.081
gcdSteinTable!(long,11): 0.246 0.080
gcdSteinTable!(long,12): 0.250 0.081



 2. What do you think, we should finally use?
 It seems more complex algorithms don't pay much for int values.
I agree on that and suggest to take Boost's implementation which is very
readable, too.

I will probably do some tests with BigInt, too. But I suspect that the
result looks totally different which means that we'll use different
specializations. The same holds true for the extended algorithm.

@Andrei: As soon as I'm done, I'll submit a pull request to github.

Matthias


Re: greatest common divisor implementation

2011-02-14 Thread Matthias Walter

 1. Are there any further suggestions on the implementations / Did I
 forget something?
 Are benchmarks done with BigInt and long too? (If you test bigints you 
 need bigger numbers too, and to test that the results are correct).
I'd like to work on the BigInt things but there are a couple of blockers:

1. abs() does not work, because opCmp for BigInts is not pure, yet. IIRC
Don waits / waited for a pure/nothrow bug to be fixed before he'd
continue working on BigInt purity, etc.

2. I don't think the current random number implementation has code to
generate BigInts easily via uniform() method. There was a fixed number
of bits that are used per call.

So I suggest to work on the Extended Euclidean algorithm implementations
and get results for int/long for those. If this is done I'll submit a
pull request with nice code for int+long and code for BigInt that just
works but is not benchmarked. Then we should change the gcd bug to
BigInt-only (or open another one...)

Matthias


Re: greatest common divisor implementation

2011-02-13 Thread Matthias Walter
On 02/07/2011 05:13 PM, Andrei Alexandrescu wrote:
 On 2/7/11 3:18 PM, Matthias Walter wrote:
 Hi everyone,

 as I'm currently working on a C++ project which involves gcd
 computations I had a quick look at phobos' implementation.

 1. First thing I saw is that gcd(-3,6) raises an exception, although
 mathematically it is just 2. Of course checking the sign of the
 arguments takes computation time, but for my stuff I'd definitely need
 it. If it's really too expensive then there should be at least another
 routine.

 2. I'd be happy to implement the Extended Euclidean algorithm for phobos
 which also gives multipliers s and t such that gcd(x,y) = s*x + t*y.

 Any comments before I start working on it?

 Matthias

 Please do. I implemented gcd in a hurry because I needed it for
 unsigned numbers, so it's not the greatest it could be. A github pull
 request would be much appreciated!
I re-implemented [1] several things like recursive / iterative or modulo
/ binary implementations. For the latter I found one with a lookup-table
that pre-computes partial results.

The testbed generated a sequence of 1 int pairs, computing the gcd
of a pair of ints and adding the sum of all (as checksum and to avoid
removal by the compiler). This was repeated 100 times using the same
sequence. Time is per gcd call and given in nanoseconds.

First column: dmd -O -release -inline
Second column: gdc -O3

SimpleRecursive:0.096 0.086
SimpleIterative:0.090 0.083
BinaryRecursive:0.240 0.213
BinaryIterative:0.141 0.133
BoostIterative: 0.087 0.085
BoostBinary:0.219 0.177
gcdSteinTable!(int, 1): 0.161 0.136
gcdSteinTable!(int, 2): 0.133 0.130
gcdSteinTable!(int, 3): 0.107 0.108
gcdSteinTable!(int, 4): 0.093 0.094
gcdSteinTable!(int, 5): 0.089 0.088
gcdSteinTable!(int, 6): 0.087 0.083
gcdSteinTable!(int, 7): 0.086 0.081
gcdSteinTable!(int, 8): 0.085 0.081
gcdSteinTable!(int, 9): 0.085 0.082
gcdSteinTable!(int,10): 0.085 0.080
gcdSteinTable!(int,11): 0.086 0.082
gcdSteinTable!(int,12): 0.086 0.080

Remark: The 2nd template parameter of the gcdSteinTable implementation
means the number of bits for the lookup-table. It therefore uses 2^bits
bytes of memory!

1. Are there any further suggestions on the implementations / Did I
forget something?

2. What do you think, we should finally use?

3. I will also implement the extended gcd (i.e. having gcd(a, b) = z = x
* a + y * b we are interested in x,y,z)

Matthias

[1] http://pastebin.com/sXpsdK5S


greatest common divisor implementation

2011-02-07 Thread Matthias Walter
Hi everyone,

as I'm currently working on a C++ project which involves gcd
computations I had a quick look at phobos' implementation.

1. First thing I saw is that gcd(-3,6) raises an exception, although
mathematically it is just 2. Of course checking the sign of the
arguments takes computation time, but for my stuff I'd definitely need
it. If it's really too expensive then there should be at least another
routine.

2. I'd be happy to implement the Extended Euclidean algorithm for phobos
which also gives multipliers s and t such that gcd(x,y) = s*x + t*y.

Any comments before I start working on it?

Matthias


Re: On 80 columns should (not) be enough for everyone

2011-01-30 Thread Matthias Walter


On 01/30/2011 01:01 PM, Peter Alexander wrote:
 On 30/01/11 5:17 PM, Andrej Mitrovic wrote:
 The unittest topic is about to get derailed so I want to continue
 this silly discussion here.

 Wheres Nick? I want to see the CRT vs LCD discussion heated up again
 with Andrei claiming that LCDs are so Godlike but yet claims 80
 columns is enough for everyone.

 80 colums is an artifact of the old age. Just like the preprocessor
 is an artifact of the C language. And many other old things are
 artifacts. There's no reason to keep these artifacts around anymore.

 snip

 Is this really worth arguing about?

 Just stick to 80 columns. It's not a big deal.
One argument that I can think of is to at least raise the number of
allowed columns. Why? Well, phobos' names like tr will be (or are)
refactored to translate and with camelcase we encourage people to use
descriptive names. And with template parameters and everything I do not
want to call functions, putting 1 argument on every line. I'd suggest
raising it to 120 or 150...


Re: structs vs classes

2011-01-29 Thread Matthias Walter
On 01/29/2011 09:13 AM, Jim wrote:
 so Wrote:

 I'm a bit troubled with the class/struct dichotomy. I would prefer them  
 both to use the same keyword. Heap/stack allocation could be specified  
 during instantiation instead. Why? Now you need to choose one over the  
 other. Not even C++ has this limitation.
 This keeps coming and i have no idea how people think C++ treatment is any  
 way good.
 You are free to call the D design of struct/class the worst possible, but  
 at least don't base your reasoning to C++ please.

 C++: both class and struct are exactly same, except one trivial:

 struct A : B {
 };

 means:

 class A : public B {
 public:
 };

 In D they are quite different and they have different keywords.

 http://www.digitalmars.com/d/2.0/class.html
 http://www.digitalmars.com/d/2.0/struct.html
 I'm only discussing the heap/stack difference.

That is of course a difference, but no argument. The reason is that you
can decide whether you want to allocate a class on the stack:

http://www.digitalmars.com/d/2.0/memory.html#stackclass

Matthias


Re: thin heaps

2010-12-20 Thread Matthias Walter
On 12/20/2010 05:01 PM, Andrei Alexandrescu wrote:
 Just saw this:

 http://www.reddit.com/r/programming/comments/eoq15/implementing_shortest_path_in_c_is_much_easier/


 in which a reader points to this paper on thin heaps:

 http://www.cs.princeton.edu/courses/archive/spr04/cos423/handouts/thin%20heap.pdf


 Does anyone here have experience with thin heaps? I think they'd be a
 good addition to std.container.
You might have realized my recent interest in std.container.BinHeap as a
priority queue. In fact I thought about implementing Fibonacci Heaps
with the same interface for D. I worked on a C++ implementation a while
ago, so maybe I should give the Thin Heaps a try?

Matthias


Re: Binary heap method to update an entry.

2010-12-16 Thread Matthias Walter
On 12/16/2010 04:17 AM, Andrei Alexandrescu wrote:
 On 12/15/10 10:21 PM, Matthias Walter wrote:
 Hi all,

 I uploaded [1] a patch for std.container to use BinaryHeap as a priority
 queue. For the latter one it is often necessary to change a value (often
 called decreaseKey in a MinHeap). For example, Dijkstra's shortest path
 algorithm would need such a method. My implementation expects that the
 user calls the update method after changing the entry in the
 underlying store.

 My method works for value-decrease and -increase, but one might want to
 split this functionality into two methods for efficiency reasons. But I
 thought it'll be better, because one can change the MaxHeap to be a
 MaxHeap by changing the template alias parameter, but this wouldn't
 change the method names :-)

 The patch is against current svn trunk.

 [1]
 http://xammy.xammy.homelinux.net/files/BinaryHeap-PriorityQueue.patch

 A better primitive is to define update to take an index and a new
 value, such that user code does not need to deal simultaneously with
 the underlying array and the heap. No?
Well, I thought of the case where you have an array of structs and use a
custom less function for ordering. There you might not have a new value,
i.e. a replaced struct, but just a minor change internally. But I see
your idea, in most cases you would just call update after replacing your
array entry... Could we provide both, maybe?

Matthias Walter


Re: Binary heap method to update an entry.

2010-12-16 Thread Matthias Walter
On 12/16/2010 10:53 AM, Andrei Alexandrescu wrote:
 On 12/16/10 7:55 AM, Matthias Walter wrote:
 On 12/16/2010 04:17 AM, Andrei Alexandrescu wrote:
 On 12/15/10 10:21 PM, Matthias Walter wrote:
 Hi all,

 I uploaded [1] a patch for std.container to use BinaryHeap as a
 priority
 queue. For the latter one it is often necessary to change a value
 (often
 called decreaseKey in a MinHeap). For example, Dijkstra's shortest
 path
 algorithm would need such a method. My implementation expects that the
 user calls the update method after changing the entry in the
 underlying store.

 My method works for value-decrease and -increase, but one might
 want to
 split this functionality into two methods for efficiency reasons.
 But I
 thought it'll be better, because one can change the MaxHeap to be a
 MaxHeap by changing the template alias parameter, but this wouldn't
 change the method names :-)

 The patch is against current svn trunk.

 [1]
 http://xammy.xammy.homelinux.net/files/BinaryHeap-PriorityQueue.patch

 A better primitive is to define update to take an index and a new
 value, such that user code does not need to deal simultaneously with
 the underlying array and the heap. No?
 Well, I thought of the case where you have an array of structs and use a
 custom less function for ordering. There you might not have a new value,
 i.e. a replaced struct, but just a minor change internally. But I see
 your idea, in most cases you would just call update after replacing your
 array entry... Could we provide both, maybe?

 Good point. Here's what I suggest:

 /**
   Applies unary function fun to the element at position index, after
 which moves that element to preserve the heap property. (It is assumed
 that fun changes the element.) Returns the new position of the element
 in the heap.

 Example:

 
 int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
 auto h = heapify(a);
 assert(equal(a, [ 16, 14, 10, 9, 8, 7, 4, 3, 2, 1 ]));
 h.update!a -= 5(1);
 assert(equal(a, [ 16, 10, 9, 9, 8, 7, 4, 3, 2, 1 ]));
 
 */
 size_t update(alias fun)(size_t index);

 Let me know of what you think, and thanks for contributing. When using
 unaryFun inside update, don't forget to pass true as the second
 argument to unaryFun to make sure you enact pass by reference.
Good idea. I like the interface!

Btw, can I then call a routine in the string, too? Like

h.update!a.updatePriority()(1);

Although this does look ugly, so separating the call would probably make
more sense.

Matthias


Re: (Improved) Benchmark for Phobos Sort Algorithm

2010-12-16 Thread Matthias Walter
On 12/16/2010 09:36 PM, Craig Black wrote:
 It was brought to my attention that the quick sort has a very bad
 worst case, so I implemented a simple fix for it.  Now the worst case
 (completely ordered) is the best case, and it only slows down the
 general case by a small percentage.  I thought to myself, it can't be
 this easy to fix quick sort.  Does anyone see a flaw in this simple
 fix?  Performs much better than Phobos in completely random and
 completely sorted data.  Perhaps there is another case where it
 doesn't do as well?

Yes, there is a flaw: There are still instances of arrays where you
will end up with a pivot element being one of the largest or one of the
smallest elements in *every* call. The means, that you split your array
from length n not into two arrays roughly of size n/2 and n/2, but of
O(1) and n - O(1). This implies a running time of n^2 (in contrast to n
log n), which is obviously bad.

I don't know how std.algorithm.sort works, but C++ STL uses an
Introspective sort, which is a quick-sort variant like you have, but it
has some measurements that observe whether the above worst case occurs
(e.g. by looking at the recursion depth) and switches to a heap-sort in
this case. [1]

Matthias

[1] http://en.wikipedia.org/wiki/Introsort


Binary heap method to update an entry.

2010-12-15 Thread Matthias Walter
Hi all,

I uploaded [1] a patch for std.container to use BinaryHeap as a priority
queue. For the latter one it is often necessary to change a value (often
called decreaseKey in a MinHeap). For example, Dijkstra's shortest path
algorithm would need such a method. My implementation expects that the
user calls the update method after changing the entry in the
underlying store.

My method works for value-decrease and -increase, but one might want to
split this functionality into two methods for efficiency reasons. But I
thought it'll be better, because one can change the MaxHeap to be a
MaxHeap by changing the template alias parameter, but this wouldn't
change the method names :-)

The patch is against current svn trunk.

[1] http://xammy.xammy.homelinux.net/files/BinaryHeap-PriorityQueue.patch


BinaryHeap usage

2010-12-14 Thread Matthias Walter
Hi all,

suppose I have an array of comparable Foo structs which I want to access
in a sorted order (e.g. a priority queue) using a BinaryHeap object (I
know that for just sorting, the BinHeap is not the right tools), but I
do not want to change the order of the objects in the original array.

I have two ideas on how to do this and just want to know whether they
are the right way:

a) Have an array of Foo*, initialize it from the original and
instantiate the BinaryHeap with a Comparision-predicate that
dereferences first.

b) Have an array of indices that are indicies in the original array
(like a permutation in a permutation group) and access the corresponding
index of the original array for comparison.

Any further ideas for this problem, or did I cover everything already?

Matthias


Re: Casting functions to delegates

2010-12-12 Thread Matthias Walter
On 12/12/2010 06:15 AM, Dmitry Olshansky wrote:
 On 12.12.2010 7:25, Matthias Walter wrote:
 Hi all,

 there was a discussion in 2006 but w/o a result, and I didn't find any
 bugs about implicitely casting functions to delegates. It seems to be
 impossible as long as function-pointer calls work differently than
 delegate calls in the ABI. Will this at some point be fixed?

 If not, is there a conversion function in phobos (I didn't find one)? I
 played a bit and found that this one might work:

 R delegate(A) funcionToDelegate (R, A...) (R function(A) func)
 {
return (A a){ return func(a); };
 }

 Matthias
 There is actually almost forgotten function in std.functional -
 toDelegate, which does it in the most general way, functional objects
 covered.
 Sadly enough it's not listed in docs, because of the auto return.
Ah, thank you very much! That looks like what I was looking for.


Re: ByToken Range

2010-12-12 Thread Matthias Walter
On 12/12/2010 02:04 AM, Christopher Nicholson-Sauls wrote:
 On 12/11/10 22:41, Matthias Walter wrote:
 Hi all,

 I wrote a ByToken tokenizer that models Range, i.e. it can be used in a
 foreach loop to read from a std.stdio.File. For it to work one has to
 supply it with a delegate, taking a current buffer and a controller
 class instance. It is called to extract a token from the unprocessed
 part of the buffer, but can act as follows (by calling methods from the
 controller class):

 - It can skip some bytes.
 - It can succeed, by eating some bytes and setting the token to be read
 by the front() property.
 - It can request more data.
 - It can indicate that the data is invalid, in which case further
 processing is stopped and a user-supplied delegate is invoked that may
 or may not handle this failure.


 It is efficient, because it reuses the same buffer every time and just
 supplies the user with a slice of unprocessed data. If more data is
 requested, the remaining unprocessed part is copied to the beginning and
 more data is read. If there is no such unprocessed data, the buffer is
 enlarged, i.e. length doubled.

 The ByToken class has the type of a token as a template parameter.

 Does this behavior make sense? Any further suggestions?
 Is there any interest in having this functionality, i.e. should I create
 a dsource project,
 or does everybody use parser-generators for everything?

 Matthias
 I write lexers/parsers relatively often -- and I don't use generators...
 because I'm masochistic like that!  And because there aren't many
 options for D.  There was Enki for D1 a while back, which might still
 work pretty well, and there's GOLD although I'm not aware of how their D
 support is right now.  I might be forgetting another.

 So I, for one, like the idea of it at the very least.  I'd have to see
 it in action, though, to say much beyond that.
My current version can be used as follows to yield a simple word-tokenizer:

http://pastebin.com/qjH6y0Mf

As I'm going to use it for one or two real-world file formats I might
change some things, but for now I like it. If you have any suggestions
for improvements, please let me know.

Matthias


Casting functions to delegates

2010-12-11 Thread Matthias Walter
Hi all,

there was a discussion in 2006 but w/o a result, and I didn't find any
bugs about implicitely casting functions to delegates. It seems to be
impossible as long as function-pointer calls work differently than
delegate calls in the ABI. Will this at some point be fixed?

If not, is there a conversion function in phobos (I didn't find one)? I
played a bit and found that this one might work:

R delegate(A) funcionToDelegate (R, A...) (R function(A) func)
{
  return (A a){ return func(a); };
}

Matthias


ByToken Range

2010-12-11 Thread Matthias Walter
Hi all,

I wrote a ByToken tokenizer that models Range, i.e. it can be used in a
foreach loop to read from a std.stdio.File. For it to work one has to
supply it with a delegate, taking a current buffer and a controller
class instance. It is called to extract a token from the unprocessed
part of the buffer, but can act as follows (by calling methods from the
controller class):

- It can skip some bytes.
- It can succeed, by eating some bytes and setting the token to be read
by the front() property.
- It can request more data.
- It can indicate that the data is invalid, in which case further
processing is stopped and a user-supplied delegate is invoked that may
or may not handle this failure.


It is efficient, because it reuses the same buffer every time and just
supplies the user with a slice of unprocessed data. If more data is
requested, the remaining unprocessed part is copied to the beginning and
more data is read. If there is no such unprocessed data, the buffer is
enlarged, i.e. length doubled.

The ByToken class has the type of a token as a template parameter.

Does this behavior make sense? Any further suggestions?
Is there any interest in having this functionality, i.e. should I create
a dsource project,
or does everybody use parser-generators for everything?

Matthias


Re: D2 byChunk

2010-12-11 Thread Matthias Walter


On 12/11/2010 01:00 AM, Christopher Nicholson-Sauls wrote:
 On 12/10/10 22:36, Matthias Walter wrote:
 On 12/10/2010 09:57 PM, Matthias Walter wrote:
 Hi all,

 I currently work on a parser for some file format. I wanted to use the
 std.stdio.ByChunk Range to read from a file and extract tokens from the
 chunks. Obviously it can happen that the current chunk ends before a
 token can be extracted, in which case I can ask for the next chunk from
 the Range. In order to keep the already-read part in mind, I need to dup
 at least the unprocessed part of the older chunk and concatenate it in
 front of the next part or at least write the code that works like they
 were concatenated. This looks like a stupid approach to me.

 Here is a small example:

 file contents: Hello world
 chunks: Hello w orld

 First I read the token Hello from the first chunk and maybe skip the
 whitespace. Then I have the w (which I need to move away from the
 buffer, because ByChunk fill overwrite it) and get orld.

 My idea was to have a ByChunk-related Object, which the user can tell
 how much of the buffer he/she actually used, such that it can move this
 data to the beginning of the buffer and append the next chunk. This
 wouldn't need further allocations and give the user contiguous data
 he/she can work with.
 I coded something that works like this:

 foreach (ref ubyte[] data; byBuffer(file, 12))
 {
   writefln([%s], cast(string) data);
   data = data[$-2 .. $];
 }

 The 2nd line in the loop tells ByBuffer that we didn't process the last
 two chars and would like to get them again along with newly read data.
 And as long as we do process something, the internal buffer does not get
 reallocated.

 It works and respects the formal requirements of ranges. Whether it
 respects the intended semantics, one can discuss about. Any comments
 whether the above things make sense or is an evil exploit of the
 provided syntax sugar?
 I don't think it's a bad approach, but I have a suggestion.

 It leaves a lot of room for abuse or misuse if you require the user code
 to modify the data[] array in order to send this protect some
 characters message.  I think it would be better to provide an explicit
 function/method that means precisely that.  Maybe return a transparent
 struct wrapping a view to the buffer's data, that further provides a
 function for doing precisely this.

 foreach( data; byBuffer( file, 12 )) {
   // do things with data, decide we need to keep 2 chars
   data.save( 2 );
 }

 Or something like it.  With regards to this, you may want to allow the
 internal buffer to grow (if you aren't already) as needed.  Imagine what
 would otherwise happen if you needed to 'save' the entire current buffer.

 -- Chris N-S
Thank you! This is a really good idea. So I basically wrap the
buffer-array and implement it such that the default behavior (without
explicitely doing something) is like the ByChunk mechanism.

Matthias


Re: setting array dimensions at runtime

2010-12-05 Thread Matthias Walter

 The only thing I've been able to think of is

byte[][] a;
a.length = size;
for (int i; i  size; i++) {
 a[i].length = size;
}
Well, you can do at least:

auto a = new byte[][size];
foreach (ref row; a)
  row = new byte[size];

Matthias



Re: bigint

2010-11-28 Thread Matthias Walter
On 11/27/2010 02:05 PM, bearophile wrote:
 Reduced case for bugzilla:
 
 http://d.puremagic.com/issues/show_bug.cgi?id=5281
   
I investigated into the bug and the reason is the signature of opEquals,
which currently is

bool opEquals(Tdummy=void)(ref const BigInt y) const
bool opEquals(T: int)(T y) const

The only working sigature for array-of-structs-comparison to work is

bool opEquals(ref const BigInt y) const

But this removes the ability to compare against ints.
(btw, it should probably be long in the 2nd signature?!)

array-comparison should definitely take templated opEquals functions
into account, or is there something mentioned in the spec?

Matthias


Re: value range propagation for %

2010-11-27 Thread Matthias Walter
On 11/27/2010 12:54 PM, Ellery Newcomer wrote:
 Hello.

 Today I've been thinking about calculating the range of values for

 x % y

You might want to state the problem more precisely. What exactly is a
range of values x % y ? Do you look at the result for x,y in some
sets? Or is either x or y fixed? From your example I would suppose that
x shall be fixed and y goes through a range?!

Matthias


Re: Basic coding style

2010-11-23 Thread Matthias Walter


On 11/23/2010 12:12 AM, Jonathan M Davis wrote:
 On Monday 22 November 2010 21:03:27 Walter Bright wrote:
   
 Matthias Walter wrote:
 
 What about adding a compiler switch that one can turn on and that warns
 on obviously wrong names? Is this realistic? At least to check the usage
 of underscores and captial first letter. The CamelCase can probably not
 be verified, but hopefully a lot of programmers will use it, if the
 compiler encourages them to not use underscores... Just an idea, you can
 flame on, if you like.
   
 If you want, it would be easy to write a simple program that read the .json
 output of the compiler, and then enforce any naming convention you need.
 
 That could be a useful tool. And I do think that a basic set of typical D 
 naming conventions and the like could be useful. But I don't really think 
 that 
 it makes sense to have the compiler itself enforcing style. That sort of 
 thing 
 definitely belongcs in external tools.
   
So we should talk to the IDE designers, s.t. they include this into
their list of planned features. I recommend a 3-minute alarm sound per
badly named variable/function :)

Matthias


Re: Basic coding style

2010-11-22 Thread Matthias Walter
On 11/22/2010 06:21 PM, JimBob wrote:
 bearophile bearophileh...@lycos.com wrote in message 
 news:icdnn4$2cn...@digitalmars.com...
   
  I have four or five times tried to explain why coding standards are 
 important for the
 development of the D community
 
 And them there stupid people just wont listen to ya. Thats mighty 
 unreasonable of them, you being president of the world an all. 
   
Come on guys, please don't flame here...

I don't like to force anybody in using a style they maybe don't like.
But on the other hand I think bearophile's arguments have some truth in
them.

What about adding a compiler switch that one can turn on and that warns
on obviously wrong names? Is this realistic? At least to check the usage
of underscores and captial first letter. The CamelCase can probably not
be verified, but hopefully a lot of programmers will use it, if the
compiler encourages them to not use underscores... Just an idea, you can
flame on, if you like.

Matthias


Re: Repairing BigInt const

2010-11-21 Thread Matthias Walter
On 11/21/2010 04:33 PM, Don wrote:
 Matthias Walter wrote:
 as it seems, the current version of BigInt is not capable of const, i.e.
 BigInt(1) + const(BigInt)(1) does not work.

 Is there already an effort to fix this or would it make sense if I had
 taken some time to create a fix for it? I have no idea of all the asm in
 the x86 specialization but as const is an interface thing, I should be
 able to figure out everything without that knowledge. Or are there
 general design problems, such that this would be a waste of time?

 It's been prevented by some compiler bugs. The changes to pure in
 2.050 were triggered by attempts to make BigInt pure. 2.051 will
 include several fixes to nothrow.
You mean by making BigInt pure that all the computation-methods (like
opBinary, etc.) will be pure, right? Or can D structs be pure as well?
(Whatever this would mean...)


 Note that const is transitive (unlike C++), so it isn't just an
 interface thing.

That's clear. For +, I succeeded in making it const, but of course I
had to modify the biguintcore module, too.

So I guess that you will work on BigInt when 2.051 is out and patch it
to work with const and immutable, right? So I have a good chance to have
a fixed version in the next month(s)?!


Repairing BigInt const

2010-11-20 Thread Matthias Walter
Hi all,

as it seems, the current version of BigInt is not capable of const, i.e.
BigInt(1) + const(BigInt)(1) does not work.

Is there already an effort to fix this or would it make sense if I had
taken some time to create a fix for it? I have no idea of all the asm in
the x86 specialization but as const is an interface thing, I should be
able to figure out everything without that knowledge. Or are there
general design problems, such that this would be a waste of time?

Matthias


Current status of toString in phobos

2010-11-17 Thread Matthias Walter
Hi,

I'm currently using DMD v2.049 with phobos. I found an old discussion
about how toString should be designed and how it is supposed to work. As
the following code does not print out the number, I wonder what is the
current status of how to implement a toString function for a struct/class:

| auto n = BigInt(42);
| writefln(%s, n);

Thanks
Matthias


Re: A module comprehensive template-specialization

2010-06-28 Thread Matthias Walter
On 06/28/2010 05:32 AM, Simen kjaeraas wrote:
 Matthias Walter xa...@xammy.homelinux.net wrote:
 
 Can I handle this in another way (like making the template a conditional
 one)?
 
 Template constraints[1] sounds like what you want.
 
 Basically, you want the following:
 
 == Module a ==
 | module a;
 |
 | template Base (T) if (!is(T t : t*))
 | {
 |   alias T Base;
 | }
 
 == Module b ==
 | module b;
 |
 | import a;
 |
 | template Base(T) if (is(T t : t*))
 | {
 |   alias Base !(T) Base;
 | }
 
 == Main module ==
 |
 |  import a, b;
 |
 | int main(char[][] args)
 | {
 |   alias Base !(int*) foo;
 |
 |   return 0;
 | }
 
 Not tested, ymmv.
 
 [1]: http://digitalmars.com/d/2.0/template.html#Constraint
 

The problem with constraints arises when I want to make an existing
class (who's code I cannot modify) match a Concept, in which case I
would just add another template specialization for this class. Here I
would have to add further conditions to the template constraints, which
would also mean to modify a library. A prominent example for Boost Graph
Library is the LEDA graph class, which can be enabled to be used by BGL
by more or less just specializing the graph_traits template.

Any further ideas?


Re: A module comprehensive template-specialization

2010-06-28 Thread Matthias Walter
On 06/28/2010 09:49 AM, Justin Spahr-Summers wrote:
 On Sun, 27 Jun 2010 18:51:35 +0200, Matthias Walter 
 xa...@xammy.homelinux.net wrote:

 Hi list,

 I tried to write a traits class comparable to iterator_traits in C++ STL
 or graph_traits in Boost Graph Library in D 2.0, but failed to do so via
 template specialization which is put into different modules. Putting
 everything into one module interferes with extensibility. I tried the
 following:

 == Module a ==
 | module a;
 |
 | template Base (T)
 | {
 |   alias T Base;
 | }

 == Module b ==
 | module b;
 |
 | import a;
 |
 | template Base(T: T*)
 | {
 |   alias Base !(T) Base;
 | }

 == Main module ==
 |
 |  import a, b;
 |
 | int main(char[][] args)
 | {
 |   alias Base !(int*) foo;
 |
 |   return 0;
 | }

 The error message is:
 bug.d(8): Error: template instance ambiguous template declaration
 b.Base(T : T*) and a.Base(T)

 Can I handle this in another way (like making the template a conditional
 one)?

 best regards
 Matthias Walter
 
 I believe this is intended behavior, as it prevents template hijacking 
 and the like. Using alias to import the two templates into the same 
 scope might help, though I'm not sure exactly how it should be done.

I tried to do so in some variants but did not succeed unfortunately. If
you have a precise idea, please let me know!

 
 On another note, though, have you looked at __traits() and std.traits?

I looked at them but didn't find them helpful for this precise problem.
The whole reason for doing this is to make it possible to make another
existing class model the concept (i.e. have some aliases / typedefs
done) of my library class without editing any of them. As I mentioned in
my other response, a prominent example for Boost Graph
Library is the LEDA graph class, which can be enabled to be used by BGL
by more or less just specializing the graph_traits template. I'd like to
have this kind of technique available, too.

Any further suggestions?


A module comprehensive template-specialization

2010-06-27 Thread Matthias Walter
Hi list,

I tried to write a traits class comparable to iterator_traits in C++ STL
or graph_traits in Boost Graph Library in D 2.0, but failed to do so via
template specialization which is put into different modules. Putting
everything into one module interferes with extensibility. I tried the
following:

== Module a ==
| module a;
|
| template Base (T)
| {
|   alias T Base;
| }

== Module b ==
| module b;
|
| import a;
|
| template Base(T: T*)
| {
|   alias Base !(T) Base;
| }

== Main module ==
|
|  import a, b;
|
| int main(char[][] args)
| {
|   alias Base !(int*) foo;
|
|   return 0;
| }

The error message is:
bug.d(8): Error: template instance ambiguous template declaration
b.Base(T : T*) and a.Base(T)

Can I handle this in another way (like making the template a conditional
one)?

best regards
Matthias Walter