Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Michael

Hello all,
  I came across some weird behaviors yesterday and I can't figure 
out what it's about.


(1)
auto factorial(int n) {
if (n  2) return 1;
return n * factorial(n-1);
}

The compiler complained about forward declaration of factorial. 
If I change the return type to int, the problem goes away. I can 
understand that with the recursion, it might be impossible for 
the compiler to deduce the type of factorial and so it compile 
errors, but I don't see anything about that on the Language 
Reference. Is this the intended behavior?


(2)
auto stuff(T)(T[] arr) {
auto inner(T[] s) {
s[0] = 0;
}
arr.inner();
}
This time the compiler complained about 'inner' not being 
defined. This time I have no idea what is wrong.


Thanks for your help!
Michael


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Tobias Pankrath

On Wednesday, 27 June 2012 at 09:07:57 UTC, Michael wrote:

Hello all,
  I came across some weird behaviors yesterday and I can't 
figure out what it's about.


(1)
auto factorial(int n) {
if (n  2) return 1;
return n * factorial(n-1);
}

The compiler complained about forward declaration of 
factorial. If I change the return type to int, the problem 
goes away. I can understand that with the recursion, it might 
be impossible for the compiler to deduce the type of factorial 
and so it compile errors, but I don't see anything about that 
on the Language Reference. Is this the intended behavior?


(2)
auto stuff(T)(T[] arr) {
auto inner(T[] s) {
s[0] = 0;
}
arr.inner();
}
This time the compiler complained about 'inner' not being 
defined. This time I have no idea what is wrong.


Thanks for your help!
Michael


(1) is intended bahaviour, though I do think that the compiler 
could be smarter. At least the cases, that could be 
tail-call-optimize could also be inferred.


(2) looks like a bug to me



Removing from SList (std.container)...

2012-06-27 Thread Minas Mina

How can I do that?

Why not list.remove(x); like in STL?


Re: Removing from SList (std.container)...

2012-06-27 Thread Tobias Pankrath

On Wednesday, 27 June 2012 at 09:37:01 UTC, Minas Mina wrote:

How can I do that?

Why not list.remove(x); like in STL?


std.container encodes the complexity of operations in the method 
names. There is no way to remove a range in constant time in 
SList, so you only get linearRemove.


And you always need a range to remove something.


Re: Removing from SList (std.container)...

2012-06-27 Thread Minas Mina

On Wednesday, 27 June 2012 at 09:52:14 UTC, Tobias Pankrath wrote:

On Wednesday, 27 June 2012 at 09:37:01 UTC, Minas Mina wrote:

How can I do that?

Why not list.remove(x); like in STL?


std.container encodes the complexity of operations in the 
method names. There is no way to remove a range in constant 
time in SList, so you only get linearRemove.


And you always need a range to remove something.


Can you show me an example or removing a number?


Re: Removing from SList (std.container)...

2012-06-27 Thread Tobias Pankrath

Can you show me an example or removing a number?


I think that is a prime example of why std.container sucks both 
in documentation and implemantation.


We really need to improve here, sadly development seems to be 
bottlenecked by Andrei working on on allocator proposal. And 
Andrei is busy at the moment.


Here is the solution. You actually need 4 different modules from 
phobos to do this and it is absolutely not obvious how to do it.


import std.algorithm;
import std.range;
import std.container;
import std.array;

void main(string[] args)
{
SList!int list = [1,2,3,4,5]; // our list
writeln(list.array()); // need to create an array to print 
nicely
auto pos = find(list[], 4); // we need a range, so we search 
for the number
auto pos2 = take(pos, 1); // but find returns a range over 
the rest, so take one

list.linearRemove(pos2); // remove it
writeln(list.array()); // print it
}


I needed to look it up myself and didn't find a solution on first 
try.


My first error: You can't just do find(list, 4), because an SList 
is not a range by itself. So you need opSlice (list[]) to get a 
range over list.


Then I knew already that find gives me not what I want. I somehow 
need to restrict the range pos to the first element. But how to 
do it? I wouldn't expect  a newcomer to come up with a solution 
on its own, because pos[0..1] will not work on a forward range. 
Luckily I knew std.range.takeOne.


But hold! takeOne(pos) does not work, you need take(pos, 1).

That sucks.

None of the above is stated explicitly in the documentation. I 
knew that the container generally need a range that was extracted 
from them. How should I know that in this special case a range 
from std.range will work, too? And not all ranges work, only the 
one from take.













Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Timon Gehr

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
   I came across some weird behaviors yesterday and I can't figure out
what it's about.

(1)
auto factorial(int n) {
 if (n  2) return 1;
 return n * factorial(n-1);
}

The compiler complained about forward declaration of factorial. If I
change the return type to int, the problem goes away. I can understand
that with the recursion, it might be impossible for the compiler to
deduce the type of factorial and so it compile errors, but I don't see
anything about that on the Language Reference. Is this the intended
behavior?



Apparently the compiler attempts to type combine the types of the
return statements. This does not match the language documentation. I
think it should just use the type of the first return statement.


(2)
auto stuff(T)(T[] arr) {
 auto inner(T[] s) {
 s[0] = 0;
 }
 arr.inner();
}
This time the compiler complained about 'inner' not being defined. This
time I have no idea what is wrong.

Thanks for your help!
Michael



This is expected behaviour. UFCS only works with module scope functions.


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Timon Gehr

On 06/27/2012 01:24 PM, Timon Gehr wrote:

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
   I came across some weird behaviors yesterday and I can't figure out
what it's about.

(1)
auto factorial(int n) {
 if (n  2) return 1;
 return n * factorial(n-1);
}

The compiler complained about forward declaration of factorial. If I
change the return type to int, the problem goes away. I can understand
that with the recursion, it might be impossible for the compiler to
deduce the type of factorial and so it compile errors, but I don't see
anything about that on the Language Reference. Is this the intended
behavior?



Apparently the compiler attempts to type combine the types of the
return statements. This does not match the language documentation. I
think it should just use the type of the first return statement.
...


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


Re: Removing from SList (std.container)...

2012-06-27 Thread Minas Mina

Thank you for your reply. Yes, std.container really sucks.

Anyway, I made my program using C++ and STL


Re: Removing from SList (std.container)...

2012-06-27 Thread Steven Schveighoffer
On Wed, 27 Jun 2012 05:37:00 -0400, Minas Mina  
minas_mina1...@hotmail.co.uk wrote:



How can I do that?

Why not list.remove(x); like in STL?


SList is quite unusable.

If you are looking for STL-like containers, there is dcollections which  
has a doubly-linked list, and supports syntax like you want.


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

-Steve


Re: Removing from SList (std.container)...

2012-06-27 Thread Jonathan M Davis
On Wednesday, June 27, 2012 08:25:04 Steven Schveighoffer wrote:
 On Wed, 27 Jun 2012 05:37:00 -0400, Minas Mina
 
 minas_mina1...@hotmail.co.uk wrote:
  How can I do that?
  
  Why not list.remove(x); like in STL?
 
 SList is quite unusable.
 
 If you are looking for STL-like containers, there is dcollections which
 has a doubly-linked list, and supports syntax like you want.
 
 http://www.dsource.org/projects/dcollections

There concept of SList is unusable IMHO. The singly-linked list is one of the 
most useless data structures ever invented. It does have some use cases, but 
almost always what you really want is doubly-linked list.

As for std.container, the basics of std.container are good, but the 
documentation isn't good enough for some basic stuff, and some of it needs to 
be ironed out a bit. For instance, the basic idea of how remove works is fine 
given how ranges work (though it's arguably one of those few places where 
ranges are worse than iterators - hence why dcollections has cursors), and 
it's exactly what you want in the general case, but it's arguably overly 
complicated for a lot of basic use cases. Adding stuff like removeFirst which 
removed the first value which matched would greatly simplify a number of basic 
use cases.

I've been meaning to figure out a small set of basic functions like that which 
would improve the API's usability for many common cases and propose them, but 
there hasn't been much point in trying to do anything with it, since that sort 
of thing needs to get passed Andrei (who is likely to say that the current 
solution with find and take is just fine, since it's nicely generic and covers 
all use cases), but he's been busy.

- Jonathan M Davis


Re: Removing from SList (std.container)...

2012-06-27 Thread Steven Schveighoffer
On Wed, 27 Jun 2012 13:44:34 -0400, Jonathan M Davis jmdavisp...@gmx.com  
wrote:



On Wednesday, June 27, 2012 08:25:04 Steven Schveighoffer wrote:

On Wed, 27 Jun 2012 05:37:00 -0400, Minas Mina

minas_mina1...@hotmail.co.uk wrote:
 How can I do that?

 Why not list.remove(x); like in STL?

SList is quite unusable.

If you are looking for STL-like containers, there is dcollections which
has a doubly-linked list, and supports syntax like you want.

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


There concept of SList is unusable IMHO. The singly-linked list is one  
of the
most useless data structures ever invented. It does have some use cases,  
but

almost always what you really want is doubly-linked list.


The thing that makes SList useless is the O(n) removal.  Nobody will ever  
use SList when they can write a replacement that has O(1) removal in 10  
minutes.


The concept of singly-linked lists is most certainly not useless.  They  
are perfect for FIFO queues, or LIFO stacks, and they consume 1/3 less  
space than a doubly-linked list (at least for an int/size_t)


My somewhat loose belief is that making a generic singly-linked list is a  
waste of time -- it's too difficult to implement in a way that is  
optimized for the intended use.



As for std.container, the basics of std.container are good, but the
documentation isn't good enough for some basic stuff, and some of it  
needs to
be ironed out a bit. For instance, the basic idea of how remove works is  
fine

given how ranges work (though it's arguably one of those few places where
ranges are worse than iterators - hence why dcollections has cursors),  
and

it's exactly what you want in the general case, but it's arguably overly
complicated for a lot of basic use cases. Adding stuff like removeFirst  
which
removed the first value which matched would greatly simplify a number of  
basic

use cases.


I haven't used std.container all that much, but I find the terminology  
very obtuse and verbose.  I can't imagine every using for example  
upperBound without having to look up what it does.


I understand the point, but it needs shortcuts.  Like how you can type  
writeln(x) instead of stdout.writeln(x).  I think that's a small  
difference that is a huge win.


But regardless, any API improvements pale in comparison to the O(n)  
removal problem for SList.


I've been meaning to figure out a small set of basic functions like that  
which
would improve the API's usability for many common cases and propose  
them, but
there hasn't been much point in trying to do anything with it, since  
that sort
of thing needs to get passed Andrei (who is likely to say that the  
current
solution with find and take is just fine, since it's nicely generic and  
covers

all use cases), but he's been busy.


It doesn't hurt to propose...  Personally, I don't see myself ever using  
std.container when I prefer the API of dcollections.  But that obviously  
isn't going to be the popular choice, since it's not in phobos.


-Steve


Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko
On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer 
wrote:
The thing that makes SList useless is the O(n) removal.  Nobody 
will ever use SList when they can write a replacement that has 
O(1) removal in 10 minutes.
Do you mean something like indexed/sorted dictionary? It doesn't 
seem to be that easy to implement. Or some other data structure 
with O(1) removal?


Re: Removing from SList (std.container)...

2012-06-27 Thread Timon Gehr

On 06/27/2012 08:46 PM, Roman D. Boiko wrote:

On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote:

The thing that makes SList useless is the O(n) removal. Nobody will
ever use SList when they can write a replacement that has O(1) removal
in 10 minutes.

Do you mean something like indexed/sorted dictionary? It doesn't seem to
be that easy to implement. Or some other data structure with O(1) removal?


O(1) removal works quite ok for a singly linked list. eg:

1.
- Add a sentinel node to the start of your list.
- Represent an iterator into the list as a pointer to the predecessor
  of the respective node.
- Removal: trivial. rebind the 'next' reference of the pointed-to node.

2.
- Represent the empty list as a sentinel node with null 'next' field.
- For removal of a node you own a pointer to:
 -- case 1: the successor is an empty list:
- destroy the value, set the 'next' reference to null.
 -- case 2: else:
- move the successor's value into the node that holds the value to
  be removed, bind the 'next' reference to the successor of the
  successor.


Re: Removing from SList (std.container)...

2012-06-27 Thread Steven Schveighoffer

On Wed, 27 Jun 2012 14:46:36 -0400, Roman D. Boiko r...@d-coding.com wrote:


On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote:
The thing that makes SList useless is the O(n) removal.  Nobody will  
ever use SList when they can write a replacement that has O(1) removal  
in 10 minutes.
Do you mean something like indexed/sorted dictionary? It doesn't seem to  
be that easy to implement. Or some other data structure with O(1)  
removal?


struct Link
{
  int val;
  Link *next;
  removeNext() {assert(next); next = next.next;}
}

O(1) removal, easy as that.

Look up SList docs, even with a reference to a *specific element*, you  
cannot do O(1) removal.


Only recently did it add O(1) insertion, but only after a specific  
element.  Good luck implementing a way to do insert *before* that element  
in O(1), it will be possible, but really obtuse.


-Steve


Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko
On Wednesday, 27 June 2012 at 19:10:24 UTC, Steven Schveighoffer 
wrote:
On Wed, 27 Jun 2012 14:46:36 -0400, Roman D. Boiko 
r...@d-coding.com wrote:


On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven 
Schveighoffer wrote:
The thing that makes SList useless is the O(n) removal.  
Nobody will ever use SList when they can write a replacement 
that has O(1) removal in 10 minutes.
Do you mean something like indexed/sorted dictionary? It 
doesn't seem to be that easy to implement. Or some other data 
structure with O(1) removal?


struct Link
{
  int val;
  Link *next;
  removeNext() {assert(next); next = next.next;}
}

O(1) removal, easy as that.
I thought you meant removal by index or value, not element 
reference.


Look up SList docs, even with a reference to a *specific 
element*, you cannot do O(1) removal.

Ha-ha, didn't know SList doesn't support that.



Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko

On Wednesday, 27 June 2012 at 19:55:02 UTC, Roman D. Boiko wrote:
Look up SList docs, even with a reference to a *specific 
element*, you cannot do O(1) removal.

Ha-ha, didn't know SList doesn't support that.
I somehow confused removal after a referenced element (which 
should be easy to implement, but not very useful) with removal of 
that element (which is not possible in 0(1) in a singly-linked 
list.


Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko

On Wednesday, 27 June 2012 at 19:06:46 UTC, Timon Gehr wrote:

On 06/27/2012 08:46 PM, Roman D. Boiko wrote:
On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven 
Schveighoffer wrote:
The thing that makes SList useless is the O(n) removal. 
Nobody will
ever use SList when they can write a replacement that has 
O(1) removal

in 10 minutes.
Do you mean something like indexed/sorted dictionary? It 
doesn't seem to
be that easy to implement. Or some other data structure with 
O(1) removal?


O(1) removal works quite ok for a singly linked list. eg:

1.
- Add a sentinel node to the start of your list.
- Represent an iterator into the list as a pointer to the 
predecessor

  of the respective node.
- Removal: trivial. rebind the 'next' reference of the 
pointed-to node.


2.
- Represent the empty list as a sentinel node with null 'next' 
field.

- For removal of a node you own a pointer to:
 -- case 1: the successor is an empty list:
- destroy the value, set the 'next' reference to null.
 -- case 2: else:
- move the successor's value into the node that holds the 
value to
  be removed, bind the 'next' reference to the successor of 
the

  successor.

Nice. But forces to use iterators everywhere.



Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko

On Wednesday, 27 June 2012 at 20:00:18 UTC, Roman D. Boiko wrote:

Nice. But forces to use iterators everywhere.
(I'm not against iterators, they are almost necessary in certain 
use cases, like this one.)


Re: Removing from SList (std.container)...

2012-06-27 Thread Steven Schveighoffer

On Wed, 27 Jun 2012 15:57:42 -0400, Roman D. Boiko r...@d-coding.com wrote:


On Wednesday, 27 June 2012 at 19:55:02 UTC, Roman D. Boiko wrote:
Look up SList docs, even with a reference to a *specific element*, you  
cannot do O(1) removal.

Ha-ha, didn't know SList doesn't support that.
I somehow confused removal after a referenced element (which should be  
easy to implement, but not very useful) with removal of that element  
(which is not possible in 0(1) in a singly-linked list.


Removal of that element is perfectly possible, you just need to maintain a  
reference to its predecessor.  Which SList's range does not keep track  
of.  It all depends on tradeoffs of what you want for performance, vs.  
features.  It's why I contend that generic singly linked list is difficult  
to create.  Can't please everyone.


And iterators are not necessary, ranges are quite possible.

-Steve


Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko
On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven Schveighoffer 
wrote:
Removal of that element is perfectly possible, you just need to 
maintain a reference to its predecessor.  Which SList's range 
does not keep track of.  It all depends on tradeoffs of what 
you want for performance, vs. features.  It's why I contend 
that generic singly linked list is difficult to create.  Can't 
please everyone.


Yes, I agree.


And iterators are not necessary, ranges are quite possible.


In this respect it is not only a performance vs. features 
tradeoff, semantics is (usually) different. Of course, we might 
use a range for what is semantically an iterator. But it feels 
unnatural for me.


E.g., to point to an element in the middle of some range we would 
need to create another range and pass it to a function along with 
the original range. I would hesitate to call them ranges unless 
that is explicitly a goal for some particular application. If 
that was the case, it would require an explicit explanation. (IMO)


Re: Removing from SList (std.container)...

2012-06-27 Thread Tobias Pankrath

On Wednesday, 27 June 2012 at 20:29:02 UTC, Roman D. Boiko wrote:
On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven 
Schveighoffer wrote:
Removal of that element is perfectly possible, you just need 
to maintain a reference to its predecessor.  Which SList's 
range does not keep track of.  It all depends on tradeoffs of 
what you want for performance, vs. features.  It's why I 
contend that generic singly linked list is difficult to 
create.  Can't please everyone.


Yes, I agree.


And iterators are not necessary, ranges are quite possible.


In this respect it is not only a performance vs. features 
tradeoff, semantics is (usually) different. Of course, we might 
use a range for what is semantically an iterator. But it feels 
unnatural for me.


E.g., to point to an element in the middle of some range we 
would need to create another range and pass it to a function 
along with the original range. I would hesitate to call them 
ranges unless that is explicitly a goal for some particular 
application. If that was the case, it would require an explicit 
explanation. (IMO)


Why pass the original range?


Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko

On Wednesday, 27 June 2012 at 21:22:31 UTC, Tobias Pankrath wrote:
E.g., to point to an element in the middle of some range we 
would need to create another range and pass it to a function 
along with the original range. I would hesitate to call them 
ranges unless that is explicitly a goal for some particular 
application. If that was the case, it would require an 
explicit explanation. (IMO)


Why pass the original range?


I mean the range on which to perform an operation. It could be 
passed via this parameter of member function or explicitly. It 
could be not needed for some operations (trivial, like copy or 
compare).


Re: Removing from SList (std.container)...

2012-06-27 Thread Jonathan M Davis
On Wednesday, June 27, 2012 22:29:01 Roman D. Boiko wrote:
 On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven Schveighoffer
 
 wrote:
  Removal of that element is perfectly possible, you just need to
  maintain a reference to its predecessor. Which SList's range
  does not keep track of. It all depends on tradeoffs of what
  you want for performance, vs. features. It's why I contend
  that generic singly linked list is difficult to create. Can't
  please everyone.
 
 Yes, I agree.
 
  And iterators are not necessary, ranges are quite possible.
 
 In this respect it is not only a performance vs. features
 tradeoff, semantics is (usually) different. Of course, we might
 use a range for what is semantically an iterator. But it feels
 unnatural for me.
 
 E.g., to point to an element in the middle of some range we would
 need to create another range and pass it to a function along with
 the original range. I would hesitate to call them ranges unless
 that is explicitly a goal for some particular application. If
 that was the case, it would require an explicit explanation. (IMO)

If you want a single element, then use take, takeExactly, or takeOne. For 
instance, that's what you do when you want to use remove in std.container 
(though apparently takeOne was missed as pointed out earlier in this thread, 
which needs to be remedied). It is true that dealing with ranges in this sort 
of situation is a bit more problematic than it is with iterators, but the 
take* functions take care of it as long as the container properly takes them 
into account (which std.container's containers are supposed to do). And if all 
you care about is having a range with one element and not whether the range is 
passable to a function on it's associated container, then the take* functions 
work just fine regardless of whether the container properly takes them into 
account. It's only an issue with the container, because the container needs 
its original range type rather than some arbitrary range which may have 
nothing to do with that container (the same happens with iterators - you just 
don't tend to wrap them in other types in the same way that happens with 
ranges).

- Jonathan M Davis


Re: Removing from SList (std.container)...

2012-06-27 Thread Roman D. Boiko
On Wednesday, 27 June 2012 at 21:38:28 UTC, Jonathan M Davis 
wrote:

On Wednesday, June 27, 2012 22:29:01 Roman D. Boiko wrote:
On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven 
Schveighoffer


wrote:
 Removal of that element is perfectly possible, you just need 
 to

 maintain a reference to its predecessor. Which SList's range
 does not keep track of. It all depends on tradeoffs of what
 you want for performance, vs. features. It's why I contend
 that generic singly linked list is difficult to create. Can't
 please everyone.

Yes, I agree.

 And iterators are not necessary, ranges are quite possible.

In this respect it is not only a performance vs. features
tradeoff, semantics is (usually) different. Of course, we might
use a range for what is semantically an iterator. But it feels
unnatural for me.

E.g., to point to an element in the middle of some range we 
would
need to create another range and pass it to a function along 
with

the original range. I would hesitate to call them ranges unless
that is explicitly a goal for some particular application. If
that was the case, it would require an explicit explanation. 
(IMO)


If you want a single element, then use take, takeExactly, or 
takeOne. For
instance, that's what you do when you want to use remove in 
std.container
(though apparently takeOne was missed as pointed out earlier in 
this thread,
which needs to be remedied). It is true that dealing with 
ranges in this sort
of situation is a bit more problematic than it is with 
iterators, but the
take* functions take care of it as long as the container 
properly takes them
into account (which std.container's containers are supposed to 
do). And if all
you care about is having a range with one element and not 
whether the range is
passable to a function on it's associated container, then the 
take* functions
work just fine regardless of whether the container properly 
takes them into
account. It's only an issue with the container, because the 
container needs
its original range type rather than some arbitrary range which 
may have
nothing to do with that container (the same happens with 
iterators - you just
don't tend to wrap them in other types in the same way that 
happens with

ranges).

- Jonathan M Davis


It depends entirely on intended semantics and use cases. There is 
a difference between a range, an iterator, and a link (pointer) 
to some container node. I meant a link when I used the term 
iterator.


To illustrate, imagine a tree container. A link could point to 
some node, which could be used conceptually as a container. A 
range would define a subset of either element values or links for 
some traversal. So a range semantically implies an ordering, and 
is quite different from a link. An iterator seems to be closer to 
a range in this respect, that's why I admitted that I used the 
term incorrectly.


Re: Removing from SList (std.container)...

2012-06-27 Thread Minas Mina

Doesn't Andrei plan to do something about this module?


Concurrency in D

2012-06-27 Thread Minas Mina
I have been playing latetly with std.concurrency and 
core.thread. I like both, but they are entirely different 
approaches to concurrency.


std.concurrency: Uses message passing. Does not allow passing of 
mutable types.

core.thread: Essentially the same as the approach taken by Java.

1) Is one favoured over the other? I guess std.concurrency would 
be, because it uses messages (and I recently read somewhere that 
immutability + message passing = good thing). Well, my problem 
about is, how can send mutable data to another thread? _Can_ I do 
it? If not, how am I supposed to share data between them? Not 
everything can be immutable right? For example I would like to 
have a thread calculate the sum of the first half of an array 
while another thread would calculate the other half, and I could 
add the two results at the end.


2) What about core.thread? To do proper sync between threads in 
core.thread, semaphore, mutexes and stuff like that are needed. 
Are those good practice in D?


3) I have also read a bit about syncronized classes and shared 
classes/structs, altough I didn't understand it too much (well I 
didn't try too much to be honest).


For all those appoaches, which is the preffered?
For all those appoaches, which is the preffered for game 
programming?


Thank you.



Re: Concurrency in D

2012-06-27 Thread Adam Burton
Minas Mina wrote:

 I have been playing latetly with std.concurrency and
 core.thread. I like both, but they are entirely different
 approaches to concurrency.
 
 std.concurrency: Uses message passing. Does not allow passing of
 mutable types.
 core.thread: Essentially the same as the approach taken by Java.
 
 1) Is one favoured over the other? I guess std.concurrency would
 be, because it uses messages (and I recently read somewhere that
 immutability + message passing = good thing).
I've not really got around to doing any concurrent programming in anger with 
D yet but from what I've read message passing is the preferred method. 
Fortunately when it comes to answering your question the concurrency chapter 
for The D Programming Language book (TDPL) was made freely available as a 
preview http://www.informit.com/articles/article.aspx?p=1609144. Hopefully 
that contains your answers :).

 Well, my problem
 about is, how can send mutable data to another thread? _Can_ I do
 it? If not, how am I supposed to share data between them? Not
 everything can be immutable right?
From what I gather this is where the shared keyword typically comes into 
play which should be detailed in the url above.

 For example I would like to
 have a thread calculate the sum of the first half of an array
 while another thread would calculate the other half, and I could
 add the two results at the end.
For this task there is another concurrency module called std.parallelism 
that is designed for this type of thing (afaik). 
http://dlang.org/phobos/std_parallelism.html

 
 2) What about core.thread? To do proper sync between threads in
 core.thread, semaphore, mutexes and stuff like that are needed.
 Are those good practice in D?
 
 3) I have also read a bit about syncronized classes and shared
 classes/structs, altough I didn't understand it too much (well I
 didn't try too much to be honest).
 
 For all those appoaches, which is the preffered?
My observation is std.concurrency is being pushed as the preferred default 
method.
 For all those appoaches, which is the preffered for game
 programming?
 
 Thank you.


Re: Concurrency in D

2012-06-27 Thread Justin Whear
On Thu, 28 Jun 2012 00:34:50 +0200, Minas Mina wrote:

 I have been playing latetly with std.concurrency and core.thread. I
 like both, but they are entirely different approaches to concurrency.
 
 std.concurrency: Uses message passing. Does not allow passing of mutable
 types.
 core.thread: Essentially the same as the approach taken by Java.
 
 1) Is one favoured over the other? I guess std.concurrency would be,
 because it uses messages (and I recently read somewhere that
 immutability + message passing = good thing). Well, my problem about is,
 how can send mutable data to another thread? _Can_ I do it? If not, how
 am I supposed to share data between them? Not everything can be
 immutable right? For example I would like to have a thread calculate the
 sum of the first half of an array while another thread would calculate
 the other half, and I could add the two results at the end.
 
 2) What about core.thread? To do proper sync between threads in
 core.thread, semaphore, mutexes and stuff like that are needed. Are
 those good practice in D?
 
 3) I have also read a bit about syncronized classes and shared
 classes/structs, altough I didn't understand it too much (well I didn't
 try too much to be honest).
 
 For all those appoaches, which is the preffered?
 For all those appoaches, which is the preffered for game programming?
 
 Thank you.

Concurrency and parallelism are two related, but different concepts. 
Concurrency is when you have different computations conducted 
simultaneously. An example is a modern game engine: you may have a 
rendering thread, a physics simulation, and a networking stack all 
operating at the same time on different cores. Concurrency allows (and 
generally assumes) communication between these parts as they need to 
share information. Message-passing is, as far as I know, pretty much the 
only truly correct way of doing this.

Parallelism is, by contrast, the decomposing of a computation into 
smaller chunks which do not depend on each other. A trivial example is 
incrementing all integers in an array by one--the result of the increment 
computation only relies on the integer being worked on, so the 
computations may be performed in parallel and the results collected.

The std.concurrency and std.parallelism thus exist to solve two different 
problems and are more of an apples-oranges situation.

Justin


Re: Concurrency in D

2012-06-27 Thread Nathan M. Swan

On Wednesday, 27 June 2012 at 22:34:51 UTC, Minas Mina wrote:
I have been playing latetly with std.concurrency and 
core.thread. I like both, but they are entirely different 
approaches to concurrency.




Aren't they great? ;)

std.concurrency: Uses message passing. Does not allow passing 
of mutable types.

core.thread: Essentially the same as the approach taken by Java.

1) Is one favoured over the other? I guess std.concurrency 
would be, because it uses messages (and I recently read 
somewhere that immutability + message passing = good thing).


Personally I favor std.concurrency, in many cases I find it 
faster.


Well, my problem about is, how can send mutable data to another 
thread? _Can_ I do it? If not, how am I supposed to share data 
between them? Not everything can be immutable right?


Mutable value types can be sent easily, because they are copied. 
You share data with shared(T) types, e.g. shared(Object) or 
shared(int[]).


However, I try to avoid shared data by keeping it in single 
threads, and having other threads access parts with message 
passing.


One paradigm is to isolate data into thread objects, threads 
which have non-shared data on the stack, and have other threads 
send GetData messages and get ReturnedData messages.


For example I would like to have a thread calculate the sum of 
the first half of an array while another thread would calculate 
the other half, and I could add the two results at the end.




Check out this:
http://dpaste.dzfl.pl/0f7ccb79

Note that for algorithms like this, you should check out 
std.parallelism, it's more high-level than std.concurrency.


2) What about core.thread? To do proper sync between threads in 
core.thread, semaphore, mutexes and stuff like that are needed. 
Are those good practice in D?




Part of D's philosophy is you can get low-level and dirty if you 
want, but the easy/safe way should also be the fast way. 
core.thread is there for you, but std.concurrency is easier. Note 
that std.concurrency is written on top of core.thread.


I definitely prefer std.concurrency, but I don't write 
CPU-intensive stuff anyway, so I'm no expert.


3) I have also read a bit about syncronized classes and shared 
classes/structs, altough I didn't understand it too much (well 
I didn't try too much to be honest).




Objects of a synchronized class automatically lock/unlock every 
method call.


You don't share stack structs, though maybe shared(StructType)*.


For all those appoaches, which is the preffered?
For all those appoaches, which is the preffered for game 
programming?


Thank you.


Hope I've helped.
NMS


Re: Concurrency in D

2012-06-27 Thread Ali Çehreli

On 06/27/2012 04:05 PM, Adam Burton wrote:

 For example I would like to
 have a thread calculate the sum of the first half of an array
 while another thread would calculate the other half, and I could
 add the two results at the end.
 For this task there is another concurrency module called std.parallelism
 that is designed for this type of thing (afaik).
 http://dlang.org/phobos/std_parallelism.html

TDPL predates std.parallelism, so it's not in the book. Although the 
module's documentation is straightforward, I have the following page 
which may be more accessible for some:


  http://ddili.org/ders/d.en/parallelism.html

Clicking [Next] on that pages goes to Message Passing Concurrency:

  http://ddili.org/ders/d.en/concurrency.html

Ali

P.S. Both of those pages are incomplete in some ways, which I will 
address soon.




Re: Concurrency in D

2012-06-27 Thread Minas Mina

You all helped, thank you :)

I will read the concurrency part tomorrow!


Re: Removing from SList (std.container)...

2012-06-27 Thread Jonathan M Davis
On Thursday, June 28, 2012 00:23:03 Minas Mina wrote:
 Doesn't Andrei plan to do something about this module?

He came up with the basic design, and he's working on the custom allocator 
design. Once that's been sorted out, std.container will be made to use it, and 
more containers will be added to it. We're trying to avoid having to implement 
the containers twice (as would happen to at least some extent if we added them 
all and then added the custom allocators later), which is why there aren't 
more of them yet. But Andrei has been very busy, so progress has been slow, 
and I don't know where he stands with it right now.

- Jonathan M Davis


Re: Stack overflow / recursive expansion with alias this

2012-06-27 Thread Kenji Hara

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

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

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

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




Yes.


I found nothing like that. Is the bug reported?


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


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


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

Bye.

Kenji Hara


Re: implicit conversion to alias this

2012-06-27 Thread BLM768

On Monday, 25 June 2012 at 20:06:21 UTC, Tobias Pankrath wrote:

-
struct A { bool a; alias a this; }
struct B { int b; alias b this; }

A a = false; // works
B b = 12; // works

struct C
{
A aa;
B ab;
}

C c = { false, 12 }; // does not work, because the implicit 
conversion does not happen.

-

What is the reason to allow the first two assignments? Isn't it 
just another implicit conversion that shouldn't be allowed?


The compiler isn't smart enough to realize that you're trying 
to use an implicit conversion. It's only told to expect the 
conversion in certain situations, such as assignment, and getting 
it to work for rarer cases would involve patching it with more 
special-case code.  The initializer is also expecting struct 
_values_; I don't think that you could call a function that wants 
an A and give it a bool, either. Making a struct value from an 
expression and initializing a struct in a definition are subtly 
different and follow different codepaths in the compiler.


Re: implicit conversion to alias this

2012-06-27 Thread Tobias Pankrath

On Thursday, 28 June 2012 at 04:43:07 UTC, BLM768 wrote:

On Monday, 25 June 2012 at 20:06:21 UTC, Tobias Pankrath wrote:

-
struct A { bool a; alias a this; }
struct B { int b; alias b this; }

A a = false; // works
B b = 12; // works

struct C
{
   A aa;
   B ab;
}

C c = { false, 12 }; // does not work, because the implicit 
conversion does not happen.

-

What is the reason to allow the first two assignments? Isn't 
it just another implicit conversion that shouldn't be allowed?


The compiler isn't smart enough to realize that you're trying 
to use an implicit conversion. It's only told to expect the 
conversion in certain situations, such as assignment, and 
getting it to work for rarer cases would involve patching it 
with more special-case code.  The initializer is also expecting 
struct _values_; I don't think that you could call a function 
that wants an A and give it a bool, either. Making a struct 
value from an expression and initializing a struct in a 
definition are subtly different and follow different codepaths 
in the compiler.


I'm fine that the assignment to C is verboten. I'd disallow the 
first assignments to and would like to know, why they are kept.