Re: Const ref and rvalues again...

2012-11-05 Thread Jonathan M Davis
On Monday, November 05, 2012 06:05:07 Rob T wrote:
> On Monday, 5 November 2012 at 03:26:10 UTC, Jonathan M Davis
> 
> wrote:
> > And when we argued for altering it so that it operated like
> > const ref in C++
> > (which allows const ref in D to continue to function like it
> > does now), some
> > folks complained, because they've found the current semantics
> > of auto ref to
> > be useful (something to do with propagating the exact, original
> > type, I
> > think).
> 
> I would expect that auto ref for a template and for a non
> template should work in exactly the same way, so why would there
> be a difference? If there must be a difference, there should be
> different semantics for specifying the difference, otherwise the
> inconsistent behaviours among identical semantics will only serve
> to confuse people.

auto ref's current semantics can't possibly work with non-templated functions, 
and it's clear that there are good reasons for keeping auto ref as it is now 
for templates. So, either we make it work with non-templated functions with 
different (albeit similar) semantics, or we need a new attribute for doing what 
we want to do with non-templated functions.

- Jonathan M Davis


Re: 'with' bug?

2012-11-05 Thread Faux Amis

On 05/11/2012 01:45, Chris Cain wrote:

On Sunday, 4 November 2012 at 23:51:15 UTC, Faux Amis wrote:

In your last paragraph you are getting to my point in my other post:
I think there is nothing wrong with a module scope private var as in D
a module is the first encapsulation and adding a wrapper only adds noise.

These are equivalent(from a good-coding pov):
---
module a;

private int i;
---
module b;

// annoying wrapper
//which makes it difficult to have a single b in the program
struct S{
 int i;
}
---

These are also equivalent:
---
module a;

int i;
---
module b;

struct S{
 static int i;
}
---


Like I said, I don't think it's something that should be banned
outright, but I've seen many examples of code where someone didn't take
the time to be explicit about the dependencies in their code and instead
chose to "hide" it like you propose is appropriate. Trust me, as the
person who has to maintain and extend their code, **I don't appreciate
their laziness**.

If you can, you should avoid such things. Module-scoped variables
mitigate the problems, but they don't eliminate them.

Also, bearophile's suggestion to try to make everything "pure" is a good
idea. I write as much code as I can using immutable and pure and only
relax those restrictions when the cost is far too great to maintain
that. When I come back to the code later, I find it significantly easier
to figure out for many of the reasons I outlined in my previous post.

---
void bar(ref int b) {
 //code using b
}
---

Is generally better than

---
int b;
void bar() {
 // code using b
}
---

Even if b is only private module scoped. I've outlined the reasons why
in my previous post.

On Sunday, 4 November 2012 at 23:58:08 UTC, bearophile wrote:

Generally it's better to minimize the scope of variables.


Quoted for truth.

Heck, I've seen examples of code where instance variables were too
liberally applied, like so:

---
struct S {
int b;
void bar() {
   // b is initialized and used in this scope, but no where else
}

// more code where b isn't used
}
---

is worse than:

---
struct S {
void bar() {
int b = ...;
// use b
}

// more code
}
---

Now, maybe b used to be used elsewhere, (I can't say for sure...) but
sometimes I wonder why people are so willing to let things like that
leak out of the scope where it's used... it makes the next person's job
much harder for no reason.


Ok, good to see that you are replying to incorrectly scoped variables, 
but this is not the point I am trying to make. I know you should always 
keep the scope as small as possible.


Can you think of a setting in which we have legitimate private struct 
members? If so, then add to this setting that you only want one 
instantiation of the data in this struct. As a solution, what is wrong 
with dropping the struct encapsulation? There is no other code except 
the struct in the module.


I sincerely want to know if there is any difference. As I understand it 
the scope is exactly the same or even smaller as you can't leak 
instances of modules as you can structs.





Re: version(deprecated)?

2012-11-05 Thread Johannes Pfau
Am Sun, 04 Nov 2012 16:48:26 +0100
schrieb "monarch_dodra" :

> I'm wondering if there is a way to know you are in deprecated 
> mode or not?
> 
> The deprecated attribute is great, because it gives a clear 
> compile error (as opposed to a static if, which just hides the 
> function completely).
> 
> But the attribute alone is not enough: I have a class with a 
> deprecated method, which consumes a book-keeping attribute: Not 
> only will this attribute exist even though it has become useless, 
> but the other functions will keep updating this attribute, even 
> though it has no more consumers.
> 
> What's more, I'd still want to unittest that function, but 
> obviously, only when compiled in "-unittest -d".
> 
> So I have a problem.
> 
> 
> Finding out if the compilation mode is deprecated is easy enough:
> 
> //
> deprecated @property void deprecateExists(){}
> enum deprecatedActive = is(typeof(deprecateExists));
> //
> 
> The thing is it's kind of dirty, and I wouldn't want to have to 
> copy paste this in all of my modules, just to know whether or not 
> deprecation is active...
> 
> 
> 
> We've currently implemented "version(assert)" and 
> "version(debug)". Do you think we should request having a 
> "version(deprecated)"? I think it would be very helpful. Thoughts?
> 
> 

As deprecated now allows optional messages some folks have suggested to
make deprecated behave like in other languages: Warn if something
deprecated is used, do not print warnings if compiling with
-deprecated.
This would conflict with your proposed usage of version(deprecated).


Re: Why does std.variant not have a tag?

2012-11-05 Thread Johannes Pfau
Am Mon, 05 Nov 2012 07:33:47 +0100
schrieb "Robert Jacques" :

> On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen
> wrote:
> > On 05-11-2012 00:31, evansl wrote:
> >>   http://dlang.org/phobos/std_variant.html
> >>
> >> says:
> >>
> >>  This module implements a discriminated union type (a.k.a. 
> >> tagged union,
> >> algebraic type).
> >>
> >> Yet, the wiki page:
> >>
> >>   http://en.wikipedia.org/wiki/Tagged_union
> >>
> >> says:
> >>
> >>   a tag field explicitly indicates which one is in use.
> >>
> >> and I don't see any indication of a tag field in the 
> >> std_variant.html
> >> page.  Another wiki reference:
> >>
> >>   http://en.wikipedia.org/wiki/Disjoint_union
> >>
> >> is more explicit because it pairs the tag with the value:
> >>
> >>   (x,i)
> >>
> >> where x is the value and i is the tag.
> >>
> >> One reason for an explicit tag is that the bounded types may 
> >> contain
> >> the same type twice.  This has lead to problems in 
> >> boost::variant as
> >> evidenced by the post:
> >>
> >>   
> >> http://article.gmane.org/gmane.comp.parsers.spirit.general/17118
> >>
> >> In addition, both variant and tuple have a common part, a 
> >> metafunction
> >> mapping from a tag to a type; hence, this same common part 
> >> could be used
> >> to implement both tuple and a tagged variant.
> >>
> >> A variant which actually contained a tag field I think would 
> >> be more
> >> general in that it would allow duplicate types among the 
> >> bounded types
> >> just as a tuple's bounded types can contain duplicate types.
> >>
> >> -regards,
> >> Larry
> >>
> >
> > Yes, this is a big problem with the current std.variant 
> > implementation (among other problems such as no recursive 
> > variants). The best std.variant can offer right now is the 
> > 'type' property to identify what's stored in it.
> >
> > std.variant is, unfortunately, not very useful if you want the 
> > semantics of variants in ML-style languages.
> 
> I've been working on an update to std.variant whose formal
> submission has been held up by a PhD thesis and some health
> issues, although I'm currently (slowly) doing a code
> review/cleanup of it in the hope of finally submitting it. ( Old
> code: https://jshare.johnshopkins.edu/rjacque2/public_html/ )
> Anyways, my implementation has an internal 'tag' as does the
> current implementation, IIRC. However, as the tag is a
> meaningless random number, instead .type is provide access to the
> meaningful typeinfo object of that class. And .type provides most
> (all?) of the functionality of an int id:
> 
> auto var = Variant(5);
> if(var.type == typeid(int)) {
>   // Do something...
> } else if(var.type == typeid(string)) {
>  // Do something else...
> }
> 
> But I am missing something as I found that the linked post wasn't
> clear what the exact issue was, only that there was an issue. If
> someone would like to clarify the problem (or any other with
> Variant) it would be appreciated.
> 

A little off-topic, but IIRC the typeid stuff is only used to allow
arbitrary types in Variant. This is a valid use case, but could we use
a simple enum/integer tag for Algebraic? There was a discussion about
Variant's performance some time ago and if you don't need to store
arbitrary types you're currently better of writing a custom
discriminated union than using Algebraic.



Re: version(deprecated)?

2012-11-05 Thread monarch_dodra

On Monday, 5 November 2012 at 08:53:48 UTC, Johannes Pfau wrote:

Am Sun, 04 Nov 2012 16:48:26 +0100
schrieb "monarch_dodra" :

I'm wondering if there is a way to know you are in deprecated 
mode or not?


The deprecated attribute is great, because it gives a clear 
compile error (as opposed to a static if, which just hides the 
function completely).


But the attribute alone is not enough: I have a class with a 
deprecated method, which consumes a book-keeping attribute: 
Not only will this attribute exist even though it has become 
useless, but the other functions will keep updating this 
attribute, even though it has no more consumers.


What's more, I'd still want to unittest that function, but 
obviously, only when compiled in "-unittest -d".


So I have a problem.


Finding out if the compilation mode is deprecated is easy 
enough:


//
deprecated @property void deprecateExists(){}
enum deprecatedActive = is(typeof(deprecateExists));
//

The thing is it's kind of dirty, and I wouldn't want to have 
to copy paste this in all of my modules, just to know whether 
or not deprecation is active...




We've currently implemented "version(assert)" and 
"version(debug)". Do you think we should request having a 
"version(deprecated)"? I think it would be very helpful. 
Thoughts?





As deprecated now allows optional messages some folks have 
suggested to
make deprecated behave like in other languages: Warn if 
something

deprecated is used, do not print warnings if compiling with
-deprecated.
This would conflict with your proposed usage of 
version(deprecated).


Is that even possible? I mean, if I deprecate R.index, then what 
is the value of isRandomAccessRange!R? If I call algorithm 
"find(r1, r2);", then will I get a message I'm using a deprecated 
branch?


Wouldn't the proposal be better served as:
-- : Deprecated stuff just can't be used
-d : You can use deprecated stuff, and you get no warning 
whatsoever

-dw : You can use deprecated stuff, but are served with a warning

In that context, we'd keep a clear [w|w/o] deprecated, and my 
proposal would not conflict either.


C++ to catch up?

2012-11-05 Thread jdrewsen
It seems like the C++ committee is speeding up development adding 
lots of the goodies from D like Ranges, static if, template 
contraints etc.


Will D still have a case when C++ gets this done?

I wonder if Andrei is part of the C++ Ranges Study Group?

The Future of C++:
http://channel9.msdn.com/Events/Build/2012/2-005

/Jonas



Re: C++ to catch up?

2012-11-05 Thread Nick Sabalausky
On Mon, 05 Nov 2012 11:00:27 +0100
"jdrewsen"  wrote:

> It seems like the C++ committee is speeding up development adding 
> lots of the goodies from D like Ranges, static if, template 
> contraints etc.
> 
> Will D still have a case when C++ gets this done?
> 


Yes, even if they go and add all of D's features, D will still be much
cleaner. (IMO)



Re: D is a cool language!

2012-11-05 Thread Don Clugston

On 04/11/12 15:30, stonemaster wrote:

On Thursday, 1 November 2012 at 15:56:24 UTC, Tobias Pankrath wrote:

On Thursday, 1 November 2012 at 15:20:11 UTC, Andrei Alexandrescu wrote:

On 11/1/12 9:47 AM, Paulo Pinto wrote:

Hi everyone,

I just saw this online.


The German magazine c't kompakt has an article about cool(exotic)
programming languages, Smalltalk, Haskell and D.

Personally, I like all of them.

Here is the link for the German speaking developers.

http://www.heise.de/newsticker/meldung/Das-neue-c-t-kompakt-Programmieren-kann-bestellt-werden-1739221.html



--
Paulo


Would love to read that. Far as I understand the article ("Exotische
Sprache") is not freely available, is that correct?

Andrei


You need to buy the hole issue for 7€ here
http://www.heise-shop.de/heise-zeitschriften-vlg-g/ct-kompakt-programmieren_pid_19862609.html


It's DRM protected. I wouldn't expect to much.


I read the print version of the D article and I have to say that I'm
quite disappointed:

- The author seems to be talking about D1.0 but not about any new D2.0
features. As a new D2 user I don't really know about the exact
differences between D1 and D2.
- For example the source code uses char[] as string type which doesn't
compile with the D2 compiler
- Descent is introduced as an IDE but it actually has been dead for
quite some time.
- Dsource.org is mentioned as a source of the D community.
- D features mentioned: dynamic and static arrays with slices, missing
preprocessor, debug/version tags, short overview of delegates & lambdas,
very short paragraph about templates, lazy parameter, design by contract
features (in/out/invariant), inline assembler and scope statements.
- There is also a paragraph about memory managament where D is described
as garbage collector centered but allows manual memory managment using
the "delete" keyword and overloading new/delete operators (which is
deprecated, right?).
- There are no examples of phobos
- D2 features like UFCS, CTFE or just the powerful type system including
immutable aren't mentioned at all.


Actually CTFE is a D1 feature!


The author draws a very positive conclusion about D in which he states
that D allows to write high-performance code which still looks
maintainable. As target audience he sees C/C++ programmers but also C#
and Java developers.

Anyway I think the article has been written some years ago and was just
warmed up to be included in the special edition of c't. I'll try to
contact the author to point out the things mentioned above.



Cheers,
André







Re: C++ to catch up?

2012-11-05 Thread monarch_dodra

On Monday, 5 November 2012 at 10:22:02 UTC, Nick Sabalausky wrote:

On Mon, 05 Nov 2012 11:00:27 +0100
"jdrewsen"  wrote:

It seems like the C++ committee is speeding up development 
adding lots of the goodies from D like Ranges, static if, 
template contraints etc.


Will D still have a case when C++ gets this done?




Yes, even if they go and add all of D's features, D will still 
be much

cleaner. (IMO)


C++'s "range" is actually a wrapper over an iterator "first-last" 
pair. While it does bring the convenience of D's ranges to C++, 
it remains hobbled in terms of efficiency and implementation. 
C++'s paradigm is pointers and iterators. At best, you can 
sparkle some ranges over it, but you'll never shift the paradigm.



The thing with C++'s new feature is that it requires developers 
to be on the bleeding edge of C++ knowledge. It's fine for the 
enthusiasts that read programming journals on their week-ends 
(like you and I), but not for the standard developer. Not to 
mention, even then, the syntax is hard as hell: lambdas in for 
loops? I have to look up the syntax every time. automatic type 
inference of the return value of a function? "auto foo() -> 
declype(...)", what...?


All these functionalities are great, but also out of reach. Most 
of my colleagues still struggle with "simple" design patters such 
as strategies, or just plain algorithms with functors. Everytime 
I say something like "awesome, C++ will allow type inference" or 
"yay, RValue references!" they look at me like I'm some kind of 
weird space alien...



D packages the whole thing in an easy to use but complete 
package. C++ just stacks complicated stuff on top of a hard to 
use core.


Re: C++ to catch up?

2012-11-05 Thread Paulo Pinto

On Monday, 5 November 2012 at 11:06:39 UTC, monarch_dodra wrote:
On Monday, 5 November 2012 at 10:22:02 UTC, Nick Sabalausky 
wrote:

On Mon, 05 Nov 2012 11:00:27 +0100
"jdrewsen"  wrote:

It seems like the C++ committee is speeding up development 
adding lots of the goodies from D like Ranges, static if, 
template contraints etc.


Will D still have a case when C++ gets this done?




Yes, even if they go and add all of D's features, D will still 
be much

cleaner. (IMO)


C++'s "range" is actually a wrapper over an iterator 
"first-last" pair. While it does bring the convenience of D's 
ranges to C++, it remains hobbled in terms of efficiency and 
implementation. C++'s paradigm is pointers and iterators. At 
best, you can sparkle some ranges over it, but you'll never 
shift the paradigm.



The thing with C++'s new feature is that it requires developers 
to be on the bleeding edge of C++ knowledge. It's fine for the 
enthusiasts that read programming journals on their week-ends 
(like you and I), but not for the standard developer. Not to 
mention, even then, the syntax is hard as hell: lambdas in for 
loops? I have to look up the syntax every time. automatic type 
inference of the return value of a function? "auto foo() -> 
declype(...)", what...?


All these functionalities are great, but also out of reach. 
Most of my colleagues still struggle with "simple" design 
patters such as strategies, or just plain algorithms with 
functors. Everytime I say something like "awesome, C++ will 
allow type inference" or "yay, RValue references!" they look at 
me like I'm some kind of weird space alien...



D packages the whole thing in an easy to use but complete 
package. C++ just stacks complicated stuff on top of a hard to 
use core.


I have the same feeling with some of our developers.

Simpler languages tend to be manager friendly. It is always 
easier to find cheap resources.


In my currently employer I have only done Java and C# projects so 
far, and I still fear the day I might do a C or C++ project, 
given the type of knowledge shown by some of our coworkers.



--
Paulo





Re: C++ to catch up?

2012-11-05 Thread Adam D. Ruppe

On Monday, 5 November 2012 at 10:00:29 UTC, jdrewsen wrote:

Will D still have a case when C++ gets this done?


C++ does a pretty good job on a lot of things, but there's a 
bunch of little things that just make it a little more 
frustrating day to day than D.


There's still a bunch of big differences too, but it is little 
conveniences and cleaner syntax, etc., that I don't think C++ 
will catch up on.


Re: Const ref and rvalues again...

2012-11-05 Thread martin
On Monday, 5 November 2012 at 08:01:57 UTC, Jonathan M Davis 
wrote:
auto ref's current semantics can't possibly work with 
non-templated functions,
and it's clear that there are good reasons for keeping auto ref 
as it is now
for templates. So, either we make it work with non-templated 
functions with
different (albeit similar) semantics, or we need a new 
attribute for doing what

we want to do with non-templated functions.


I agree that the current auto ref semantics are only useful for 
templates since "auto ref T" is replaced by either a reference 
(ref T for lvalues) or a value (T for rvalues), two very 
different things.
I don't know how auto ref for templates is currently implemented, 
i.e., if, given a function


void foo(T)(auto ref T x, auto ref T y) {}

the compiler would instantiate the template max 2^2 times for 
each used type T to cover all lvalue/rvalue combinations for x 
and y. In that case, treating a non-templated function


void foo(auto ref MyStruct x, auto ref MyStruct y) {}

as implicit template (without template parameters) would be a 
viable option imho, i.e.,


void foo()(auto ref MyStruct x, auto ref MyStruct y) {}

If that kind of auto-templating is not what we want, I'd 
definitely opt for allowing rvalues as "in ref" parameters to 
keep things simple.


std.signals2 proposal

2012-11-05 Thread Robert
Hi there!

I just developed a proof-of-concept implementation of an improved
std.signals. 

Things I did not like about the current implementation:

1. Passing a delegate to connect, which basically is an extended (void*)
and assuming it is an object delegate, does not feel quite right in D,
where we usually try to guarantee correctness by the compiler wherever
possible.

2. The restriction that only objects can be connected. 

Point 2 does not really bother me, because from my little experience I
never really had connected anything else than objects to a signal. But
the restriction that the connected delegate must not be some wrapper, is
quite a restriction I came to dislike about Qt and even more so with
this implementation because unlike Qt the signatures have to match
exactly, you can't omit parameters, like: 
// Qt code
connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClicked());

-> In the current implementation buttonClicked would have to take a
bool.

In addition boost::signals together with boost::bind offered even more
comfort like passing additional parameters to a slot, which is really
very, very useful:

for(int i=0; ihttps://github.com/eskimor/phobos/tree/new_signal

You can easily connect to an object's method with: 

obj.signal.connect!"someMethod"(obj);

instead of the old implementation:

obj.signal.connect(&obj.someMethod);

-> The interface is clean and type safe, all the ugly details are hidden
from the user. And it is just one character more typing. Simple things
stay simple.

In addition a method allowing wrapper delegates was added:

class Observer {
void addNumber(int i) {
sum+=i;
}
int sum;
}

class Button { 
Signal!(bool) clicked;
// ...
}

void main() {
auto b=new Button;
auto o=new Observer;
// Ignore boolean parameter and pass some int:
b.connect!Observer(o, (o, p) { o.addNumber(7); });
// or even:
b.connect!Observer(o, (o, p) => o.addNumber(7));
// For some reason the compiler is not able to deduce "o" being
// Observer, so the !Observer is needed, but it is still very
// neat and readable.
}

Thanks to D's lamdas the syntax is even more concise as boost::bind and
far more powerful.

By passing the object explicitly to the delegate, it is possible to
maintain the 'weak ref' semantics to the target object, while ensuring
that the delegates context won't be freed.

As a side effect it is now even possible to use struct delegates or even
any non object delegate. Simply pass null for the obj parameter. It is
completely safe, the only drawback is that the struct won't be deleted
until the Button gets destroyed. (Because it holds a reference to the
struct, by means of the delegate.) But for long lived structs this
usually is perfectly acceptable.

Implementation:

In my implementation I changed the Signal mixin to be a simple template
struct, because I hit strange compiler errors with it being a mixin. The
most prominent:

std/signals.d(443): Error: no overload matches for connect(string
method,T2) if (is(T2 : Object))

You can find the version triggering these errors at:

https://github.com/eskimor/phobos/tree/new_signal_mixin

Also I did not really get the point why a mixin was used in the first
place, it does not really gain us anything? What was the reasoning about
it?
I almost thought I found the reason, because my implementations suffers
from unhook not being called, although it was properly registered with
"rt_attachDisposeEvent(obj, &unhook);", thus causing a segmentation
fault when the observer gets deleted. I did not really find any
difference from the original version that could explain this behavior,
despite the original implementation being a mixin. So I thought, well
maybe the delegate passed to "rt_attachDisposeEvent(obj, &unhook);" must
be an object delegate (that's would be why the mixin was needed), but
after digging in object_.d I did not find any code assuming that the
delegate was an object delegate. Any ideas on this?

Another thing I'd like to ask Walter, is what the "L1:" label is for in
connect(), is it just some left over or has it some special internal
compiler thing meaning?

What do you think?

Best regards,

Robert




Re: Why does std.variant not have a tag?

2012-11-05 Thread evansl
On 11/05/12 00:33, Robert Jacques wrote:
> On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen
> wrote:
>> On 05-11-2012 00:31, evansl wrote:
>>>   http://dlang.org/phobos/std_variant.html
>>>
>>> says:
>>>
>>>  This module implements a discriminated union type (a.k.a. tagged union,
>>> algebraic type).
>>>
>>> Yet, the wiki page:
>>>
>>>   http://en.wikipedia.org/wiki/Tagged_union
>>>
>>> says:
>>>
>>>   a tag field explicitly indicates which one is in use.
>>>
>>> and I don't see any indication of a tag field in the std_variant.html
>>> page.  Another wiki reference:
>>>
>>>   http://en.wikipedia.org/wiki/Disjoint_union
>>>
>>> is more explicit because it pairs the tag with the value:
>>>
>>>   (x,i)
>>>
>>> where x is the value and i is the tag.
>>>
>>> One reason for an explicit tag is that the bounded types may contain
>>> the same type twice.  This has lead to problems in boost::variant as
>>> evidenced by the post:
>>>
>>>   http://article.gmane.org/gmane.comp.parsers.spirit.general/17118
>>>
>>> In addition, both variant and tuple have a common part, a metafunction
>>> mapping from a tag to a type; hence, this same common part could be used
>>> to implement both tuple and a tagged variant.
>>>
>>> A variant which actually contained a tag field I think would be more
>>> general in that it would allow duplicate types among the bounded types
>>> just as a tuple's bounded types can contain duplicate types.
>>>
>>> -regards,
>>> Larry
>>>
>>
>> Yes, this is a big problem with the current std.variant implementation
>> (among other problems such as no recursive variants). The best
>> std.variant can offer right now is the 'type' property to identify
>> what's stored in it.
>>
>> std.variant is, unfortunately, not very useful if you want the
>> semantics of variants in ML-style languages.
> 
> I've been working on an update to std.variant whose formal
> submission has been held up by a PhD thesis and some health
> issues, although I'm currently (slowly) doing a code
> review/cleanup of it in the hope of finally submitting it. ( Old
> code: https://jshare.johnshopkins.edu/rjacque2/public_html/ )
> Anyways, my implementation has an internal 'tag' as does the
> current implementation, IIRC. However, as the tag is a
> meaningless random number, instead .type is provide access to the
> meaningful typeinfo object of that class. And .type provides most
> (all?) of the functionality of an int id:
> 
> auto var = Variant(5);
> if(var.type == typeid(int)) {
>  // Do something...
> } else if(var.type == typeid(string)) {
> // Do something else...
> }

Robert, I see no bounded types in the above Variant.
Looking back at:

  http://dlang.org/phobos/std_variant.html

I see now that std.Variant doesn't require the set of
types to be bounded.  It's only Algebraic:

  http://dlang.org/phobos/std_variant.html#Algebraic

that has a bounded set of types.  I should have read
closer.  I mistakenly thought std.variant served the
same purpose as Boost.variant, but now I see that
Boost.variant and std.Algebraic serve similar purposes
in that they require a set of bounded types, but that
Boost.any and std.variant are similar in that the types
are unbounded (IOW, any type can be stored in std.variant
or Boost.any).

Sorry for not carefully reading.  So my question then is
why doesn't ALgebraic have a tag.  This would allow:

  Algebraic!(int,int)

> 
> But I am missing something as I found that the linked post wasn't
> clear what the exact issue was, only that there was an issue. If
> someone would like to clarify the problem (or any other with
> Variant) it would be appreciated.
> 

If std.Algebraic is like Boost.Variant, then duplicate
bounded types are not allowed and leads to the problem mentioned
in the post on the spirit mailing list which I linked to in my
OP.  OOPS,  now I see why reading that post was not clear enough.
Maybe this earlier post in same spirit thread would be clearer.

http://article.gmane.org/gmane.comp.parsers.spirit.general/17113

In particular, note the phrase:

  neither can you use variant
  because variant can't take duplicate types.

This can lead to problems in the spirit parser because
the attributes of parsing:

a | b

where:
  phrase a has an attribute of type A
  phrase b has an attribute of type B
is:

variant

as noted near the bottom of:


http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html

and if A and B are the same, then there's a problem because
Boost.variant can't handle duplicates.

Hope that's clearer.

-regards,
Larry

BTW, recently there was a review of
another Boost library that has some similarity to
Boost.any.  It's called type_erasure:


http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html

Since std.Variant is similar to Boost.any (as noted above),
and since Boost.any is, in some ways, like Boost.type_erasure,
and since you're working on a revised 

Re: automatic mixin in classes

2012-11-05 Thread deadalnix

Le 27/10/2012 07:39, Gor Gyolchanyan a écrit :

I've stumbled upon this numerous times and I wish I could automate this
somehow.
The idea is to have some mixin templates mixed into classes
automatically when they inherit from some base class.
For instance, advanced RTTI methods, which analyze the enclosing class
at compile-time.
Unfortunately, AFAIK, there's no way of doing it automatically and one
needs to both derive from a certain class and mix in a certain mixin
template manually.
Is there a way to avoid the boilerplate and have it done automatically?

--
Bye,
Gor Gyolchanyan.


I had this need several time too. But I don't think this should be a 
functionality added in D at this point.


This is typically AOP stuff and it is much more interesting for D to 
think about how to integrate the whole AOP concept instead of hacking 
around each use case.


Re: What is the use case for this weird switch mecanism

2012-11-05 Thread deadalnix

Le 31/10/2012 21:33, Chris Nicholson-Sauls a écrit :

Some related actual code from a while back:

##
ParseTree prune ( ParseTree p ) {
p.children = p.children.dup;
foreach ( ref child ; p.children ) {
child = prune( child );
}

switch ( p.ruleName ) {
// strip prefix/suffix terminals, then if left with only one child, skip
over it
case "Args" :
case "List" :
case "Params" :
case "Table" : p.children = p.children[ 1 .. $ - 1 ];
if ( p.children.length == 1 ) {

// skip over immediate child (always a "Series")
case "QualIdent" :
case "Type" : p.children = p.children[ 0 ].children;
}
break;

// skip self if it has exactly one child
case "Addition" :
case "BoolAnd" :
case "BoolOr" :
case "Comparison" :
case "Conditional" :
case "MaybeParens" :
case "Multiplication" :
case "Postfix" :
case "Primary" :
case "Unary" : if ( p.children.length == 1 ) {

// skip self
case "Expression" :
case "Field" :
case "Ident" :
case "Literal" :
case "PathElem" :
case "Statement" : p = p.children[ 0 ];
}
break;

default:
}

return p;
}
##

Without the loosely defined switch() statement syntax, this would have
been a royal pain to piece together. Especially when each block of cases
was evolving over time.

There is also the trick of doing 'switch(val) with(EnumType) {...}' to
bring an enum's members into scope so that cases can be written as 'case
Foo:' rather than 'case EnumType.Foo:'.

-- Chris Nicholson-Sauls



Wow this is not actually the case presented in y first post, but still 
very interesting.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 04:11, Jonathan M Davis a écrit :

On Sunday, November 04, 2012 15:40:18 deadalnix wrote:

Le 04/11/2012 03:26, Jonathan M Davis a écrit :

3. Make it so that ranges which can be transient are non-transient by
default but provide a function to get at a transient version for speed
(which was the fastRange proposal in this thread). The main problem here
is that when the fast range gets wrapped, it's transient, and so anything
using the wrapped range will be forced to use the transient version
rather than using the non- transient version and only using the transient
version when it's asked for. So, I don't think that this is particularly
viable.


Can you elaborate on that. I definitively don't see a problem that big here.


The problem is that you can't opt out of the fast range once you've got it. If
you use fastRange and then the result ends up getting wrapped by another
range, that range's front is transient and has no way of indicating it. So,
you're right back in the boat that we're in right now. In order to avoid that,
virtually all range-based functions would have to not use fastRange, because
they have no idea whether you're going to use their result to pass to another
function or not.

- Jonathan M Davis


HS Teoh explained it nicely.

The responsibility of using .transient or not belong to the consumer. 
Only the consumer can know if a transient range is suitable.


So you don't wrap a transient range. You wrap a non transient range, 
and, if the consumer is able to handle the transcient version, it call 
.transient on its source, that call it on its source, etc . . . up to 
the real source.


If one transformer is unable to handle transient range, the it don't 
pass .transient to its source.


Re: What is the use case for this weird switch mecanism

2012-11-05 Thread bearophile

Era Scarecrow:


It's not worth the unsafety of the whole switch.


 What? I'd need a little explanation what you'd mean.


I meant that semantically clean language features help avoid
troubles later while you program :-)




besides, 'switch with' and 'with switch' are practically
identical... aren't they?


Yeah, they are practically identical, that's my point. But 'with
switch' allows you to to not allow code after the switch, so
allows to keep switch syntax cleaner :-)

Bye,
bearophile


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 04/11/2012 23:10, H. S. Teoh a écrit :

On Sun, Nov 04, 2012 at 12:38:06PM -0500, Andrei Alexandrescu wrote:

On 11/4/12 12:26 PM, deadalnix wrote:

I think it fit nicely D's phylosophy, in the sense it does provide a
safe, easy to use interface while providing a backdoor when this
isn't enough.


It doesn't fit the (admittedly difficult to fulfill) desideratum that
the obvious code is safe and fast. And the obvious code uses byLine,
not byLine.transient.


Actually, it does. The proposal was to modify byLine so that it returns
strings instead of a reused char[] buffer. The current version of byLine
that has transient front will be moved into a .transient property. This
has the following results:

- All existing code doesn't break: it just becomes a tad slower from
   duplicating each line. Correctness is not broken.

- Code that wants to be fast can call .transient at the end of the
   construction, e.g., stdin.byLine().map!myFunc.transient. Assuming
   that map propagates .transient (which also implies it's safe to use
   with transient ranges), this will return an optimized range that
   reuses the transient buffer safely.

- Code that calls .transient on non-transient ranges get a no-op:
   [1,2,3].map!myFunc.transient is equivalent to [1,2,3].map!myFunc,
   because non-transient ranges just alias .transient to themselves (this
   can be done via UFCS so no actual change needs to be made to existing
   non-transient ranges).

IOW, code is always 100% safe by default. You can optionally use
.transient with certain ranges if you'd like for it to be faster. Using
.transient where it isn't supported simply defaults to the usual safe
behaviour (no performance increase, but no safety bugs either).

Now, this can be taken one step further. User code need not even know
what .transient is. As deadalnix said, the insight is that it is only
invoked by range *consumers*. For example, one could in theory make
canFind() transient-safe, so the user would write this:

auto n = stdin.byLine().map!myFunc.canFind(myNeedle);

and canFind uses the .transient range to do the finding. Assuming
map!myFunc correctly supports .transient, this request for the faster
range automatically propagates back to byLine(), and so the code is fast
*without the user even asking for .transient*.

And if the range being scanned is non-transient, then it behaves
normally as it does today. For example, if map!myFunc does *not* support
.transient, then when canFind asks for .transient, UFCS takes over and
it just gets the (non-transient) mapped range back. Which in turn asks
for the *non-transient* version of byLine(), so in no case will there be
any safety breakage.

I think this solution is most elegant so far, in the sense that:

(1) Existing code doesn't break;
(2) Existing code doesn't even need to change, or can be slowly
optimized to use .transient on a case-by-case basis without any code
breakage;
(3) The user doesn't even need to know what .transient is to reap the
benefits, where it's supported;
(4) The algorithm writer decides whether or not .transient is supported,
guaranteeing that there will be no hidden bugs caused by assuming .front
is persistent and then getting a transient range passed to it. So it's
the algorithm that declares whether or not it supports .transient.



Back to a simpler solution: what's wrong with adding alternative
APIs for certain input ranges? We have byLine, byChunk,
byChunkAsync. We may as well add eachLine, eachChunk, eachChunkAsync
and let the documentation explain the differences.

[...]

This is less elegant than deadalnix's proposal, because there is a
certain risk associated with using .transient ranges. Now the onus is on
the user to make sure he doesn't pass a transient range to an algorithm
that can't handle it.

With deadalnix's proposal, it's the *algorithm* that decides whether or
not it knows how to handle .transient properly. The user doesn't have to
know, and can still reap the benefits. An algorithm that doesn't know
how to deal with transient ranges simply does nothing, and UFCS takes
over to provide the default .transient, which just returns the original
non-transient range.



I think I'll hire you when I need to promote my ideas :D This is much 
better explained than what I did myself and is exactly what I had in mind.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 04:21, Jonathan M Davis a écrit :

However, that means that we need to be very clear about the fact that input
ranges can have transient fronts and that algorithms cannot assume that their
fronts are not transient (something that only you appear to have thought was
clear).


Note that this break inputRange.array(); Which seems like a really big 
problem to me.



We then either have to change a bunch of algorithms so that they
require forward ranges, or we need to create a trait which can determine
whether front is transient in it least some cases (it would still be claiming
that front is transient in some cases where it isn't, because it can't know
for sure, but we'd at least be able to figure it out in some cases), and make
algorithms use that in their constraints when they deal with input ranges.
std.array.array would be a prime case where an algorithm would have to be
changed, because it can't function with a transient front, and it's a prime
example of a function that you'd normally expect to work with an input range.
And this _will_ break code. It'll allow us to fix the ByLine problem though.

- Jonathan M Davis




Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Sun, Nov 04, 2012 at 11:58:18PM -0800, Jonathan M Davis wrote:
> On Sunday, November 04, 2012 21:07:46 H. S. Teoh wrote:
> > Stop right there. You're contradicting yourself. You kept saying
> > that transient ranges are rare, abnormal, etc., and now you say they
> > are a potentially large number of range types? I'm sorry, you've
> > managed to utterly confuse me.  Are they rare, or are they not?
> > 
> > If they are rare, then this thin wrapper only needs to be written in
> > those few rare cases. *No other range type needs to be changed.*
> > 
> > If they are common, then they aren't abnormal, and we should be
> > fixing Phobos to deal with them. Everywhere. In a pervasive,
> > invasive, large changeset, because almost all current code is broken
> > w.r.t. to these common cases -- if indeed they are common.
> 
> Base ranges with transient fronts are rare, but as soon as you have to
> take them into account with wrapper ranges, then they potentially
> affect almost every range-based function in Phobos. So, you're taking
> a very rare case and forcing _everything_ to account for it. _That_ is
> why it affects a large number of range types.

Only wrapper ranges that explicit support transience need to propagate
it. Wrapper ranges that don't support transience, by definition, should
*not* propagate it, because that would be wrong (they don't support
transience because they don't handle transient .front correctly, so they
should not propagate it at all, otherwise they will exhibit buggy
behaviour).


[...]
> > As I said, by having a UFCS version of .transient that simply
> > returns the original range, you don't even need to know what
> > .transient does.  Don't even include it in your range, and it just
> > behaves as a normal non-transient range. How is that any more
> > complicated?
> 
> You can't just return the original range from a wrapper range and have
> it work. Take filter for instance, if you got at the range that it
> wrapped, you'd be completely bypassing filter, and the range wouldn't
> be filtered at all.

No, you're misunderstanding how it works. Say I have this range:

struct MyRange {
@property auto front() { ... }
@property bool empty() { ... }
void popFront() { ... }
auto transient() { return MyTransientRange(this); }
}

Now, say filter doesn't support transience. In which case we simply
do this:

auto filter(alias pred, R)(R range) {
struct Filter(alias pred) {
@property auto front() { /* filtered front */ }
@property bool empty() { ... }
void popFront() { ... }
// NB: No .transient is defined
}
return Filter!pred(range);
}

Now we call filter on our range:

MyRange r;
auto filtered = filter!"a<10"(r);

What happens? Filter doesn't define .transient, so UFCS kicks in with
the default function that simply returns Filter!pred (NOT r). This is
the correct behaviour, because filter() doesn't support transience. It
would be wrong to add this line to struct Filter:

auto transient() { return _filterImpl(range.transient); }

because the filter implementation does NOT support transience. So in
this case, .transient shouldn't be propagated.


> Any and all wrapper ranges would have to take transient into account.
> If they couldn't do transient ranges, then they just wouldn't
> propagate or use transient. But if they could, then they'd have to
> create their own transient property which returned an appropriate
> range type which functioned properly with transience. Yes, it would
> use the transient property of the range that it was wrapping, but it
> would have to create its own transient property which functioned
> properly with whatever it was doing.

Which is only a small cost, as I demonstrated with the thin wrapper.


> The _only_ way that this doesn't affect a lot of ranges in Phobos is
> if we just don't bother to propagate the transient property, and if we
> don't bother to propagate it, then there was no point in having it in
> the first place. Such ranges might as well have their own functions
> for iterating or just use opApply if no wrapper ranges are going to
> propagate their extra properties or if no range-based functions take
> those extra properties into account.
[...]

Like I said, it only affects Phobos ranges that explicitly support
transience. Those are the ranges that *should* be modified in the first
place. Those that don't support .transient, simply don't propagate it
(and they *shouldn't* propagate it, because that would be a bug).  No
changes are required in that case.

And of those ranges that should support transience, well, they are
already failing today to work with transient ranges, so they need to be
fixed anyway. With this proposal, we even get to delay the fix because
we make all ranges non-transient b

Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 04:47, Jonathan M Davis a écrit :

On Sunday, November 04, 2012 19:41:39 H. S. Teoh wrote:

On Sun, Nov 04, 2012 at 07:11:22PM -0800, Jonathan M Davis wrote:

On Sunday, November 04, 2012 15:40:18 deadalnix wrote:

Le 04/11/2012 03:26, Jonathan M Davis a écrit :

3. Make it so that ranges which can be transient are non-transient
by default but provide a function to get at a transient version
for speed (which was the fastRange proposal in this thread). The
main problem here is that when the fast range gets wrapped, it's
transient, and so anything using the wrapped range will be forced
to use the transient version rather than using the non- transient
version and only using the transient version when it's asked for.
So, I don't think that this is particularly viable.


Can you elaborate on that. I definitively don't see a problem that
big here.


The problem is that you can't opt out of the fast range once you've
got it. If you use fastRange and then the result ends up getting
wrapped by another range, that range's front is transient and has no
way of indicating it. So, you're right back in the boat that we're in
right now. In order to avoid that, virtually all range-based functions
would have to not use fastRange, because they have no idea whether
you're going to use their result to pass to another function or not.


[...]

The crux of what deadalnix proposed is that range transformers simply
pass .transient along, whilst range consumers decide whether or not to
use .transient. So this isn't even an issue until you are in a range
consumer, which can decide whether or not the transient range should be
used.

IOW, the choice between .transient or not isn't even made until the end.
The range consumer is the one in the position to decide whether or not
.transient should be used.


And how on earth would it decide that when it's been wrapped by who-knows how
many wrapper ranges? It would be far too late at that point. Unless you expect
that every one of those ranges is going to duplicate itself such that when you
call fastRange or transient or whatever you can get a different range type
which is transient? That's worse than inTransient IMHO. The only advantage
that it has is that if you fail to take it into account, you end up with the
non-transient range, and your code doesn't end up doing crazy stuff. But in
either case, all of the range types have to take it into account, complicating
their implementations that much further, and fastRange would complicate those
implementations far more than isTransient would, because it would require code
duplication rather than just statically disallowing the transient range when
it wouldn't work.

- Jonathan M Davis


That is not true. As shown by sample code before the following happens :

Transient source ranges can be wrapped into the non transient one, using 
alias this and implementing only .front to dup. .transient then just 
unwrap. Code duplication is avoided most of the time.


Transformer ranges are usually transient or not according to their 
source. Joiner proposal by H. S. Teoh is done quickly, but in fact, you 
notice that joiner can have just one implementation, and that its 
transientness will depends on source transcientness. In this case, code 
duplication is avoided too.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 05:42, Jonathan M Davis a écrit :

On Sunday, November 04, 2012 20:20:58 H. S. Teoh wrote:

What's not to like about this proposal?


It creates massive code duplication all over the place, and it's yet one more
range concept that everyone has to remember and keep in mind. Remember that
ranges are supposed to be perfectly writable by the average D user, not just
Phobos devs. And this complicates them yet further. If anything, we need to
_simplify_ ranges, not make them more complex (e.g. getting rid of the move*
functions). And this proposal not only makes them more complex, it ends up
requiring that a lot more code be written.

Sure, the fact that ranges are non-transient by default reduces the problem,
but that just means that it's that much less likely to actually be used,
meaning that we're complicating ranges even further for something that most
people are going to forget about completely.



That is probably true.

But, whatever the solution, this will be true. So it is better, 
considering this will be true, that the user get correct code.



I honestly think that you're pushing for an incredibly abnormal use case here,
and that it's just not worth the extra complication that it requires.



It isn't the first time the subject pop's, and I have already 
encountered the issue in my own code too (in a rubik's cube solver and 
in compiler code to be precise). We may not have the same coding style 
or code on apps that require different approach, but the problem seems 
real to me.



It's bad enough to be stuck trying to support transient fronts with input
ranges, but input ranges are so useless in general that it may actually end up
affecting very few functions in reality. Anything like isTransient or transient
or fastRange affects _everything_, and just because it can be added in piece by
piece instead of all at once doesn't change that fact. It just allows us to
spread out the work.



Dealing with transient range require care anyway. Bunch of code have to 
be touched, whatever the solution choosen. Most phobos act like .front 
isn't transient and currently just expose undefined behavior.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 08:58, Jonathan M Davis a écrit :

On Sunday, November 04, 2012 21:07:46 H. S. Teoh wrote:

Stop right there. You're contradicting yourself. You kept saying that
transient ranges are rare, abnormal, etc., and now you say they are a
potentially large number of range types? I'm sorry, you've managed to
utterly confuse me.  Are they rare, or are they not?

If they are rare, then this thin wrapper only needs to be written in
those few rare cases. *No other range type needs to be changed.*

If they are common, then they aren't abnormal, and we should be fixing
Phobos to deal with them. Everywhere. In a pervasive, invasive, large
changeset, because almost all current code is broken w.r.t. to these
common cases -- if indeed they are common.


Base ranges with transient fronts are rare, but as soon as you have to take
them into account with wrapper ranges, then they potentially affect almost
every range-based function in Phobos. So, you're taking a very rare case and
forcing _everything_ to account for it. _That_ is why it affects a large number
of range types.



Don't you understand that every other solution proposed here, including 
Andrei's, have the same very drawback ?


I'll add that this drawback is much worse, because with the ;transient 
solution, unmodified code will work correctly. With all other proposed 
behaviors, non updated code will expose undefined behavior when facing 
transient ranges, which is much worse.


Re: C++ to catch up?

2012-11-05 Thread deadalnix

Le 05/11/2012 11:22, Nick Sabalausky a écrit :

On Mon, 05 Nov 2012 11:00:27 +0100
"jdrewsen"  wrote:


It seems like the C++ committee is speeding up development adding
lots of the goodies from D like Ranges, static if, template
contraints etc.

Will D still have a case when C++ gets this done?




Yes, even if they go and add all of D's features, D will still be much
cleaner. (IMO)



You never heard about @property ?


Re: Generic and fundamental language design issue

2012-11-05 Thread deadalnix

Le 04/11/2012 18:35, Tommi a écrit :

I have a fundamental language design talking point for you. It's not
specific to D. I claim that, most of the time, a programmer cannot, and
shouldn't have to, make the decision of whether to allocate on stack or
heap. For example:

void func(T)()
{
auto t = 
...
}

The question of whether variable t should lay in heap or stack, depends
not only on the sizeof(T), but also on the context in which func is
called at. If func is called at a context in which allocating T on stack
would cause a stack overflow, then t should be allocated from the heap.
On the other hand, if func is called at a context where T still fits
nicely on the stack, it would probably be better and faster to allocate
t on stack.

So, the question of whether to allocate that variable t on stack or heap
is something that only the compiler (or runtime) can answer. Is there
any language where you have the ability to say "allocate T from wherever
it's best"?

I wonder if it would be possible in D to let the compiler allocate
dynamic arrays on stack when it can statically guarantee that it's safe
to do so (no dangling references, never increasing the size of the
array, etc).


BTW, Why can't we allocate 1Gb stack or something insanely big on 64bits 
systems ?


It will not use actual physical memory unless it is used, and much more 
stuffs can be allocated on stack.


Re: automatic mixin in classes

2012-11-05 Thread Gor Gyolchanyan
I don't see anything related to this issue.


On Sun, Oct 28, 2012 at 5:41 AM, Chris Nicholson-Sauls <
ibisbase...@gmail.com> wrote:

> On Saturday, 27 October 2012 at 05:39:59 UTC, Gor Gyolchanyan wrote:
>
>> I've stumbled upon this numerous times and I wish I could automate this
>> somehow.
>> The idea is to have some mixin templates mixed into classes automatically
>> when they inherit from some base class.
>> For instance, advanced RTTI methods, which analyze the enclosing class at
>> compile-time.
>> Unfortunately, AFAIK, there's no way of doing it automatically and one
>> needs to both derive from a certain class and mix in a certain mixin
>> template manually.
>> Is there a way to avoid the boilerplate and have it done automatically?
>>
>
> Does this give you any ideas on how to solve your use cases:
> https://github.com/csauls/**zeal.d/blob/master/source/**
> zeal/base/controller.d
> https://github.com/csauls/**zeal.d#controllers
> https://github.com/csauls/**zeal.d/blob/master/source/**
> zeal/http/router.d#L93
>
> -- Chris Nicholson-Sauls
>
>


-- 
Bye,
Gor Gyolchanyan.


Re: automatic mixin in classes

2012-11-05 Thread Gor Gyolchanyan
Yeah, I know. Currently bug fixes are way more important then new features
and this one really really looks like a dirty hack. But the problem it
solves is very real. I honestly don't know what to do about it.


On Mon, Nov 5, 2012 at 6:38 PM, deadalnix  wrote:

> Le 27/10/2012 07:39, Gor Gyolchanyan a écrit :
>
>> I've stumbled upon this numerous times and I wish I could automate this
>> somehow.
>> The idea is to have some mixin templates mixed into classes
>> automatically when they inherit from some base class.
>> For instance, advanced RTTI methods, which analyze the enclosing class
>> at compile-time.
>> Unfortunately, AFAIK, there's no way of doing it automatically and one
>> needs to both derive from a certain class and mix in a certain mixin
>> template manually.
>> Is there a way to avoid the boilerplate and have it done automatically?
>>
>> --
>> Bye,
>> Gor Gyolchanyan.
>>
>
> I had this need several time too. But I don't think this should be a
> functionality added in D at this point.
>
> This is typically AOP stuff and it is much more interesting for D to think
> about how to integrate the whole AOP concept instead of hacking around each
> use case.
>



-- 
Bye,
Gor Gyolchanyan.


Re: C++ to catch up?

2012-11-05 Thread Tobias Pankrath

On 11/05/2012 11:22 AM, Nick Sabalausky wrote:

On Mon, 05 Nov 2012 11:00:27 +0100
"jdrewsen"  wrote:


It seems like the C++ committee is speeding up development adding
lots of the goodies from D like Ranges, static if, template
contraints etc.

Will D still have a case when C++ gets this done?




Yes, even if they go and add all of D's features, D will still be much
cleaner. (IMO)



Compile times!


Re: C++ to catch up?

2012-11-05 Thread H. S. Teoh
On Mon, Nov 05, 2012 at 01:19:04PM +0100, jdrewsen wrote:
> On Monday, 5 November 2012 at 11:39:54 UTC, Erèbe wrote:
> >On Monday, 5 November 2012 at 10:00:29 UTC, jdrewsen wrote:
> >>It seems like the C++ committee is speeding up development
> >>adding lots of the goodies from D like Ranges, static if,
> >>template contraints etc.
> >>
> >>Will D still have a case when C++ gets this done?
> >>
> >>I wonder if Andrei is part of the C++ Ranges Study Group?
> >>
> >>The Future of C++:
> >>http://channel9.msdn.com/Events/Build/2012/2-005
> >>
> >>/Jonas
> >
> >http://forum.dlang.org/thread/iokgislnlzsvsosmq...@forum.dlang.org
> 
> I didn't read all of that thread because of the title "D vs C++11" -
> but it does list some very good arguments in favour of D.
> 
> I'll stop the emergency port of my D project to C++ then :P
[...]

The thing you've to understand about C++ is that it is an old,
widely-adopted language, and therefore it needs to maintain backward
compatibility with the very large existing codebase. This prevents it
from truly cleaning up some of the earliest design flaws, because that
will break just about every C++ program ever written, which is something
the C++ committee pretty much will never do.

We're already seeing a little bit of this effect in D; introducing
breaking changes OT1H lets us clean up the language and make it much
better, but it also alienates a lot of existing users. That's why Walter
has stated that there must be no more breaking changes, even if it is to
fix what is in retrospect a poor language design decision. This limits
how much we can do to fix existing design issues.

D had the advantage that it could learn from C++'s mistakes and do
things better. C++ doesn't have that benefit; it can introduce new
features, but the old flaws that still plague the language must live on.
The horribly ambiguous template syntax, for example, will continue to
live on. C++ will continue being the language that must be parsed before
it can be lexed. The ctor, copy ctor, etc., mess, must still live on.
Operator overloading will never have the convenience of D's compile-time
string-based approach, which allows very nice ways of reducing
boilerplate code. Etc., etc..

And new features must work around existing syntax in order to not break
existing code, which means nice syntax like D's templates, aliases,
etc., will never be as nice as they are in D.

I used to be big on C/C++ before I found D. From my admittedly biased
POV, though, C++11 (and beyond) is "too little, too late". I remember
being really excited when I first found out about C++11 (back when it
was still called C++0x -- it didn't make it before the turn of the
decade). Finally, I thought, here was the long-needed language update
that everyone's been waiting for. Well, I have to say that I felt quite
deflated after reading the spec summary. Yes it introduced some new
innovations which I liked, and some fixes to the most glaring language
flaws. But it was too little, too late. It took way too many years to
finalize, which meant many more years before wide adoption and
availability of conforming implementations. And it *still* didn't fix
all of the fundamental flaws in the language.

Not long afterwards, I found D, and that was the end of C++ for me. Yes
D does have its warts, but in spite of it all it's still superior to C++
in many fundamental ways.


T

-- 
Guns don't kill people. Bullets do.


Re: C++ to catch up?

2012-11-05 Thread Jonathan M Davis
On Monday, November 05, 2012 11:00:27 jdrewsen wrote:
> It seems like the C++ committee is speeding up development adding
> lots of the goodies from D like Ranges, static if, template
> contraints etc.
> 
> Will D still have a case when C++ gets this done?
> 
> I wonder if Andrei is part of the C++ Ranges Study Group?
> 
> The Future of C++:
> http://channel9.msdn.com/Events/Build/2012/2-005

The closer that C++ gets to D, the less interested that many people will be in 
adopting it, particularly because of the large user base and the large amount 
of code out there that already uses C++. Programmers have to be convinced to 
move to D, and for many C++ programmers, the improvements to C++11 are enough 
to make a move to D not worth it, even if D is a better language.

But C++ will never have all that D does. There are too many things that it 
would have to fundamentally change (e.g. how arrays work) which it can't 
change, because it would break backwards compatibility. Many of C++'s flaws 
stem from retaining backwards compatibility with C, and they're not going to 
break that now either. So, while they can do a lot to improve C++, there's a 
definite limit to it. D will ultimately have similar problems, since we'll have 
to maintain backwards compatibility for the same reasons that every other 
mainstream language does, but it's definitely ahead of C++ in that regard, 
because it was able to learn from C++'s mistakes. And if we ever create a D3, 
and we're willing to actually break compatibility with that version change 
(which C++ will never do in any real way with any version change), then we can 
avoid C++'s fate in that regard to at least some extent, but then you get into 
a situation like python 2 and python 3 or perl 5 and perl 6.

In any case, it's pretty much a given that improving C++ will mean that fewer 
people will move away from it to other languages, but it's also a given that 
there are fundamental problems with C++ that can't be fixed, and in that 
regard, D will always come out ahead of it.

- Jonathan M Davis


Re: std.signals2 proposal

2012-11-05 Thread Jonathan M Davis
On Monday, November 05, 2012 14:36:55 Robert wrote:
> Another thing I'd like to ask Walter, is what the "L1:" label is for in
> connect(), is it just some left over or has it some special internal
> compiler thing meaning?

It's a label. There's nothing special about it. You jump to them with gotos. 
However, there's no goto in that function (and D does not support using gotos 
across functions), so it doesn't do anything. Presumably, it's left over from 
some previous refactoring.

- Jonathan M Davis


Re: std.signals2 proposal

2012-11-05 Thread Robert
Thought so. Thank you!
>  Presumably, it's left over from 
> some previous refactoring.
> 
> - Jonathan M Davis




Re: std.signals2 proposal

2012-11-05 Thread Zhenya

On Monday, 5 November 2012 at 13:35:26 UTC, Robert wrote:

Hi there!

I just developed a proof-of-concept implementation of an 
improved

std.signals.

Things I did not like about the current implementation:

1. Passing a delegate to connect, which basically is an 
extended (void*)
and assuming it is an object delegate, does not feel quite 
right in D,
where we usually try to guarantee correctness by the compiler 
wherever

possible.

2. The restriction that only objects can be connected.

Point 2 does not really bother me, because from my little 
experience I
never really had connected anything else than objects to a 
signal. But
the restriction that the connected delegate must not be some 
wrapper, is
quite a restriction I came to dislike about Qt and even more so 
with
this implementation because unlike Qt the signatures have to 
match

exactly, you can't omit parameters, like:
// Qt code
connect(button, SIGNAL(clicked(bool)), this, 
SLOT(buttonClicked());


-> In the current implementation buttonClicked would have to 
take a

bool.

In addition boost::signals together with boost::bind offered 
even more
comfort like passing additional parameters to a slot, which is 
really

very, very useful:

for(int i=0; ihttps://github.com/eskimor/phobos/tree/new_signal

You can easily connect to an object's method with:

obj.signal.connect!"someMethod"(obj);

instead of the old implementation:

obj.signal.connect(&obj.someMethod);

-> The interface is clean and type safe, all the ugly details 
are hidden
from the user. And it is just one character more typing. Simple 
things

stay simple.

In addition a method allowing wrapper delegates was added:

class Observer {
void addNumber(int i) {
sum+=i;
}
int sum;
}

class Button {
Signal!(bool) clicked;
// ...
}

void main() {
auto b=new Button;
auto o=new Observer;
// Ignore boolean parameter and pass some int:
b.connect!Observer(o, (o, p) { o.addNumber(7); });
// or even:
b.connect!Observer(o, (o, p) => o.addNumber(7));
// For some reason the compiler is not able to deduce "o" being
// Observer, so the !Observer is needed, but it is still very
// neat and readable.
}

Thanks to D's lamdas the syntax is even more concise as 
boost::bind and

far more powerful.

By passing the object explicitly to the delegate, it is 
possible to
maintain the 'weak ref' semantics to the target object, while 
ensuring

that the delegates context won't be freed.

As a side effect it is now even possible to use struct 
delegates or even
any non object delegate. Simply pass null for the obj 
parameter. It is
completely safe, the only drawback is that the struct won't be 
deleted
until the Button gets destroyed. (Because it holds a reference 
to the
struct, by means of the delegate.) But for long lived structs 
this

usually is perfectly acceptable.

Implementation:

In my implementation I changed the Signal mixin to be a simple 
template
struct, because I hit strange compiler errors with it being a 
mixin. The

most prominent:

std/signals.d(443): Error: no overload matches for 
connect(string

method,T2) if (is(T2 : Object))

You can find the version triggering these errors at:

https://github.com/eskimor/phobos/tree/new_signal_mixin

Also I did not really get the point why a mixin was used in the 
first
place, it does not really gain us anything? What was the 
reasoning about

it?
I almost thought I found the reason, because my implementations 
suffers
from unhook not being called, although it was properly 
registered with
"rt_attachDisposeEvent(obj, &unhook);", thus causing a 
segmentation

fault when the observer gets deleted. I did not really find any
difference from the original version that could explain this 
behavior,
despite the original implementation being a mixin. So I 
thought, well
maybe the delegate passed to "rt_attachDisposeEvent(obj, 
&unhook);" must
be an object delegate (that's would be why the mixin was 
needed), but
after digging in object_.d I did not find any code assuming 
that the

delegate was an object delegate. Any ideas on this?

Another thing I'd like to ask Walter, is what the "L1:" label 
is for in
connect(), is it just some left over or has it some special 
internal

compiler thing meaning?

What do you think?

Best regards,

Robert


Hi!Could you write some examples for struct and non-object 
delegates?




Re: std.signals2 proposal

2012-11-05 Thread Robert

> Hi!Could you write some examples for struct and non-object 
> delegates?
> 

Sure!

Something like:

struct Observer {
void observe(int a, int b) {
// ...
}
}

void main() {
Signal!(int, int) s1;
Signal!int s2
Observer o;
s1.connect!Object(null, (null_object, a, b) => o.observe(a, b));
s2.connect!Object(null, (null_object, a) => o.observe(7, a));

}

Having the delegate accept a null parameter might not be pretty, but I
consider this a good thing, because of the changed semantics: The signal
will keep a reference to the struct now, so the signals weak reference
semantics are no longer in place. (If struct is allocated on the heap,
it won't be freed as long as the signal is alive.)
But it is possible and safe. And if you know what you are doing also
very reasonable. 

But the main benefit is not that you can connect to structs (which is a
side effect), but that you can use wrapping delegates which do parameter
adoptions. That's the killer feature that proved to be so indispensable
and neat for me and others.

If really required it would not be to hard to provide an overload of
connect() which takes a struct pointer directly, just like the one
taking an object, but because of the changed semantics and the rare uses
I'd expect, probably not worthwhile. But comments are appreciated.





Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Jonathan M Davis
On Monday, November 05, 2012 15:48:41 deadalnix wrote:
> HS Teoh explained it nicely.
> 
> The responsibility of using .transient or not belong to the consumer.
> Only the consumer can know if a transient range is suitable.
> 
> So you don't wrap a transient range. You wrap a non transient range,
> and, if the consumer is able to handle the transcient version, it call
> .transient on its source, that call it on its source, etc . . . up to
> the real source.
> 
> If one transformer is unable to handle transient range, the it don't
> pass .transient to its source.

You still need to wrap it in every wrapper range which could possibly support 
transience. So, this affects every single range which could possibly support 
transience.

At least with Andrei's proposal, transience is explicitly restricted to input 
ranges, which seriously reduces the problems caused by them, particularly 
since so few functions can really function with just an input range.

- Jonathan M Davis


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 19:42, Jonathan M Davis a écrit :

On Monday, November 05, 2012 15:48:41 deadalnix wrote:

HS Teoh explained it nicely.

The responsibility of using .transient or not belong to the consumer.
Only the consumer can know if a transient range is suitable.

So you don't wrap a transient range. You wrap a non transient range,
and, if the consumer is able to handle the transcient version, it call
.transient on its source, that call it on its source, etc . . . up to
the real source.

If one transformer is unable to handle transient range, the it don't
pass .transient to its source.


You still need to wrap it in every wrapper range which could possibly support
transience. So, this affects every single range which could possibly support
transience.



As shown before, most wrapper range wouldn't have to do a thing except 
rewraping with .transient . The typical situation is that a wrapper 
range get its transientness from the wraped range. So it boils down to 
womething like :


struct Wrapper(Wrapped) {
Wrapped e;

// Range implementation

@property auto transient() {
return Wrapper!(typeof(e.transient))(e.transient);
}
}

Considering that doing a wrapper that is compatible with transient 
ranges is already some work and require the writer to be aware of such a 
concept (you can expect most programmer to simply ignore that fact).


The extra work for a wrapper range is really small, and add the benefice 
to ensure that the developer that programmed the wrapper took special 
care to ensure this will work with transient.



At least with Andrei's proposal, transience is explicitly restricted to input
ranges, which seriously reduces the problems caused by them, particularly
since so few functions can really function with just an input range.



This proposal is simplistic. array() is not even implementable with such 
an approach. It is also slower for several use cases shown in this thread.


And finally, it is likely that many non transient compatible stuff will 
proliferate, leading to undefined behavior all over the place.


Simply telling to people to follow some guideline is not going to work. 
Many lead devs have experienced that with small teams, and we are 
talking here about every single D user.


Re: std.signals2 proposal

2012-11-05 Thread Zhenya

On Monday, 5 November 2012 at 19:07:13 UTC, Robert wrote:


Hi!Could you write some examples for struct and non-object 
delegates?




Sure!

Something like:

struct Observer {
void observe(int a, int b) {
// ...
}
}

void main() {
Signal!(int, int) s1;
Signal!int s2
Observer o;
	s1.connect!Object(null, (null_object, a, b) => o.observe(a, 
b));

s2.connect!Object(null, (null_object, a) => o.observe(7, a));

}

Having the delegate accept a null parameter might not be 
pretty, but I
consider this a good thing, because of the changed semantics: 
The signal
will keep a reference to the struct now, so the signals weak 
reference
semantics are no longer in place. (If struct is allocated on 
the heap,

it won't be freed as long as the signal is alive.)
But it is possible and safe. And if you know what you are doing 
also

very reasonable.

But the main benefit is not that you can connect to structs 
(which is a
side effect), but that you can use wrapping delegates which do 
parameter
adoptions. That's the killer feature that proved to be so 
indispensable

and neat for me and others.

If really required it would not be to hard to provide an 
overload of
connect() which takes a struct pointer directly, just like the 
one
taking an object, but because of the changed semantics and the 
rare uses
I'd expect, probably not worthwhile. But comments are 
appreciated.


I am embarrassed a little that a member function of the structure 
looks like a static function,maybe it would be better if connect 
took struct pointer directly.I think if struct become immortal it 
will not be a big trouble,in other

case we have disconnect,that will help us.

Sorry for my awful english


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Mon, Nov 05, 2012 at 01:42:47PM -0500, Jonathan M Davis wrote:
> On Monday, November 05, 2012 15:48:41 deadalnix wrote:
> > HS Teoh explained it nicely.
> > 
> > The responsibility of using .transient or not belong to the consumer.
> > Only the consumer can know if a transient range is suitable.
> > 
> > So you don't wrap a transient range. You wrap a non transient range,
> > and, if the consumer is able to handle the transcient version, it call
> > .transient on its source, that call it on its source, etc . . . up to
> > the real source.
> > 
> > If one transformer is unable to handle transient range, the it don't
> > pass .transient to its source.
> 
> You still need to wrap it in every wrapper range which could possibly
> support transience. So, this affects every single range which could
> possibly support transience.

You *can* wrap it if the wrapper range can support transience. It
doesn't *have* to be wrapped. That's what I like about deadalnix's
proposal -- do nothing, and you get *correct* behaviour. Do something,
and you make it faster. Sounds like a good deal to me.

Besides, almost *all* of those wrapper ranges are currently _broken_ for
transient ranges. You get undefined behaviour when you inadvertently
pass a transient range to them. No matter what you do, this has to be
fixed, one way or another. By fixing *all* ranges to be non-transient by
default (and, as you say, there are only a scant few of them -- byLine
is the only Phobos example I can think of), we fix all of this broken
behaviour instantly. The rest is optional optimization.


> At least with Andrei's proposal, transience is explicitly restricted
> to input ranges, which seriously reduces the problems caused by them,
> particularly since so few functions can really function with just an
> input range.
[...]

With Andrei's proposal, all code that assumes transient .front with
input ranges are broken by definition. I've looked over std.algorithm --
there are a *lot* of places with this assumption. Instead of getting
correct default behaviour, you get a whole bunch of broken code with
buggy behaviour, unless you first rewrite a lot of code in
std.algorithm (and probably std.range as well).

Furthermore, afterwards there is still no safety net: accidentally
create a transient forward range? You're screwed, std.algorithm breaks
all over the place. You said that ranges are supposed to be easy for
users to create. Well, with Andrei's scheme, all the user has to do is
to write a .save method in his input range, and all of a sudden
everything breaks. The problem is that input ranges allow transient
.front to begin with. Now users have to remember, once I add .save, I
have to make .front non-transient. This is very counterintuitive to me.
I'm extending a range to make it usable as a forward range, and now
suddenly I can't reuse my buffers anymore? In my mind, forward ranges
should be a refinement of input ranges. So I should be able to just add
more stuff to my input range, and it should become a valid forward
range.  But now this is not true anymore, and the reason? We arbitrarily
decided to make forward ranges non-transient.

By making *all* ranges non-transient by default, we avoid this problem.
Users don't have to remember the strange interaction between .front and
.save. You only get transient ranges when you explicitly ask for it.  So
code is safe by default, and if you know what you're doing, you can make
it faster. And std.array.array actually works correctly 100% of the time
with no further changes.

The current situation is, code is *not* safe by default. Pass a
transient range to std.algorithm, and sometimes it works, sometimes it
breaks. Passing it to std.array.array sometimes works, sometimes
doesn't. Subtle bugs arise everywhere.

With Andrei's proposal, you still have the same problem: forget to
update a Phobos algorithm that expects an input range, and it breaks.
You have to pretty much rewrite every single algorithm in Phobos that
expects an input range, AND complete this rewrite BEFORE code starts
working correctly.  Then after that, every time you write code that
takes an input range, you have to watch out for transient ranges,
otherwise things will break. And std.array.array can no longer take an
input range because it can't copy .front correctly. IOW, input ranges
become almost completely useless.

How is this any better than deadalnix's solution?  From what I can tell,
it's a lot worse, for all of the above reasons.


T

-- 
"Hi." "'Lo."


Re: Why does std.variant not have a tag?

2012-11-05 Thread Robert Jacques

On Monday, 5 November 2012 at 14:13:41 UTC, evansl wrote:

On 11/05/12 00:33, Robert Jacques wrote:
On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne 
Petersen

wrote:

On 05-11-2012 00:31, evansl wrote:


[snip]


If std.Algebraic is like Boost.Variant, then duplicate
bounded types are not allowed and leads to the problem mentioned
in the post on the spirit mailing list which I linked to in my
OP.  OOPS,  now I see why reading that post was not clear 
enough.

Maybe this earlier post in same spirit thread would be clearer.

http://article.gmane.org/gmane.comp.parsers.spirit.general/17113

In particular, note the phrase:

  neither can you use variant
  because variant can't take duplicate types.

This can lead to problems in the spirit parser because
the attributes of parsing:

a | b

where:
  phrase a has an attribute of type A
  phrase b has an attribute of type B
is:

variant

as noted near the bottom of:


http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html

and if A and B are the same, then there's a problem because
Boost.variant can't handle duplicates.

Hope that's clearer.

-regards,
Larry


Thank you for the clarification. Implementing an id seems 
reasonable feature request for algebraic. I've added a bugzilla 
request for it: 
http://d.puremagic.com/issues/show_bug.cgi?id=8962 Please have a 
look in case I missed anything.



BTW, recently there was a review of
another Boost library that has some similarity to
Boost.any.  It's called type_erasure:


http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html

Since std.Variant is similar to Boost.any (as noted above),
and since Boost.any is, in some ways, like Boost.type_erasure,
and since you're working on a revised std.Variant,
you might be interested in looking at type_erasure.


Thanks, I'll take a look at it.


Pegged Master - Semantic Actions - dmd 2.060

2012-11-05 Thread Rosetta Coder

Hi Mr. Sigaud,

I seem to have run into some issues with "Semantic Actions"... I 
can't get it working, neither from following the 
tutorial-description nor from attempting to compile the official 
xml example.


rdmd.exe --main pegged\examples\xml.d
pegged\examples\xml.d(59): Error: found ')' instead of statement
pegged\examples\xml.d(59): Error: found ')' instead of statement

If I remove:
{opening} {closing}

then it works just fine... otherwise, thanks for an amazing piece 
of engineering!




Re: Why does std.variant not have a tag?

2012-11-05 Thread evansl
On 11/05/12 13:53, Robert Jacques wrote:
> On Monday, 5 November 2012 at 14:13:41 UTC, evansl wrote:
>> On 11/05/12 00:33, Robert Jacques wrote:
>>> On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen
>>> wrote:
 On 05-11-2012 00:31, evansl wrote:
> 
> [snip]
> 
>> If std.Algebraic is like Boost.Variant, then duplicate
>> bounded types are not allowed and leads to the problem mentioned
>> in the post on the spirit mailing list which I linked to in my
>> OP.  OOPS,  now I see why reading that post was not clear enough.
>> Maybe this earlier post in same spirit thread would be clearer.
>>
>> http://article.gmane.org/gmane.comp.parsers.spirit.general/17113
>>
>> In particular, note the phrase:
>>
>>   neither can you use variant
>>   because variant can't take duplicate types.
>>
>> This can lead to problems in the spirit parser because
>> the attributes of parsing:
>>
>> a | b
>>
>> where:
>>   phrase a has an attribute of type A
>>   phrase b has an attribute of type B
>> is:
>>
>> variant
>>
>> as noted near the bottom of:
>>
>>
>> http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html
>>
>>
>> and if A and B are the same, then there's a problem because
>> Boost.variant can't handle duplicates.
>>
>> Hope that's clearer.
>>
>> -regards,
>> Larry
> 
> Thank you for the clarification. Implementing an id seems reasonable
> feature request for algebraic. I've added a bugzilla request for it:
> http://d.puremagic.com/issues/show_bug.cgi?id=8962 Please have a look in
> case I missed anything.

The bugzilla request looks good to me, especially the way that the
tuple and algebraic are made as similar as possible.  As I mentioned
before, the thing that's similar is the metafunction mapping from
tags to types.  Maybe that could be a future enhancement.

BTW, the idea of this metafunction map I first found in NuPrl, where
these types of functions are called type-valued functions, expressed as:

  B:(A -> U_1)

where U_1 represents all the types, primitive and user defined, in c++,
and A is something like an enum or unsigned or some other type serving
as the set of possible tag values.

The above B expression is found here:

http://www.nuprl.org/book/Introduction_Type_Theory.html#SECTION00321000


where it's used to define:

  dependent functions (corresponding to std.tuple)
  dependent products  (corresponding to std.Algebraic)

Thought you might find that interesting, as I did.
> 
>> BTW, recently there was a review of
>> another Boost library that has some similarity to
>> Boost.any.  It's called type_erasure:
>>
>>
>> http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html
>>
>>
>> Since std.Variant is similar to Boost.any (as noted above),
>> and since Boost.any is, in some ways, like Boost.type_erasure,
>> and since you're working on a revised std.Variant,
>> you might be interested in looking at type_erasure.
> 
> Thanks, I'll take a look at it.

IIRC, the main difference between Boost.any and Boost.type_erasure is
type_erasure can be used to put some constraints on the contained type
such as requiring the type to support certain functions.
I think type_erasure calls the constraints concepts.  You can search for
"type_erasure" here:

  http://thread.gmane.org/gmane.comp.lib.boost.devel

to access some interesting discussions.

HTH.
-regards,
Larry




-regards,



Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/5/12 9:45 PM, H. S. Teoh wrote:

Besides, almost *all* of those wrapper ranges are currently _broken_ for
transient ranges. You get undefined behaviour when you inadvertently
pass a transient range to them.


It's not undefined behavior, it's just surprising behavior. UB would be 
a fair amount more worrisome.



With Andrei's proposal, all code that assumes transient .front with
input ranges are broken by definition.


I think this should be: all code that DOES NOT assume transient .front 
with input ranges is broken.



I've looked over std.algorithm --
there are a *lot* of places with this assumption. Instead of getting
correct default behaviour, you get a whole bunch of broken code with
buggy behaviour, unless you first rewrite a lot of code in
std.algorithm (and probably std.range as well).


Could you please put together a list of these algorithms so we have it? 
Thanks.



Furthermore, afterwards there is still no safety net: accidentally
create a transient forward range?


But that goes for any incorrect range.


How is this any better than deadalnix's solution?  From what I can tell,
it's a lot worse, for all of the above reasons.


I think we should start from here: the .transient proposal will not be 
accepted because it is too complex. Consider it a baseline that other 
proposals would be evaluated against. Then let's see how to devise a 
robust, simple solution.



Andrei


Re: Why does std.variant not have a tag?

2012-11-05 Thread Era Scarecrow

On Sunday, 4 November 2012 at 22:31:56 UTC, evansl wrote:

Yet, the wiki page:
  http://en.wikipedia.org/wiki/Tagged_union
says:
  a tag field explicitly indicates which one is in use.

and I don't see any indication of a tag field in the 
std_variant.html


 I remember a while back asking about the variant. I wanted to be 
able to specify an area in memory and say 'this is xxx', but 
couldn't; This was to help avoid having to manually make and 
manage something like 60 structs and far more complex code to 
manage that.


 This leads me to develop my own version (for built-in types); My 
version isn't anywhere complete (or clean enough) for 
publication, but enough for my own project (as read-only use).



 Hmmm curiously enough, i might be able to convert/rebuild by 
using a polymorphic struct that I'm tinkering with, but that 
seems like a lot of extra work.


DConf 2013 to be recorded

2012-11-05 Thread Andrei Alexandrescu
I updated 
http://www.kickstarter.com/projects/2083649206/the-d-programming-language-conference-2013-0 
as follows:


=
Late-Breaking News: Smile, You're On Camera!

It's confirmed - through volunteer support, the conference talks will be 
recorded and posted on the Net for free! We're preparing diligently to 
ensure professional quality recordings. One more reason to pledge even 
if for those of you who can't be there!

=

We have two volunteers who offered; I'm not naming them because I don't 
know whether they want to take the responsibility burden at this point. 
If you do, just reply to this!



Andrei


Re: DConf 2013 to be recorded

2012-11-05 Thread Ali Çehreli

On 11/05/2012 02:10 PM, Andrei Alexandrescu wrote:

I updated
http://www.kickstarter.com/projects/2083649206/the-d-programming-language-conference-2013-0
as follows:

=
Late-Breaking News: Smile, You're On Camera!

It's confirmed - through volunteer support, the conference talks will be
recorded and posted on the Net for free! We're preparing diligently to
ensure professional quality recordings. One more reason to pledge even
if for those of you who can't be there!
=

We have two volunteers who offered; I'm not naming them because I don't
know whether they want to take the responsibility burden at this point.
If you do, just reply to this!


Andrei


Thanks Andrei! I promise that the talks will be recorded and published. :)

Ali


Re: DConf 2013 to be recorded

2012-11-05 Thread Iain Buclaw
On 5 November 2012 22:18, Ali Çehreli  wrote:
> On 11/05/2012 02:10 PM, Andrei Alexandrescu wrote:
>>
>> I updated
>>
>> http://www.kickstarter.com/projects/2083649206/the-d-programming-language-conference-2013-0
>> as follows:
>>
>> =
>> Late-Breaking News: Smile, You're On Camera!
>>
>> It's confirmed - through volunteer support, the conference talks will be
>> recorded and posted on the Net for free! We're preparing diligently to
>> ensure professional quality recordings. One more reason to pledge even
>> if for those of you who can't be there!
>> =
>>
>> We have two volunteers who offered; I'm not naming them because I don't
>> know whether they want to take the responsibility burden at this point.
>> If you do, just reply to this!
>>
>>
>> Andrei
>
>
> Thanks Andrei! I promise that the talks will be recorded and published. :)
>
> Ali

And I'll bring a picture camera to take photos.

Could also bring a recording device, incase the recorded audio on the
video is poor :o)

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';


Re: DConf 2013 to be recorded

2012-11-05 Thread Walter Bright
On 11/5/2012 2:33 PM, Iain Buclaw wrote:> Could also bring a recording device, 
incase the recorded audio on the

> video is poor :o)

I can recommend a backup recording. I had a talk of mine once that got video, 
but no audio, because the mike was accidentally left off. It was a smallish 
venue, so nobody noticed it was off.


Heck, an ipod can do it.



Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 05/11/2012 22:51, Andrei Alexandrescu a écrit :

On 11/5/12 9:45 PM, H. S. Teoh wrote:

Besides, almost *all* of those wrapper ranges are currently _broken_ for
transient ranges. You get undefined behaviour when you inadvertently
pass a transient range to them.


It's not undefined behavior, it's just surprising behavior. UB would be
a fair amount more worrisome.



Unless you know the internal implementation of the range, it is 
undefined (nothing in the spec specify what the range does in this case, 
which IS undefined behavior).



With Andrei's proposal, all code that assumes transient .front with
input ranges are broken by definition.


I think this should be: all code that DOES NOT assume transient .front
with input ranges is broken.



You never addressed the std.array.array() problem. Neither the fact that 
forward ranges may require to be transient (I have that in my rubik's 
cube solver, and H. S. Teoh seems to needs that too).



How is this any better than deadalnix's solution? From what I can tell,
it's a lot worse, for all of the above reasons.


I think we should start from here: the .transient proposal will not be
accepted because it is too complex. Consider it a baseline that other
proposals would be evaluated against. Then let's see how to devise a
robust, simple solution.



I'd like to see a proposal discarded in favor of a better proposal. I'm 
certain I can say that we don't have one. Let me explain what is wrong 
in your proposal (=> forward range = non transient / input range = 
transient).


First two concepts are packed into one. I can safely say that both are 
not related, and uses cases has already been presented in all possible 
combination of input/forward transient or not. This usually seems like a 
win, but ends up creating a more complex situation at the ends. I've 
made that mistake quite a lot of time myself, surely enough to be sure 
that this is a bad idea.


See for instance how the private method made final automagicaly (which 
sounds nice at first) create inconsistent behavior when it come to NVI 
as explained in TDPL. This is typical of how different concept packed 
into one tends to explode at some point.


Additionally, the proposed solution put a responsibility on the 
developer : he/she must ensure that all its code with input ranges is 
compatible with transient range.


The fact is that transient stuff are highly unusual in most programming 
languages (even when possible, it is usually avoided like plague), and 
that all input ranges will not be transient. This WILL result in a lot 
of code in the field using input range but not supporting when it is 
transient.


Putting the responsibility on the programmer never worked since 
programmer exists, and it is not going to improve soon.


Re: C++ to catch up?

2012-11-05 Thread Marco Leise
Am Mon, 05 Nov 2012 13:10:35 +0100
schrieb "Paulo Pinto" :

> On Monday, 5 November 2012 at 11:06:39 UTC, monarch_dodra wrote:
> > On Monday, 5 November 2012 at 10:22:02 UTC, Nick Sabalausky 
> > wrote:
> >> On Mon, 05 Nov 2012 11:00:27 +0100
> >> "jdrewsen"  wrote:
> >>
> >>> It seems like the C++ committee is speeding up development 
> >>> adding lots of the goodies from D like Ranges, static if, 
> >>> template contraints etc.
> >>> 
> >>> Will D still have a case when C++ gets this done?
> >>> 
> >>
> >>
> >> Yes, even if they go and add all of D's features, D will still 
> >> be much
> >> cleaner. (IMO)
> >
> > C++'s "range" is actually a wrapper over an iterator 
> > "first-last" pair. While it does bring the convenience of D's 
> > ranges to C++, it remains hobbled in terms of efficiency and 
> > implementation. C++'s paradigm is pointers and iterators. At 
> > best, you can sparkle some ranges over it, but you'll never 
> > shift the paradigm.
> >
> > 
> > The thing with C++'s new feature is that it requires developers 
> > to be on the bleeding edge of C++ knowledge. It's fine for the 
> > enthusiasts that read programming journals on their week-ends 
> > (like you and I), but not for the standard developer. Not to 
> > mention, even then, the syntax is hard as hell: lambdas in for 
> > loops? I have to look up the syntax every time. automatic type 
> > inference of the return value of a function? "auto foo() -> 
> > declype(...)", what...?
> >
> > All these functionalities are great, but also out of reach. 
> > Most of my colleagues still struggle with "simple" design 
> > patters such as strategies, or just plain algorithms with 
> > functors. Everytime I say something like "awesome, C++ will 
> > allow type inference" or "yay, RValue references!" they look at 
> > me like I'm some kind of weird space alien...
> >
> > 
> > D packages the whole thing in an easy to use but complete 
> > package. C++ just stacks complicated stuff on top of a hard to 
> > use core.
> 
> I have the same feeling with some of our developers.
> 
> Simpler languages tend to be manager friendly. It is always 
> easier to find cheap resources.
> 
> In my currently employer I have only done Java and C# projects so 
> far, and I still fear the day I might do a C or C++ project, 
> given the type of knowledge shown by some of our coworkers.
> 
> 
> --
> Paulo

Are you talking bad about your colleagues behind their backs ?
Hey, if I was to write a project in Haskell I'd be the idiot,
too.

-- 
Marco



Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 1:26 AM, deadalnix wrote:

Le 05/11/2012 22:51, Andrei Alexandrescu a écrit :

On 11/5/12 9:45 PM, H. S. Teoh wrote:

Besides, almost *all* of those wrapper ranges are currently _broken_ for
transient ranges. You get undefined behaviour when you inadvertently
pass a transient range to them.


It's not undefined behavior, it's just surprising behavior. UB would be
a fair amount more worrisome.



Unless you know the internal implementation of the range, it is
undefined (nothing in the spec specify what the range does in this case,
which IS undefined behavior).


That would be unspecified behavior.


With Andrei's proposal, all code that assumes transient .front with
input ranges are broken by definition.


I think this should be: all code that DOES NOT assume transient .front
with input ranges is broken.



You never addressed the std.array.array() problem. Neither the fact that
forward ranges may require to be transient (I have that in my rubik's
cube solver, and H. S. Teoh seems to needs that too).


How is this any better than deadalnix's solution? From what I can tell,
it's a lot worse, for all of the above reasons.


I think we should start from here: the .transient proposal will not be
accepted because it is too complex. Consider it a baseline that other
proposals would be evaluated against. Then let's see how to devise a
robust, simple solution.



I'd like to see a proposal discarded in favor of a better proposal. I'm
certain I can say that we don't have one.


Good solutions are found in the minds of people. Starting from the idea 
that .transient is unacceptably complicated, work from that angle. You 
can't claim you have reached perfection in design can you?



Let me explain what is wrong
in your proposal (=> forward range = non transient / input range =
transient).


I am well aware of the relative tradeoffs. Arguing for .transient is 
futile at this point. What we need to do is find something better.



Andrei


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 06/11/2012 01:21, Andrei Alexandrescu a écrit :

I'd like to see a proposal discarded in favor of a better proposal. I'm
certain I can say that we don't have one.


Good solutions are found in the minds of people. Starting from the idea
that .transient is unacceptably complicated, work from that angle. You
can't claim you have reached perfection in design can you?



I certainly don't ! I'd be happy to switch to another solution granted 
it is superior. I just don't see any right now, which obviously don't 
mean none exist.



Let me explain what is wrong
in your proposal (=> forward range = non transient / input range =
transient).


I am well aware of the relative tradeoffs. Arguing for .transient is
futile at this point. What we need to do is find something better.



To be honest, my biggest fear isn't that this proposal is rejected, but 
that we fallback as default on the input range = transient / forward 
range = non transient scheme, because we fail to come up with something 
better, or that the status quo is choosen (as both seems to me worse 
than the .transient proposal).


Now, as previously said, if someone come up with something better, I'd 
be happy to drop it completely. I'm not pushing this proposal because it 
is mine.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Mon, Nov 05, 2012 at 11:51:35PM +0200, Andrei Alexandrescu wrote:
[...]
> >With Andrei's proposal, all code that assumes transient .front with
> >input ranges are broken by definition.
> 
> I think this should be: all code that DOES NOT assume transient
> .front with input ranges is broken.

Then std.array.array is broken by definition, and cannot be implemented
with anything less than a forward range. This will very likely break a
lot of existing code.


> >I've looked over std.algorithm -- there are a *lot* of places with
> >this assumption. Instead of getting correct default behaviour, you
> >get a whole bunch of broken code with buggy behaviour, unless you
> >first rewrite a lot of code in std.algorithm (and probably std.range
> >as well).
> 
> Could you please put together a list of these algorithms so we have
> it? Thanks.

This is probably an incomplete list, but it's a start:

std.algorithm.reduce - when no seed is given.
std.algorithm.joiner - both variants (I have a fix for the second variant)
std.algorithm.group
std.algorithm.minCount
(std.algorithm.minPos - but takes forwardRange, so probably OK)
(std.algorithm.Levenshtein - takes forwardRange, probably OK)
(std.algorithm.makeIndex - takes forwardRange, probably OK)
std.algorithm.splitter - tries to take slices without checking if range is 
sliceable
std.algorithm.uniq
std.algorithm.topNCopy - copies .front of input range.
std.algorithm.NWayUnion - copies .front of (possibly input) outer range into a 
heap
(std.algorithm.largestPartialIntersection - uses NWayUnion)
std.array.array - tries to copy input range
std.array.insertInPlace - tries to copy input range
std.array.join - tries to copy input range
std.stdio.writeln - there's too much code here so I didn't narrow it
down, but testing with a transient range shows that it doesn't
work correctly. This probably implicates std.format somewhere.

I didn't check the other Phobos modules, but basically any code that
currently takes an input range needs to be audited for this issue.


[...]
> >How is this any better than deadalnix's solution?  From what I can tell,
> >it's a lot worse, for all of the above reasons.
> 
> I think we should start from here: the .transient proposal will not
> be accepted because it is too complex. Consider it a baseline that
> other proposals would be evaluated against. Then let's see how to
> devise a robust, simple solution.
[...]

I still think forcing input ranges to be transient is oversimplifying
the issue. Whether a range is transient is orthogonal to whether you can
.save the current position or whether you can traverse it in two
directions. Trying to conflate the two only leads to leaky abstractions.

The only real solution IMO is to address the issue head-on: either
recognize transience as an inherent property of ranges, or (re)define
ranges to exclude all transience.

If we recognize transience as an inherent property of ranges, then no
matter what we do, there's going to be complications, because you'll
always have to deal with two cases. Either an algorithm can handle
transience, or it can't. If it can't, there needs to be a way to make it
so that it will reject transient ranges somehow. With deadalnix's
proposal, the overhead of doing this is more or less minimized, but it
is still there.

If we exclude all transience, then there is no additional complication.
We just have to fix the current code and make it crystal clear in the
documentation that .front must always be persistent no matter what. The
disadvantage here is that some algorithms, like find(), don't *need* the
persistence of .front, so you lose generality. Any code that works with
transient ranges will have to stick with foreach, or reinvent
std.algorithm. With .transient proposal, this is the default behaviour,
except that we have the *option* of using transient ranges if both the
range type and the algorithm can handle it.

So the .transient proposal is pretty close to a comfortable balance
between the two extremes. If it is still considered too complicated,
then I'd like to hear what other proposals will address all the
underlying issues in just as nice a way (or an even nicer way), without
compromising this balance between the two extremes.


T

-- 
In order to understand recursion you must first understand recursion.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Jonathan M Davis
On Monday, November 05, 2012 16:49:42 H. S. Teoh wrote:
> On Mon, Nov 05, 2012 at 11:51:35PM +0200, Andrei Alexandrescu wrote:
> [...]
> 
> > >With Andrei's proposal, all code that assumes transient .front with
> > >input ranges are broken by definition.
> > 
> > I think this should be: all code that DOES NOT assume transient
> > .front with input ranges is broken.
> 
> Then std.array.array is broken by definition, and cannot be implemented
> with anything less than a forward range. This will very likely break a
> lot of existing code.

We can create an hasTransientFront trait for checking whether front is 
transient or not. It can't be 100% accurate, but it would fall on the side of 
declaring something transient when it wasn't, so it wouldn't declare something 
transient to be non-transient. Then any range for which hasTransientFront was 
false could work with std.array.array. For the rest, they can do something 
like

auto arr = std.array.array(map!"a.dup"(file.byLine()));

But it's certainly true that fixing std.array.array will break code, which is 
annoying. But as long as front can be transient, there's no way around that. 
byLine cannot possibly work with std.array.array as it stands. The only 
solutions that I see at this point are

1. Exclude transience completely.

2. Mark ranges as transient in some way and force algorithms to take this new 
trait into account.

3. Insist that input ranges have transient fronts (save perhaps when it can be 
statically verified that they aren't based on front's type) and that anything 
requiring a non-transient front require forward ranges.

4. Make all ranges non-transient but provide a way to get at a transient 
version of it and force algorithms to take this new property into account.

All 4 solutions have problems. They just have different problems.

> I still think forcing input ranges to be transient is oversimplifying
> the issue. Whether a range is transient is orthogonal to whether you can
> .save the current position or whether you can traverse it in two
> directions. Trying to conflate the two only leads to leaky abstractions.

I completly agree that transience and whether something is an input range are 
orthogonal, but we need to simplify.

> The only real solution IMO is to address the issue head-on: either
> recognize transience as an inherent property of ranges, or (re)define
> ranges to exclude all transience.

Personally, I'm all for excluding transience completely and insisting that 
anything which would be transient use opApply, but Andrei doesn't like that 
idea. It would certainly be the simplest solution though, and it probably 
wouldn't really cause much of a problem for ranges like ByLine, because in 
most cases what you do is use them with a foreach loop. std.array.array would 
be the main loss there, but if opApply is used for foreach rather than the 
range functions (I don't know which currently gets precedence), then ByLine 
can become a normal range when used with range functions (i.e. no transience) 
and just reuse its buffer with opApply. Then it would work with range-based 
functions but still avoid extra allocations when simply iterating over it. 
That would be my ideal solution at this point, but clearly not everyone 
agrees.

- Jonathan M Davis


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Tue, Nov 06, 2012 at 01:44:28AM +0100, deadalnix wrote:
> Le 06/11/2012 01:21, Andrei Alexandrescu a écrit :
[...]
> >Good solutions are found in the minds of people. Starting from the
> >idea that .transient is unacceptably complicated, work from that
> >angle. You can't claim you have reached perfection in design can you?

I'd like to hear a counterproposal to the .transient idea. Let's not get
into a battle of words with nothing on the table to discuss.


[...]
> To be honest, my biggest fear isn't that this proposal is rejected,
> but that we fallback as default on the input range = transient /
> forward range = non transient scheme, because we fail to come up with
> something better, or that the status quo is choosen (as both seems to
> me worse than the .transient proposal).
[...]

Yeah, that is my fear also. Which is why I'm making noise about this
issue.

The status quo is definitely out of the question, as it leads to
undefined/unspecified behaviour with basically no warning.

Conflating transience with input range is not workable IMO, because it
leads to leaky abstractions like transient forward ranges being
considered non-forward ranges because we arbitrarily decided that
forward ranges cannot be transient. I've already given a number of
non-trivial examples of transient forward ranges, and apparently
deadalnix has also encountered the same issue. Denying these cases just
for the sake of holding on to an idealized abstraction is only further
proof that the abstraction is leaky. We all know from experience that
leaky abstractions will only lead to trouble down the road.

The only other remaining proposal so far is Jonathan's, that is to
redefine all ranges to be non-transient. Then we fix byLine() to be
non-transient, and everything else will work with no further trouble.
We also don't get to use std.algorithm with any transient ranges, and
will in all likelihood reinvent std.algorithm everywhere a transient
range pops up. I don't see this as a viable solution either.

So the .transient idea currently seems to be the best we have. I'd love
to hear a superior proposal, if there is one.


T

-- 
I don't trust computers, I've spent too long programming to think that
they can get anything right. -- James Miller


How do you remove/insert elements in a dynamic array without allocating

2012-11-05 Thread Malte Skarupke

Let's say I want to


How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Malte Skarupke

Following code:

void main()
{
import core.memory;
GC.disable();
scope(exit) GC.enable();

int[] a = [1, 2, 3, 4, 5];
foreach(i; 0 .. 10)
{
--a.length;
a ~= i;
}
}

That loop will keep on allocating in every iteration until your 
memory is full.


Is there a way to do something similar to this without 
allocating? I have also tried slicing:

a = a[0 .. $ - 1]; // instead of (--a.length;)

But neither one works.

How do you work with the dynamic array without having to rely on 
the GC all the time? I want something similar to the stl vector, 
which only re-allocates once your array grows past a certain 
size, not on every append.


Thanks!

Malte


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Ali Çehreli

On 11/05/2012 05:11 PM, Malte Skarupke wrote:

Following code:

void main()
{
import core.memory;
GC.disable();
scope(exit) GC.enable();

int[] a = [1, 2, 3, 4, 5];
foreach(i; 0 .. 10)
{
--a.length;
a ~= i;
}
}

That loop will keep on allocating in every iteration until your memory
is full.

Is there a way to do something similar to this without allocating? I
have also tried slicing:
a = a[0 .. $ - 1]; // instead of (--a.length;)

But neither one works.

How do you work with the dynamic array without having to rely on the GC
all the time? I want something similar to the stl vector, which only
re-allocates once your array grows past a certain size, not on every
append.

Thanks!

Malte


I think you want assumeSafeAppend() as explained here:

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

Ali


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Jonathan M Davis
On Tuesday, November 06, 2012 02:11:06 Malte Skarupke wrote:
> Following code:
> 
> void main()
> {
> import core.memory;
> GC.disable();
> scope(exit) GC.enable();
> 
> int[] a = [1, 2, 3, 4, 5];
> foreach(i; 0 .. 10)
> {
> --a.length;
> a ~= i;
> }
> }
> 
> That loop will keep on allocating in every iteration until your
> memory is full.
> 
> Is there a way to do something similar to this without
> allocating? I have also tried slicing:
> a = a[0 .. $ - 1]; // instead of (--a.length;)

There's no real difference between those two.

> But neither one works.
> 
> How do you work with the dynamic array without having to rely on
> the GC all the time? I want something similar to the stl vector,
> which only re-allocates once your array grows past a certain
> size, not on every append.

Arrays do work that way. They have capacity, and they have reserve. They only 
append when they don't have enough memory or they're not the last slice in the 
block. The problem is that if you remove elements, the runtime doesn't know if 
there's another slice pointing to the element which was just removed, so it 
has to assume that that there is, and it'll be forced to reallocate when 
appending.

If you _know_ that there are no slices of anything beyond the end of the 
array, then you can call assumeSafeAppend on the array, and then the runtime 
will mark it as the last slice in the block, and appending won't reallocate 
unless it actually runs out of space in the block (or you end up removing 
another element without calling assumeSafeAppend or you end up with a slice 
which contains elements beyond the end of that array - e.g. if you slice the 
array and then append to the slice). So, in this particular case, 
assumeSafeAppend would solve your problem. Whether it works in your program in 
general depends on what your program is doing. And if you want to make sure
that the array has enough space before appending to it a bunch, then you can
use reserve. However, if you're specifically building an array, you should
probably look at std.array.Appender. Don't remove elements from that though.
It's just for making appending more efficient, not for being used once the
array has been fully constructed.

If you haven't read it yet, I'd strongly advise reading this article on arrays 
in D:

http://dlang.org/d-array-article.html

- Jonathan M Davis


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread bearophile

Malte Skarupke:


void main()
{
import core.memory;
GC.disable();
scope(exit) GC.enable();

int[] a = [1, 2, 3, 4, 5];
foreach(i; 0 .. 10)
{
--a.length;
a ~= i;
}
}

That loop will keep on allocating in every iteration until your 
memory is full.


Is there a way to do something similar to this without 
allocating?


void main() {
auto array = [1, 2, 3, 4, 5];
array.assumeSafeAppend();
foreach (i; 0 .. 10_000_000) {
array.length--;
array ~= i;
}
}




But neither one works.


And that's good, it was designed that way on purpose :-)


How do you work with the dynamic array without having to rely 
on the GC all the time?


There are various ways to do it...


I want something similar to the stl vector, which only 
re-allocates once your array grows past a certain size, not on 
every append.


D arrays already work like this.

Bye,
bearophile


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Jonathan M Davis
On Tuesday, November 06, 2012 02:27:24 bearophile wrote:
> void main() {
> auto array = [1, 2, 3, 4, 5];
> array.assumeSafeAppend();
> foreach (i; 0 .. 10_000_000) {
> array.length--;
> array ~= i;
> }
> }

assumeSafeAppend needs to be called every time that length is decremented. It 
does nothing in this example, because when it's called, array is already 
marked as the last slice in its block.

- Jonathan M Davis


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 3:06 AM, H. S. Teoh wrote:

I've already given a number of
non-trivial examples of transient forward ranges, and apparently
deadalnix has also encountered the same issue.


I'd like to build more of this argument. I pointed out that your range 
is actually defining .dup, not .save. I think an argument can be made 
that forward ranges with transient .front do not qualify as forward 
ranges, seeing as a forward range is modeled after a list that actually 
has data sitting in memory.



Andrei


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 2:44 AM, deadalnix wrote:

To be honest, my biggest fear isn't that this proposal is rejected, but
that we fallback as default on the input range = transient / forward
range = non transient scheme, because we fail to come up with something
better, or that the status quo is choosen (as both seems to me worse
than the .transient proposal).


I think the simplification of input range = transient and forward range 
= not transient has a lot going for it. It is simple, easy to explain 
and understand, and builds on simple real-life examples (buffered input 
and singly-linked lists). Clearly adding a new notion to the soup makes 
for more expressiveness, but it also makes for more complexity and 
subtlety in support for niche ranges. This should not be neglected.


Andrei



Re: DConf 2013 on kickstarter.com: we're live!

2012-11-05 Thread ButHead
On Monday, 22 October 2012 at 17:25:28 UTC, Andrei Alexandrescu 
wrote:
We're on! For one month starting today, we're raising funding 
for DConf 2013.


http://www.kickstarter.com/projects/2083649206/the-d-programming-language-conference-2013-0

Please pledge your support and encourage your friends to do the 
same. Hope to see you in 2013!



Thanks,

Andrei


Collecting money to blow up Andrei's EGO even more ?
Hope the show fails.looks good so far.
what about collectimg money for solid, real world projects 
instead of donating to bla bla nonsense parties.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 06/11/2012 02:36, Andrei Alexandrescu a écrit :

On 11/6/12 3:06 AM, H. S. Teoh wrote:

I've already given a number of
non-trivial examples of transient forward ranges, and apparently
deadalnix has also encountered the same issue.


I'd like to build more of this argument. I pointed out that your range
is actually defining .dup, not .save.


Yes my code can also fall in the .dup stuff.

If we actually make that difference, our case is moot, but a hell lot of 
code is broken as well.


For instance, the way map is defined is highly incorrect as each call to 
.front can pop a newly generated element as well, and I'm pretty that 
isn't the only one.


We are here back to equality vs identity, and it seems D also have some 
stuff to fix in that regard (notably struct and AA). Discussing that 
here only make the problem more confuse and is not helping as long as 
this question is open in D.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread deadalnix

Le 06/11/2012 02:40, Andrei Alexandrescu a écrit :

On 11/6/12 2:44 AM, deadalnix wrote:

To be honest, my biggest fear isn't that this proposal is rejected, but
that we fallback as default on the input range = transient / forward
range = non transient scheme, because we fail to come up with something
better, or that the status quo is choosen (as both seems to me worse
than the .transient proposal).


I think the simplification of input range = transient and forward range
= not transient has a lot going for it. It is simple, easy to explain
and understand, and builds on simple real-life examples (buffered input
and singly-linked lists). Clearly adding a new notion to the soup makes
for more expressiveness, but it also makes for more complexity and
subtlety in support for niche ranges. This should not be neglected.



At this point, if transient is out I'd prefer Jonathan's proposal were 
everything is non transient. This is clearly simpler to use and break 
less code.


Indeed, the added complexity of .transient exists. The beauty of it is 
that it is possible to write 100% correct code without even knowing 
.transient exists. This is why I like this option : the added complexity 
only exists for the programmer that what to explore the arcane of the 
language (which include you and me, but not most D users).


Re: DConf 2013 on kickstarter.com: we're live!

2012-11-05 Thread Jesse Phillips

On Monday, 5 November 2012 at 21:57:01 UTC, Ali Çehreli wrote:

On 10/31/2012 05:35 PM, Faux Amis wrote:

> I will pledge 100$ if that would mean videos.

There is a change on the project page: :)

"Late-Breaking News: Smile, You're On Camera!

It's confirmed - through volunteer support, the conference 
talks will be recorded and posted on the Net for free! We're 
preparing diligently to ensure professional quality recordings. 
One more reason to pledge even if for those of you who can't be 
there!"


Ali


That probably should be posted as an Update in kickstarter (not 
just a change to the main page)...


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread bearophile

Jonathan M Davis:

assumeSafeAppend needs to be called every time that length is 
decremented.


Right. (But adding one such call inside a critical loop...).

Bye,
bearophile


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Malte Skarupke
On Tuesday, 6 November 2012 at 01:25:39 UTC, Jonathan M Davis 
wrote:

On Tuesday, November 06, 2012 02:11:06 Malte Skarupke wrote:

Following code:

void main()
{
import core.memory;
GC.disable();
scope(exit) GC.enable();

int[] a = [1, 2, 3, 4, 5];
foreach(i; 0 .. 10)
{
--a.length;
a ~= i;
}
}

That loop will keep on allocating in every iteration until your
memory is full.

Is there a way to do something similar to this without
allocating? I have also tried slicing:
a = a[0 .. $ - 1]; // instead of (--a.length;)


There's no real difference between those two.


But neither one works.

How do you work with the dynamic array without having to rely 
on
the GC all the time? I want something similar to the stl 
vector,

which only re-allocates once your array grows past a certain
size, not on every append.


Arrays do work that way. They have capacity, and they have 
reserve. They only
append when they don't have enough memory or they're not the 
last slice in the
block. The problem is that if you remove elements, the runtime 
doesn't know if
there's another slice pointing to the element which was just 
removed, so it
has to assume that that there is, and it'll be forced to 
reallocate when

appending.

If you _know_ that there are no slices of anything beyond the 
end of the
array, then you can call assumeSafeAppend on the array, and 
then the runtime
will mark it as the last slice in the block, and appending 
won't reallocate
unless it actually runs out of space in the block (or you end 
up removing
another element without calling assumeSafeAppend or you end up 
with a slice
which contains elements beyond the end of that array - e.g. if 
you slice the
array and then append to the slice). So, in this particular 
case,
assumeSafeAppend would solve your problem. Whether it works in 
your program in
general depends on what your program is doing. And if you want 
to make sure
that the array has enough space before appending to it a bunch, 
then you can
use reserve. However, if you're specifically building an array, 
you should
probably look at std.array.Appender. Don't remove elements from 
that though.
It's just for making appending more efficient, not for being 
used once the

array has been fully constructed.

If you haven't read it yet, I'd strongly advise reading this 
article on arrays

in D:

http://dlang.org/d-array-article.html

- Jonathan M Davis


Thanks, that explains it well. I must admit that I didn't fully 
understand slices before. I've read the linked article and am 
baffled that this is seen as acceptable behavior. I will most 
certainly never use dynamic arrays or slices again for anything 
that needs to grow or shrink dynamically.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Tue, Nov 06, 2012 at 02:03:45AM +0100, Jonathan M Davis wrote:
[...]
> The only solutions that I see at this point are
> 
> 1. Exclude transience completely.
> 
> 2. Mark ranges as transient in some way and force algorithms to take
> this new trait into account.
> 
> 3. Insist that input ranges have transient fronts (save perhaps when
> it can be statically verified that they aren't based on front's type)
> and that anything requiring a non-transient front require forward
> ranges.
> 
> 4. Make all ranges non-transient but provide a way to get at a
> transient version of it and force algorithms to take this new property
> into account.
> 
> All 4 solutions have problems. They just have different problems.
[...]

Hmm. Another idea just occurred to me. The basic problem here is that we
are conflating two kinds of values, transient and persistent, under a
single name .front. What if we explicitly name them? Say, .copyFront for
the non-transient value and .refFront for the transient value (the
names are unimportant right now, let's consider the semantics of it).

Then an algorithm like std.array.array can be written something like
this:

auto array(R)(R range) {
auto a = appender!(ElementType!R)();
while (!range.empty) {
// Self-documenting: we expect to get a
// persistent copy of the front value.
a.put(range.copyFront);
range.popFront();
}
return a.data;
}

OTOH, an algorithm that is agnostic to transience, like find(), can be
written something like this:

R find(R,S)(R haystack, S needle) {
while (!haystack.empty) {
// Self-documenting: we don't expect a
// persistent front value.
if (haystack.refFront == needle)
return haystack;
haystack.popFront();
}
return haystack;
}

Of course, this immediately breaks many ranges, because they only have a
single .front currently. Which is bad. So we make use of UFCS:

@property auto copyFront(R)(R range) {
// Not sure how to do this yet, the idea is that
// copyFront should be default.
return range.front;
}
@property auto refFront(R)(R range) {
// By default, .refFront is the same as copyFront.
return range.copyFront;
}

ByLine can then do this:

struct ByLine {
char[] buf;

@property auto copyFront() {
return buf.dup;
}
@property auto refFront() {
return buf;
}
}

I haven't worked out all the details yet, but this is the gist of it.
While it's still not perfect, it is a slight improvement over the
.transient proposal in that no new range types are involved.

There is still the issue of naming: I chose .copyFront and .refFront
just for illustration purposes. I'm thinking probably we can make .front
== .copyFront, so that it will automatically work with (almost) all
current ranges, which should be non-transient. UFCS saves us from having
to implement .refFront for everything except actual transient ranges,
which should be only a few rare cases.

Of course, this has the disadvantage of needing to update existing
algorithms to use .refFront or .copyFront where appropriate -- but then,
we have to do that anyway if we're going to support transient ranges at
all.

Maybe somebody can improve on this idea?


T

-- 
Long, long ago, the ancient Chinese invented a device that lets them see 
through walls. It was called the "window".


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Jonathan M Davis
On Monday, November 05, 2012 18:36:53 H. S. Teoh wrote:
> Hmm. Another idea just occurred to me. The basic problem here is that we
> are conflating two kinds of values, transient and persistent, under a
> single name .front. What if we explicitly name them? Say, .copyFront for
> the non-transient value and .refFront for the transient value (the
> names are unimportant right now, let's consider the semantics of it).

I thought of this a couple days ago but threw it away fairly quickly, because 
it breaks _everything_. And it definitely affects all ranges for the sake of a 
few.

- Jonathan M Davis


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Jonathan M Davis
On Tuesday, November 06, 2012 03:28:09 Malte Skarupke wrote:
> Thanks, that explains it well. I must admit that I didn't fully
> understand slices before. I've read the linked article and am
> baffled that this is seen as acceptable behavior. I will most
> certainly never use dynamic arrays or slices again for anything
> that needs to grow or shrink dynamically.

It has to work this way, or it would totally screw up slices. You can't append 
to a slice which is not the last slice in the block without affecting the 
slices after it, so a reallocation must occur. And it would create too much 
overhead for the runtime to try to figure out whether it's safe for a slice to 
be considered the last slice in the block when you decrement its length. So, 
if you want it to be considered the last one, you have to keep track of it and 
tell the runtime yourself.

This sort of thing wouldn't be a problem if you couldn't slice arrays, but not 
being able to do that would be a huge loss. So, you either need to manage it 
yourself or create a type which will do that for you (e.g. std.container.Array 
should do that, though unfortunately, it looks like it doesn't currently call 
assumeSafeAppend like it should).

- Jonathan M Davis


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Tommi
I don't think this whole issue has anything to do with ranges. I 
think this is an issue of assuming that the symbol = means "copy 
what's on the right to what's on the left". When in reality, = 
could mean: (if what's on the right has reference semantics) 
"make what's on the left reference the same thing that the thing 
on the right references".


I think all range types should be allowed to return whatever they 
want from their front property. It's the responsibility of the 
user of the range to *actually* copy what front returns (if 
that's what he intends), instead of assuming that = means copy.


In the code below, X marks the bug:

module main;

import std.stdio;
import std.range;

class MyData
{
int _value;
}

struct MyFwdRange
{
MyData _myData;

this(MyData md)
{
_myData = md;
}

@property MyData front()
{
return _myData;
}

@property bool empty() const
{
return _myData._value > 10;
}

void popFront()
{
_myData._value++;
}

@property MyFwdRange save() const
{
auto copy = MyFwdRange();
copy._myData = new MyData();
copy._myData._value = _myData._value;
return copy;
}
}

void printFirstAndSecond(R)(R range)
if (isForwardRange!MyFwdRange)
{
// X
auto first = range.front; // That is *not* copying

range.popFront();
writeln(first._value, " ", range.front._value);
}

void main()
{
auto mfr = MyFwdRange(new MyData());

printFirstAndSecond(mfr); // prints: 1 1 (instead of 0 1)
}


Re: std.signals2 proposal

2012-11-05 Thread Ellery Newcomer



On 11/05/2012 05:36 AM, Robert wrote:

I just developed a proof-of-concept implementation of an improved
std.signals.


Cool.


1. Passing a delegate to connect, which basically is an extended (void*)
and assuming it is an object delegate, does not feel quite right in D,
where we usually try to guarantee correctness by the compiler wherever
possible.


Not sure I understand why such hatred is rational?


Point 2 does not really bother me,


It bothers me.



So I tried to improve std.signals, code:
(warning at least one bug is remaining, explained below)

https://github.com/eskimor/phobos/tree/new_signal


in emit:

if(slot.indirect.ptr) {
 
}else{
 
 slot.indirect.ptr = 
 slot.indirect(i);
}

 will not be executed more than once?

in addSlot:

you use malloc &friends to allocate objs, but the gc to allocate slots? 
The correct thing to do here is use allocators, which we will totally 
have fleshed out by Christmas (right, Andrei?).


in connect [Object]:

 It's not formatted right! 

You might s/is(T2 : Object)/is(T2 == class)/

Also, it looks like it will not delegate to any overriding methods, but 
I don't know if that is desired. I doubt it differs from existing 
std.signal.


invariant:


assert(slots_idx==slots.length); // I probably even remove slots_idx 
all together.


Yes you should. Also, you should assert that slots.length == objs.length.

private:

union DelegateTypes
{
void delegate(void*, T1) indirect;
void delegate(T1) direct;
}


Could you explain why indirect must have its first param void* ?



You can easily connect to an object's method with:

obj.signal.connect!"someMethod"(obj);

instead of the old implementation:

obj.signal.connect(&obj.someMethod);


The improvement is where?


In addition a method allowing wrapper delegates was added:

class Observer {
void addNumber(int i) {
sum+=i;
}
int sum;
}

class Button {
Signal!(bool) clicked;
// ...
}

void main() {
auto b=new Button;
auto o=new Observer;
// Ignore boolean parameter and pass some int:
b.connect!Observer(o, (o, p) { o.addNumber(7); });
// or even:
b.connect!Observer(o, (o, p) => o.addNumber(7));
// For some reason the compiler is not able to deduce "o" being
// Observer, so the !Observer is needed, but it is still very
// neat and readable.
}


Nice.
Should that be b.clicked.connect?



By passing the object explicitly to the delegate, it is possible to
maintain the 'weak ref' semantics to the target object, while ensuring
that the delegates context won't be freed.


When would the delegate's context be freed? I think it wouldn't.



As a side effect it is now even possible to use struct delegates or even
any non object delegate. Simply pass null for the obj parameter. It is
completely safe, the only drawback is that the struct won't be deleted
until the Button gets destroyed. (Because it holds a reference to the
struct, by means of the delegate.) But for long lived structs this
usually is perfectly acceptable.


I like this capability, but the api could handle the case of non-object 
delegates better.


 Not completely safe if the struct was allocated on the stack 




In my implementation I changed the Signal mixin to be a simple template
struct, because I hit strange compiler errors with it being a mixin. The
most prominent:


Welcome to D.


Also I did not really get the point why a mixin was used in the first
place, it does not really gain us anything? What was the reasoning about
it?


So you can do b.connect in the simplest case?



What do you think?


I like the way this is headed.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Tue, Nov 06, 2012 at 05:18:18AM +0100, Tommi wrote:
> I don't think this whole issue has anything to do with ranges. I
> think this is an issue of assuming that the symbol = means "copy
> what's on the right to what's on the left". When in reality, = could
> mean: (if what's on the right has reference semantics) "make what's
> on the left reference the same thing that the thing on the right
> references".
> 
> I think all range types should be allowed to return whatever they
> want from their front property. It's the responsibility of the user
> of the range to *actually* copy what front returns (if that's what
> he intends), instead of assuming that = means copy.
[...]

The problem is that you can't do this in generic code, because generic
code by definition doesn't know how to copy an arbitrary type.  Unless
we introduce a standardized deep copy operation to D, like a .clone
method that all copyable types implement, this solution isn't really
viable.


T

-- 
The computer is only a tool. Unfortunately, so is the user. -- Armaphine, K5


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Tue, Nov 06, 2012 at 04:12:17AM +0100, Jonathan M Davis wrote:
> On Monday, November 05, 2012 18:36:53 H. S. Teoh wrote:
> > Hmm. Another idea just occurred to me. The basic problem here is
> > that we are conflating two kinds of values, transient and
> > persistent, under a single name .front. What if we explicitly name
> > them? Say, .copyFront for the non-transient value and .refFront for
> > the transient value (the names are unimportant right now, let's
> > consider the semantics of it).
> 
> I thought of this a couple days ago but threw it away fairly quickly,
> because it breaks _everything_. And it definitely affects all ranges
> for the sake of a few.
[...]

If we make .copyFront == .front, then things will still mostly work.
That is, all existing non-transient ranges and algorithms that expect
non-transient ranges will still work. Thanks to UFCS, only transient
ranges (which are "rare") need an explicit definition of .refFront.  If
nothing else is done beyond that point, then we are back to the case
where all ranges are non-transient, so everything works (just a tad
slow).

Then we can update algos that can handle transient values to call
.refFront instead of .front, and we have a similar sort of situation
with the .transient proposal, where only algorithms that can handle
transient values will get them. If indeed we want to support transient
ranges correctly, then those algorithms have to be updated anyway, so
this isn't much of an additional cost. Plus, we have reduced the amount
of code per range to just an additional member in the rare transient
range -- no extra range types are needed.

I don't know how much better we can get beyond this, as far as explicit
support of transient is concerned. No matter what we do, as long as we
acknowledge transient ranges as valid ranges, we have to, one way or
another, (1) update all transient ranges to use whichever scheme we
decide on, (2) update all transient-capable algorithms to handle
transience correctly. We can't do any less than this, from this
direction.

The alternative is either to reject all transient ranges, which
currently seems to be the least effort option, and also not ideal.


T

-- 
It is of the new things that men tire --- of fashions and proposals and 
improvements and change. It is the old things that startle and intoxicate. It 
is the old things that are young. -- G.K. Chesterton


Re: How do you remove/insert elements in a dynamic array without allocating?

2012-11-05 Thread Jakob Ovrum

On Tuesday, 6 November 2012 at 01:11:08 UTC, Malte Skarupke wrote:
I want something similar to the stl vector, which only 
re-allocates once your array grows past a certain size, not on 
every append.


std.container.Array is similar to a shared_ptr>.



Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Tue, Nov 06, 2012 at 03:36:54AM +0200, Andrei Alexandrescu wrote:
> On 11/6/12 3:06 AM, H. S. Teoh wrote:
> >I've already given a number of non-trivial examples of transient
> >forward ranges, and apparently deadalnix has also encountered the
> >same issue.
> 
> I'd like to build more of this argument. I pointed out that your range
> is actually defining .dup, not .save. I think an argument can be made
> that forward ranges with transient .front do not qualify as forward
> ranges, seeing as a forward range is modeled after a list that
> actually has data sitting in memory.
[...]

I suppose you could argue that way. But that still doesn't solve the
problem of std.array.array with input ranges. Making std.array.array
require forward ranges seems to defeat its purpose, to me. So even if
you get rid of transience in forward ranges, you still need to make that
distinction with input ranges. Which still requires large-scale code
changes to existing Phobos algorithms. And which still requires some
sort of complication to the existing range code.


T

-- 
Music critic: "That's an imitation fugue!"


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Tommi

On Tuesday, 6 November 2012 at 04:31:56 UTC, H. S. Teoh wrote:
The problem is that you can't do this in generic code, because 
generic code by definition doesn't know how to copy an

arbitrary type.


I'm not familiar with that definition of generic code. But I do 
feel that there's a pretty big problem with a language design if 
the language doesn't provide a generic way to make a copy of a 
variable. To be fair, e.g. C++ doesn't provide that either.




Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread H. S. Teoh
On Tue, Nov 06, 2012 at 05:49:44AM +0100, Tommi wrote:
> On Tuesday, 6 November 2012 at 04:31:56 UTC, H. S. Teoh wrote:
> >The problem is that you can't do this in generic code, because
> >generic code by definition doesn't know how to copy an arbitrary
> >type.
> 
> I'm not familiar with that definition of generic code. But I do feel
> that there's a pretty big problem with a language design if the
> language doesn't provide a generic way to make a copy of a variable.
> To be fair, e.g. C++ doesn't provide that either.

OK I worded that poorly. All I meant was that currently, there is no
generic way to make a copy of something. It could be construed to be a
bug or a language deficiency, but that's how things are currently.

One *could* introduce a new language construct for making a copy of
something, of course, but that leads to all sorts of issues about
implicit allocation, how to eliminate unnecessary implicit copying,
etc.. It's not a simple problem, in spite of the simplicity of stating
the problem.


T

-- 
Verbing weirds language. -- Calvin (& Hobbes)


Re: Simple implementation of __FUNCTION

2012-11-05 Thread Rob T

On Friday, 2 November 2012 at 22:33:37 UTC, Rob T wrote:
I discovered it fails to compile when inside a function with 
"auto" as the return type.


auto test()
{
   throw new Exception(  mixin(__FUNCTION) );
   return 0;
}

Error: forward reference to test

but this works

int test()
{
   throw new Exception(  mixin(__FUNCTION) );
   return 0;
}

So we're kinda sunk for inclusion in phobos unless this error 
can be resolved.


I'll try the enum idea to see if that works.

--rt


An update on this problem. I found out that the error when using 
auto as return type has nothing to do with the mixin. The 
compiler error persists when you take mixin out and put in the 
__traits( ... ) code directly.


Does anyone else think that this is a compiler bug? If it is a 
bug then I'll report it in the bug tracker.


--rt



Re: DConf 2013 on kickstarter.com: we're live!

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 4:15 AM, Jesse Phillips wrote:

On Monday, 5 November 2012 at 21:57:01 UTC, Ali Çehreli wrote:

On 10/31/2012 05:35 PM, Faux Amis wrote:

> I will pledge 100$ if that would mean videos.

There is a change on the project page: :)

"Late-Breaking News: Smile, You're On Camera!

It's confirmed - through volunteer support, the conference talks will
be recorded and posted on the Net for free! We're preparing diligently
to ensure professional quality recordings. One more reason to pledge
even if for those of you who can't be there!"

Ali


That probably should be posted as an Update in kickstarter (not just a
change to the main page)...


You mean send an update to all current backers?

Andrei


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Mehrdad

On Tuesday, 6 November 2012 at 04:49:45 UTC, Tommi wrote:

On Tuesday, 6 November 2012 at 04:31:56 UTC, H. S. Teoh wrote:
The problem is that you can't do this in generic code, because 
generic code by definition doesn't know how to copy an 
arbitrary type.


I'm not familiar with that definition of generic code. But I do 
feel that there's a pretty big problem with a language design 
if the language doesn't provide a generic way to make a copy of 
a variable. To be fair, e.g. C++ doesn't provide that either.




C++ as a language doesn't, but if you follow the convention that 
C++ establishes in its libraries (where copy assignment & copy 
construction == deep copy), it always works out correctly.


D doesn't have that convention so that's why we're running into 
trouble.


Discussion on using module-scoped variables (was 'with' bug?)

2012-11-05 Thread Chris Cain

On Monday, 5 November 2012 at 08:37:49 UTC, Faux Amis wrote:
Ok, good to see that you are replying to incorrectly scoped 
variables, but this is not the point I am trying to make. I 
know you should always keep the scope as small as possible.


Eh? I'm confused. The second half of my post certainly was a bit 
of a rant on incorrectly scoped variables (which is related to 
the discussion, but it was my response to bearophile), but the 
first part of my post is supporting the viewpoint that you should 
avoid using module-scoped variables (and even static struct 
member variables) and suggesting an alternative.


Can you think of a setting in which we have legitimate private 
struct members? If so, then add to this setting that you only 
want one instantiation of the data in this struct. As a 
solution, what is wrong with dropping the struct encapsulation? 
There is no other code except the struct in the module.


I sincerely want to know if there is any difference. As I 
understand it the scope is exactly the same or even smaller as 
you can't leak instances of modules as you can structs.


From my understanding, you're trying to get a specific viewpoint 
on this idea?


From a good-coding standpoint, do you think there is a 
difference between these two options?


--
module a;

int a;
--
module b;

struct S{//otherwise unused wrapper
static int b;
}
--


I think the first option is "better" than the second. The second 
seems to be a misuse of struct to me. I can't see why you'd use a 
struct in the second option.


That said, they're effectively equivalent pieces of code. That 
is, they're both static data that is a shared resource among all 
functions that have access to them. And, thus, they're both 
"equally bad" in terms of how they will affect the 
understandability and testability of the code. It's possible that 
it would cause the code to have more bugs in it than it would 
otherwise.


That is, both of them are not as good of choices as this:
---
void good(ref int b) pure {
// code using/setting b
}
void good2(int b) pure {
// code using b, but not setting it
}

// No b in module scope or statically allocated

// Sometimes a better idea, depending on circumstances:
int better(int b) pure {
   // code using b, and putting changes into changedB
   return changedB;
}

// example uses:
void main() {
int a = 1, b = 2, c = 3;
good(a);
good2(b);
c = better(c);
}
---

Because this creates code that is honest about its dependencies 
and allows for the overall state of the program to be consistent 
between runs of functions. This is essential for testability, but 
it's also important for a programmer to reason about the behavior 
of their code.


Of course, I'm sure you can give examples of code that couldn't 
be written like that, and that's okay. I'm only arguing that you 
should avoid static data when it's realistic to do so, not that 
it will open a black hole in your living room if you use it under 
any circumstances :-). Though if you're using it as your "primary 
data encapsulation," I have to wonder whether you're using it in 
instances it could have been avoided.


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 4:36 AM, H. S. Teoh wrote:

Hmm. Another idea just occurred to me. The basic problem here is that we
are conflating two kinds of values, transient and persistent, under a
single name .front. What if we explicitly name them? Say, .copyFront for
the non-transient value and .refFront for the transient value (the
names are unimportant right now, let's consider the semantics of it).


We could transfer that matter to the type of .front itself, i.e. define 
a function copy(x) that returns e.g. x for for string and x.dup for 
char[] etc. There would be problems on e.g. defining copy for structs 
with pointer and class reference fields etc.


One quite simple approach would be to define (on the contrary) 
.peekFront, which means "yeah, I'd like to take a peek at the front but 
I don't plan to store it anywhere". That would entail we define eachLine 
etc. to return string from .front and char[] from .peekFront, and 
deprecate byLine.



Andrei


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 6:49 AM, Tommi wrote:

On Tuesday, 6 November 2012 at 04:31:56 UTC, H. S. Teoh wrote:

The problem is that you can't do this in generic code, because generic
code by definition doesn't know how to copy an
arbitrary type.


I'm not familiar with that definition of generic code. But I do feel
that there's a pretty big problem with a language design if the language
doesn't provide a generic way to make a copy of a variable. To be fair,
e.g. C++ doesn't provide that either.


Languages commonly have trouble defining comparison and copying 
generically. More often than not user intervention is needed (e.g. see 
Java's clone, Lisp's many comparison operators etc).


Andrei



Re: DConf 2013 on kickstarter.com: we're live!

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 8:40 AM, Andrei Alexandrescu wrote:

On 11/6/12 4:15 AM, Jesse Phillips wrote:

On Monday, 5 November 2012 at 21:57:01 UTC, Ali Çehreli wrote:

On 10/31/2012 05:35 PM, Faux Amis wrote:

> I will pledge 100$ if that would mean videos.

There is a change on the project page: :)

"Late-Breaking News: Smile, You're On Camera!

It's confirmed - through volunteer support, the conference talks will
be recorded and posted on the Net for free! We're preparing diligently
to ensure professional quality recordings. One more reason to pledge
even if for those of you who can't be there!"

Ali


That probably should be posted as an Update in kickstarter (not just a
change to the main page)...


You mean send an update to all current backers?


Well did so.

Andrei



Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Andrei Alexandrescu

On 11/6/12 7:48 AM, H. S. Teoh wrote:

On Tue, Nov 06, 2012 at 05:49:44AM +0100, Tommi wrote:

On Tuesday, 6 November 2012 at 04:31:56 UTC, H. S. Teoh wrote:

The problem is that you can't do this in generic code, because
generic code by definition doesn't know how to copy an arbitrary
type.


I'm not familiar with that definition of generic code. But I do feel
that there's a pretty big problem with a language design if the
language doesn't provide a generic way to make a copy of a variable.
To be fair, e.g. C++ doesn't provide that either.


OK I worded that poorly. All I meant was that currently, there is no
generic way to make a copy of something. It could be construed to be a
bug or a language deficiency, but that's how things are currently.

One *could* introduce a new language construct for making a copy of
something, of course, but that leads to all sorts of issues about
implicit allocation, how to eliminate unnecessary implicit copying,
etc.. It's not a simple problem, in spite of the simplicity of stating
the problem.


Here's where user defined @tributes would help a lot. We'd then define 
@owned to mention that a class reference field inside an object must be 
duplicated upon copy:


class A { ... }

struct B
{
   @owned A payload;
   A another;
   ...
}

That way a generic clone() routine could be written.


Andrei


Re: Transience of .front in input vs. forward ranges

2012-11-05 Thread Jonathan M Davis
On Tuesday, November 06, 2012 08:49:26 Andrei Alexandrescu wrote:
> On 11/6/12 4:36 AM, H. S. Teoh wrote:
> > Hmm. Another idea just occurred to me. The basic problem here is that we
> > are conflating two kinds of values, transient and persistent, under a
> > single name .front. What if we explicitly name them? Say, .copyFront for
> > the non-transient value and .refFront for the transient value (the
> > names are unimportant right now, let's consider the semantics of it).
> 
> We could transfer that matter to the type of .front itself, i.e. define
> a function copy(x) that returns e.g. x for for string and x.dup for
> char[] etc. There would be problems on e.g. defining copy for structs
> with pointer and class reference fields etc.
> 
> One quite simple approach would be to define (on the contrary)
> .peekFront, which means "yeah, I'd like to take a peek at the front but
> I don't plan to store it anywhere". That would entail we define eachLine
> etc. to return string from .front and char[] from .peekFront, and
> deprecate byLine.

peekFront would work better than copy, because whether front needs to be 
copied or not doesn't necessarily have much to do with its type. For instance, 
byLine/eachLine can return char[] from front just fine and still have it be a 
new array every time. So, while in some cases, you can tell from the type that 
no copy is needed (e.g. string), you can't tell in the general case and would 
be forced to make needless copies in a number of cases. For instance, every 
range of class objects would end up having to make a copy, because they'd be 
mutable reference types, and without knowing that the range is doing, you have 
no way of knowing whether it keeps replacing the objects referred to by front 
or not (it's not particularly likely that it would be, but you can't tell for 
sure just the same).

If we defined peekFront via UFCS as a wrapper which calls front, then anything 
wanting to use peekFront could use peekFront regardless of whether the type 
defined it or not. So, that would reduce the impact caused by its introduction, 
but it would still impact a lot of range types ultimately, because we'd have 
to create appropriate wrappers for peekFront in most of them, or we'd end up 
making unnecessary copies.

I don't like how much this impacts, but as H. S. Teoh points out, we don't 
exactly have very many options with minimal impact beyond banning transient 
fronts entirely (which I'd honestly like to do just the same).

At least this avoids the need to create more traits to test ranges for, since 
if we create a free function peekFront, all range types can just assume that 
it's there and create wrappers for it without caring whether the wrapped range 
defines it itself or uses the free function. And it's less complicated than the 
.transient suggestion. Though it _does_ introduce the possibility of front and 
peekFront returning completely different types, which could complicate things a 
bit. It might be better to require that they be identical to avoid that 
problem.

For better or worse though, this approach would mean that byLine (or eachLine 
or whatever) wouldn't be reusing the buffer with foreach like they do now, 
though I suppose that you could make them have opApply which does the same 
thing as now (meaning that it effectively uses peekFront), and then any range-
based functions would use front until they were updated to use peekFront if 
appropriate. But then again, maybe we want byLine/eachLine to copy by default, 
since that's safer, much as it's less efficient, since then we have safe by 
default but still have an explicit means to be more efficient. That fits in 
well 
with our general approach.

peekFront may be the way to go, but I think that we need to think through the 
consequences (like the potential problems caused by front and peekFront 
returning different types) before we decide on this.

- Jonathan M Davis


Re: DConf 2013 to be recorded

2012-11-05 Thread Jacob Carlborg

On 2012-11-05 23:10, Andrei Alexandrescu wrote:

I updated
http://www.kickstarter.com/projects/2083649206/the-d-programming-language-conference-2013-0
as follows:

=
Late-Breaking News: Smile, You're On Camera!

It's confirmed - through volunteer support, the conference talks will be
recorded and posted on the Net for free! We're preparing diligently to
ensure professional quality recordings. One more reason to pledge even
if for those of you who can't be there!
=

We have two volunteers who offered; I'm not naming them because I don't
know whether they want to take the responsibility burden at this point.
If you do, just reply to this!


That's great.

--
/Jacob Carlborg


Re: Simple implementation of __FUNCTION

2012-11-05 Thread Don Clugston

On 06/11/12 07:09, Rob T wrote:

On Friday, 2 November 2012 at 22:33:37 UTC, Rob T wrote:

I discovered it fails to compile when inside a function with "auto" as
the return type.

auto test()
{
   throw new Exception(  mixin(__FUNCTION) );
   return 0;
}

Error: forward reference to test

but this works

int test()
{
   throw new Exception(  mixin(__FUNCTION) );
   return 0;
}

So we're kinda sunk for inclusion in phobos unless this error can be
resolved.

I'll try the enum idea to see if that works.

--rt


An update on this problem. I found out that the error when using auto as
return type has nothing to do with the mixin. The compiler error
persists when you take mixin out and put in the __traits( ... ) code
directly.

Does anyone else think that this is a compiler bug? If it is a bug then
I'll report it in the bug tracker.

--rt


It fails because you're asking for the full function name, before its 
type has been determined. (There's no real return type 'auto', 'auto' 
just means 'work it out for me').


I don't think this is a bug. Although it might be solvable in this 
particular example, in general it's a circular dependency.


eg, if you do:

auto foo()
{
   static if (__FUNCTION == "int foo()") { return 'a' }
   return 0;
}
if __FUNCTION is "int foo()" then it will return a char, which means its 
signature is "char foo()". This is a contradiction.