www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Any chance to call Tango as Extended Standard Library

reply Piotrek <starpit tlen.pl> writes:
Hello!

It's just an idea. After reading about issues on disallowing DWT to stay 
in standardization area (Anomaly on Wiki4D GuiLibraries page) some 
question appeared in my mind. For propaganda sake isn't it better to not 
make such a big division between phobos and tango in the module naming? 
Logically:

phobos -> std
tango  -> stdex (not tango -> tango)


Module naming example:
import std.stdio;
import std.string;

import stdex.io.Stdout;
import stdex.text.Util;

Doesn't it look fine? (Also note that alphabetical order is preserved).

After all tango is a standard library. Currently from incomer/observer 
point of view tango could be seen as an rebel initiative. But thanks to 
druntime phobos and tango can live in harmony and take advantage of each 
other.
Another good thing is that one could write in his project documentation:
Extended Standard Library (Tango) needed
instead of
Tango library needed.

In addition some information could be added on the digitalmars.com website.

Cheers
Jan 17 2009
next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 17 Jan 2009 15:48:14 +0300, Piotrek <starpit tlen.pl> wrote:

 Hello!

 It's just an idea. After reading about issues on disallowing DWT to stay  
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some  
 question appeared in my mind. For propaganda sake isn't it better to not  
 make such a big division between phobos and tango in the module naming?  
 Logically:

 phobos -> std
 tango  -> stdex (not tango -> tango)


 Module naming example:
 import std.stdio;
 import std.string;

 import stdex.io.Stdout;
 import stdex.text.Util;

 Doesn't it look fine? (Also note that alphabetical order is preserved).

 After all tango is a standard library. Currently from incomer/observer  
 point of view tango could be seen as an rebel initiative. But thanks to  
 druntime phobos and tango can live in harmony and take advantage of each  
 other.
 Another good thing is that one could write in his project documentation:
 Extended Standard Library (Tango) needed
 instead of
 Tango library needed.

 In addition some information could be added on the digitalmars.com  
 website.

 Cheers

I like the idea. Other thing I constantly think about is that once Tango is ported to D2, it should start being distributed alongside the Phobos (just the way it comes with LDC). I believe there are a lot of advantages for Tango library developers, its users and D in general.
Jan 17 2009
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Piotrek wrote:

 Hello!
 
 It's just an idea. After reading about issues on disallowing DWT to stay
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some
 question appeared in my mind. For propaganda sake isn't it better to not
 make such a big division between phobos and tango in the module naming?
 Logically:
 
 phobos -> std
 tango  -> stdex (not tango -> tango)

Tango will stay Tango (and tango.*). The above naming assumes that Tango will depend on Phobos, and it will not. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 17 2009
next sibling parent reply IUnknown <a b.com> writes:
To D gods,

Having to learn and choose between two libraries is a big -ve point in adopting
D. Many people would also like to use D on ARM if possible in the future so
dividing the library into two parts would help as then only the core lib can be
linked in. 

Really, D's community needs to grow up and create ONE standard library for D2.
D2 would be a nice time to break backwards compatibility in the libraries. 

 A language needs large scale adoption to be successful and its implementations
must be delivered in a ready to use manner. Many people find D interesting but
not sufficiently interesting to switch away from the pain of C++. 
If D also has other pain points, how do you think it will get adopted? 
dmd seems lacking on floating point optimization. Not many platforms are
supported. While platform support is an understandable problem and is something
that happens over time. Having two competing libraries is simply either
egoistic or retarded from an outsider's perspective. 

Programmers simply don't seem to want to do the necessary work to make the
software appealing to use. Many people want to use a powerful editor like vim,
but then find that all the standard features they find in other editors are
extensions in vim and the simple act of finding the right scripts even from
vim's homepage is a deterrent. 

Please, the worst thing you can do in deterring a person from trying out
something new is in giving him options with no clear way to choose. Can't you
learn this from python? Of often having one way to accomplish something? Merge
the libs, pretty pretty please.

Lars Ivar Igesund Wrote:

 Piotrek wrote:
 
 Hello!
 
 It's just an idea. After reading about issues on disallowing DWT to stay
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some
 question appeared in my mind. For propaganda sake isn't it better to not
 make such a big division between phobos and tango in the module naming?
 Logically:
 
 phobos -> std
 tango  -> stdex (not tango -> tango)

Tango will stay Tango (and tango.*). The above naming assumes that Tango will depend on Phobos, and it will not. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango

Jan 17 2009
next sibling parent John Reimer <terminal.node gmail.com> writes:
Hello IUnknown,

 To D gods,
 
 Having to learn and choose between two libraries is a big -ve point in
 adopting D. Many people would also like to use D on ARM if possible in
 the future so dividing the library into two parts would help as then
 only the core lib can be linked in.
 

Yes, this is true.
 Really, D's community needs to grow up and create ONE standard library
 for D2. D2 would be a nice time to break backwards compatibility in
 the libraries.
 

He he... well, you have to understand the dynamics of this D community to understand why the problem exists. The D community /has/ created such a library: it's called Tango for D1. I doubt the community will implement one for D2 until it is stable because the time and effort of chasing experimental language design is far too great: that area is completely reserved for the D core team and its Phobos. Even if Tango were complete for D 2.0, the community has absolutely no say on whether it becomes the ONE standard library or not. Historically, Tango was a somewhat reactive process resulting from the community feeling unable to influence the growth of the standard library and D 1.0. This is the point: it has nothing to do with the D community as far as I understand it. You'll have to talk to the D core team about this one. They control what is and what is not the standard library. They do tend to accept portions from the community, but not to the extent that you are going to see a community managed standard library. The problem tends to be that the core team has one set of ideas about D's future while the community (specifically Tango for D 1.0) has a different set of ideas. Sometimes the sets intersect, often not... Sometimes the community has some influence on ideas, sometimes not. The process of communication of this core team with the community is what allows the D language design to grow. But I think it's important to erase the notion that the community has to get its act together. Perhaps both the core team and the community should get it's act together, but then who speaks for the community (not everyone is involved in the Tango aspect of it)? What's hugely missing is face to face communication between the two with the determined purpose of resolving the problem. I've seen no evidence that this will happen beyond the initiation of druntime for d2.0 (a good start... but where does it go from there?); but I think the core team, who has a vested interest in D, should initiate such a venture soon if they want to see D succeed in the long term. The other thing to remember is that since there is no Tango for D 2.0... there is no competing libraries for D 2.0 yet. So there isn't really an issue there, just an odd realization that D 2.0 is a different language then D 1.0 where Tango is by far the most popular library.... yep it's complicated.
 A language needs large scale adoption to be successful and its
 implementations must be delivered in a ready to use manner. Many
 people find D interesting but not sufficiently interesting to switch
 away from the pain of C++. If D also has other pain points, how do you
 think it will get adopted? dmd seems lacking on floating point
 optimization. Not many platforms are supported. While platform support
 is an understandable problem and is something that happens over time.
 Having two competing libraries is simply either egoistic or retarded
 from an outsider's perspective.
 
 Programmers simply don't seem to want to do the necessary work to make
 the software appealing to use. Many people want to use a powerful
 editor like vim, but then find that all the standard features they
 find in other editors are extensions in vim and the simple act of
 finding the right scripts even from vim's homepage is a deterrent.
 
 Please, the worst thing you can do in deterring a person from trying
 out something new is in giving him options with no clear way to
 choose. Can't you learn this from python? Of often having one way to
 accomplish something? Merge the libs, pretty pretty please.
 

This is a specific problem with the D langauge design process, and it is very hard to know what the solution to it is. At the very least, maybe it would be nice to have the structure of the D design progress layed out on a wiki, so newcomers can better understand how D progresses. This is D's handicap. And I think most people here realize this now. -JJR
Jan 17 2009
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
IUnknown wrote:
<snip>
 Really, D's community needs to grow up and create ONE standard 
 library for D2. D2 would be a nice time to break backwards 
 compatibility in the libraries.

D already has ONE standard library. It's called Phobos. http://www.digitalmars.com/d/archives/digitalmars/D/Two_standard_libraries_58530.html Stewart.
Jan 18 2009
parent reply =?UTF-8?B?QWxleGFuZGVyIFDDoW5law==?= writes:
Stewart Gordon wrote:
 IUnknown wrote:
 <snip>
 Really, D's community needs to grow up and create ONE standard library 
 for D2. D2 would be a nice time to break backwards compatibility in 
 the libraries.

D already has ONE standard library. It's called Phobos.

*yawn* Don’t you get tired of this?
Jan 18 2009
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Alexander Pánek wrote:
 Stewart Gordon wrote:

 D already has ONE standard library.  It's called Phobos.

*yawn* Don’t you get tired of this?

I do get tired of the misunderstanding of what Tango is that seems to have arisen from the misterminology. Stewart.
Jan 18 2009
parent reply =?UTF-8?B?QWxleGFuZGVyIFDDoW5law==?= writes:
Stewart Gordon wrote:
 Alexander Pánek wrote:
 Stewart Gordon wrote:

 D already has ONE standard library.  It's called Phobos.

*yawn* Don’t you get tired of this?

I do get tired of the misunderstanding of what Tango is that seems to have arisen from the misterminology.

It didn’t arise from misterminology, but people who do call it their (de-facto, but nonetheless) standard D library. You might not accept, respect or acknowledge this in any way, but then again you seem to be all into semantics. “A standard library for a programming language is the library that is conventionally made available in every implementation of that language. In some cases, the library is described directly in the programming language specification; in other cases, the contents of the standard library are determined by more informal social practices in the programming community.” I think Tango meets every but the first (conventional) “rule”. So there might have been a misunderstanding I do get tired of on your side. Kind regards, Alex
Jan 18 2009
parent =?UTF-8?B?QWxleGFuZGVyIFDDoW5law==?= writes:
Alexander Pánek wrote:
 Stewart Gordon wrote:
 Alexander Pánek wrote:
 Stewart Gordon wrote:

 D already has ONE standard library.  It's called Phobos.

*yawn* Don’t you get tired of this?

I do get tired of the misunderstanding of what Tango is that seems to have arisen from the misterminology.

It didn’t arise from misterminology, but people who do call it their (de-facto, but nonetheless) standard D library. You might not accept, respect or acknowledge this in any way, but then again you seem to be all into semantics. “A standard library for a programming language is the library that is conventionally made available in every implementation of that language. In some cases, the library is described directly in the programming language specification; in other cases, the contents of the standard library are determined by more informal social practices in the programming community.”

Source: http://en.wikipedia.org/wiki/Standard_library
 I think Tango meets every but the first (conventional) “rule”. So there 
 might have been a misunderstanding I do get tired of on your side.

Jan 18 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Jan 18, 2009 at 4:35 AM, IUnknown <a b.com> wrote:
 To D gods,

 Having to learn and choose between two libraries is a big -ve point in ad=

ture so dividing the library into two parts would help as then only the cor= e lib can be linked in.
 Really, D's community needs to grow up and create ONE standard library fo=

ries.
  A language needs large scale adoption to be successful and its implement=

esting but not sufficiently interesting to switch away from the pain of C++= .
 If D also has other pain points, how do you think it will get adopted?
 dmd seems lacking on floating point optimization. Not many platforms are =

hing that happens over time. Having two competing libraries is simply eithe= r egoistic or retarded from an outsider's perspective.
 Programmers simply don't seem to want to do the necessary work to make th=

vim, but then find that all the standard features they find in other edito= rs are extensions in vim and the simple act of finding the right scripts ev= en from vim's homepage is a deterrent.
 Please, the worst thing you can do in deterring a person from trying out =

ou learn this from python? Of often having one way to accomplish something?= Merge the libs, pretty pretty please. Preach it brutha'. It is ridiculous for a niche language to allow a split like this to happen. Fortunately, things are moving to repair the schism at last in D2. And finally if you don't like to choose, then there is Tangobos, which lets you use either Tango or Phobos as you please. It's my preferred platform because generally I like Phobo's minimal style, but Tango just has a lot more stuff in it for those odd occasions when I do need something beyond what Phobos has. --bb
Jan 17 2009
prev sibling next sibling parent reply Piotrek <starpit tlen.pl> writes:
Lars Ivar Igesund wrote:
 Tango will stay Tango (and tango.*). The above naming assumes that Tango will
depend on Phobos, and it will not.
 

I see. Cheers
Jan 17 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Piotrek wrote:
 Lars Ivar Igesund wrote:
 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.

I see. Cheers

(Note: speaking as merely an infrequent contributor to Tango; my opinion is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up. It's best if you think of Phobos as being Python and Tango as being Java. Phobos implements a relatively flat (if messy) hierarchy of simple, fat classes. For example, IO is done using the Stream interfaces, each one implements all the methods you'd probably need to work with streams. Tango, on the other hand, implements a very deep (if confusing) hierarchy of simple, component interfaces that get plugged together. Unlike Phobos, IO in Tango has many layers and components, each of which is very narrowly defined, allowing you to plug them together however you like. The problem is that neither of these approaches is WRONG. They're both valid and arguably better in certain circumstances. What's more, the continued existence of both shows that there are people who believe in each of them (not necessarily at the same time, but there you go.) So let's say we combined them into std.* and stdex.*. Why is Tango stdex? Why isn't Tango std.* and Phobos stdsimple? Ok, ignoring egos, the problem is that they wouldn't work together anyway. An old favourite of mine is (again, sorry about this) IO. Phobos strives to be compatible with the C IO library; so you can interleave Phobos and C IO calls and it's all gravy. Tango takes C out the back and shoots it before burying it upside-down at a crossroads with a steak through the heart and salting the earth. You CAN mix Tango and C IO calls, but you really have no idea what order the output's going to arrive in. I remember Andrei getting antsy about this a while back; why break compatibility?! Because Tango's IO was faster this way. Neither one of them was 'right' because they both had legitimate points of view. Really, it all boils down to this: there *is no* one right way. Yes, it's more confusing. But it's a problem with programming in general; programming is all about looking at your options and making a decision on the matter. -- Daniel
Jan 17 2009
next sibling parent John Reimer <terminal.node gmail.com> writes:
Hello Daniel,

 Piotrek wrote:
 
 Lars Ivar Igesund wrote:
 
 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.
 

Cheers

opinion is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up. It's best if you think of Phobos as being Python and Tango as being Java. Phobos implements a relatively flat (if messy) hierarchy of simple, fat classes. For example, IO is done using the Stream interfaces, each one implements all the methods you'd probably need to work with streams. Tango, on the other hand, implements a very deep (if confusing) hierarchy of simple, component interfaces that get plugged together. Unlike Phobos, IO in Tango has many layers and components, each of which is very narrowly defined, allowing you to plug them together however you like. The problem is that neither of these approaches is WRONG. They're both valid and arguably better in certain circumstances. What's more, the continued existence of both shows that there are people who believe in each of them (not necessarily at the same time, but there you go.) So let's say we combined them into std.* and stdex.*. Why is Tango stdex? Why isn't Tango std.* and Phobos stdsimple? Ok, ignoring egos, the problem is that they wouldn't work together anyway. An old favourite of mine is (again, sorry about this) IO. Phobos strives to be compatible with the C IO library; so you can interleave Phobos and C IO calls and it's all gravy. Tango takes C out the back and shoots it before burying it upside-down at a crossroads with a steak through the heart and salting the earth. You CAN mix Tango and C IO calls, but you really have no idea what order the output's going to arrive in. I remember Andrei getting antsy about this a while back; why break compatibility?! Because Tango's IO was faster this way. Neither one of them was 'right' because they both had legitimate points of view. Really, it all boils down to this: there *is no* one right way. Yes, it's more confusing. But it's a problem with programming in general; programming is all about looking at your options and making a decision on the matter. -- Daniel

That's a very good description of the situation, I think. Thanks. -JJR
Jan 17 2009
prev sibling next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Daniel Keep (daniel.keep.lists gmail.com)'s article
 Piotrek wrote:
 Lars Ivar Igesund wrote:
 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.

I see. Cheers

is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up. It's best if you think of Phobos as being Python and Tango as being Java. Phobos implements a relatively flat (if messy) hierarchy of simple, fat classes. For example, IO is done using the Stream interfaces, each one implements all the methods you'd probably need to work with streams. Tango, on the other hand, implements a very deep (if confusing) hierarchy of simple, component interfaces that get plugged together. Unlike Phobos, IO in Tango has many layers and components, each of which is very narrowly defined, allowing you to plug them together however you like. The problem is that neither of these approaches is WRONG. They're both valid and arguably better in certain circumstances. What's more, the continued existence of both shows that there are people who believe in each of them (not necessarily at the same time, but there you go.) So let's say we combined them into std.* and stdex.*. Why is Tango stdex? Why isn't Tango std.* and Phobos stdsimple? Ok, ignoring egos, the problem is that they wouldn't work together anyway. An old favourite of mine is (again, sorry about this) IO. Phobos strives to be compatible with the C IO library; so you can interleave Phobos and C IO calls and it's all gravy. Tango takes C out the back and shoots it before burying it upside-down at a crossroads with a steak through the heart and salting the earth. You CAN mix Tango and C IO calls, but you really have no idea what order the output's going to arrive in. I remember Andrei getting antsy about this a while back; why break compatibility?! Because Tango's IO was faster this way. Neither one of them was 'right' because they both had legitimate points of view. Really, it all boils down to this: there *is no* one right way. Yes, it's more confusing. But it's a problem with programming in general; programming is all about looking at your options and making a decision on the matter. -- Daniel

Wow. Excellent analysis. One thing I'd like to add is that Phobos tends to be much more focused on the bleeding edge, with pretty much all development happening on the D2 branch, while Tango is more focused on targeting stable compilers. Also, another way I would summarize the situation is that Phobos focuses on first making simple operations simple first and foremost, and then worries about making complicated operations possible, while Tango does just the opposite. I've said this before, but I think it's not so bad for D to have two standard libraries with different design philosophies, at least in principle, though the inability to use both side by side on D1 is obviously a bad thing. There are times when I like the Phobos "keep it simple, stupid" approach and times when I want Tango's "everything but the kitchen sink" approach. There are a few things that I think would help a lot here: 1. Both Phobos and Tango should adopt these opposite design philosophies, which are true de facto anyhow, officially. This will prevent excessive feature envy and duplication of effort and allow newcomers to determine which is best for their everyday use. 2. The creation of druntime so that Phobos and Tango can be used side by side is a huge step forward. Once D2 is out of alpha and Tango is ported to D2, people will be able to use their preferred lib most of the time and the other when their preferred lib has some missing functionality. This will also greatly simplify 3rd party libs.
Jan 17 2009
parent reply John Reimer <terminal.node gmail.com> writes:
Hello dsimcha,

 == Quote from Daniel Keep (daniel.keep.lists gmail.com)'s article
 
 Piotrek wrote:
 
 Lars Ivar Igesund wrote:
 
 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.
 

Cheers

opinion is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up. It's best if you think of Phobos as being Python and Tango as being Java. Phobos implements a relatively flat (if messy) hierarchy of simple, fat classes. For example, IO is done using the Stream interfaces, each one implements all the methods you'd probably need to work with streams. Tango, on the other hand, implements a very deep (if confusing) hierarchy of simple, component interfaces that get plugged together. Unlike Phobos, IO in Tango has many layers and components, each of which is very narrowly defined, allowing you to plug them together however you like. The problem is that neither of these approaches is WRONG. They're both valid and arguably better in certain circumstances. What's more, the continued existence of both shows that there are people who believe in each of them (not necessarily at the same time, but there you go.) So let's say we combined them into std.* and stdex.*. Why is Tango stdex? Why isn't Tango std.* and Phobos stdsimple? Ok, ignoring egos, the problem is that they wouldn't work together anyway. An old favourite of mine is (again, sorry about this) IO. Phobos strives to be compatible with the C IO library; so you can interleave Phobos and C IO calls and it's all gravy. Tango takes C out the back and shoots it before burying it upside-down at a crossroads with a steak through the heart and salting the earth. You CAN mix Tango and C IO calls, but you really have no idea what order the output's going to arrive in. I remember Andrei getting antsy about this a while back; why break compatibility?! Because Tango's IO was faster this way. Neither one of them was 'right' because they both had legitimate points of view. Really, it all boils down to this: there *is no* one right way. Yes, it's more confusing. But it's a problem with programming in general; programming is all about looking at your options and making a decision on the matter. -- Daniel

tends to be much more focused on the bleeding edge, with pretty much all development happening on the D2 branch, while Tango is more focused on targeting stable compilers. Also, another way I would summarize the situation is that Phobos focuses on first making simple operations simple first and foremost, and then worries about making complicated operations possible, while Tango does just the opposite.

I don't know if that is strictly true. In Tango's defense, I believe it has tried quite hard to move in the direction of making simple things simple even under the restrictions of its own philosophy :). If you examine the progression of Tango revisions, there has been a significant "cleanup" in progress that appears to be simplifying what was originally verbose.
 I've said this before, but I think it's not so bad for D to have two
 standard libraries with different design philosophies, at least in
 principle, though the inability to use both side by side on D1 is
 obviously a bad thing.  There are times when I like the Phobos "keep
 it simple, stupid" approach and times when I want Tango's "everything
 but the kitchen sink" approach.  There are a few things that I think
 would help a lot here:
 

 1.  Both Phobos and Tango should adopt these opposite design
 philosophies, which are true de facto anyhow, officially.  This will
 prevent excessive feature envy and duplication of effort and allow
 newcomers to determine which is best for their everyday use.
 

Like I said, I believe Tango has worked harder at doing this than you might think. I don't think Phobos cares to look at the opposite philosophy because it really doesn't merge well with it's intended goals. Tango can afford some brevity because it started at the verbose end.
 2.  The creation of druntime so that Phobos and Tango can be used side
 by side is a huge step forward.  Once D2 is out of alpha and Tango is
 ported to D2, people will be able to use their preferred lib most of
 the time and the other when their preferred lib has some missing
 functionality.  This will also greatly simplify 3rd party libs.
 

This somehow parallels my original thinking too which I've mentioned before. I am all for the druntime, and it certainly will be a net gain if both Tango V2 (if it ever surfaces complete) and Phobos can share it once D2 is stable. But I'm afraid, it is still a grave difficulty for new users to face two different libraries. Now that I've waited and think about it longer, I'm not sure what to make of it. How does one promote this twin package deal for D. I predict that the first person that finds a clever way to promote D 2.0 and it's shiny new twin-library / pick-your-style feature will be a D hero forever. ;-) No, it's not bad. It's just rather... new... and it will take some very fancy promotion to get people to digest it. I'm not sure if I'm up to the challenge. That said, I guess I'm kind of jumping to conclusions if I even attempt to figure out what the D team is going to do about this. Maybe they have no plans to ship two libraries together. They may just continue to ship d2.0 with Phobos only... in which case Tango will indeed become a third party library. Perhaps for the best? I really don't know. -JJR
Jan 17 2009
parent reply Don <nospam nospam.com> writes:
John Reimer wrote:
 Hello dsimcha,
 
 == Quote from Daniel Keep (daniel.keep.lists gmail.com)'s article

 Piotrek wrote:

 Lars Ivar Igesund wrote:

 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.

Cheers

opinion is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up. It's best if you think of Phobos as being Python and Tango as being Java. Phobos implements a relatively flat (if messy) hierarchy of simple, fat classes. For example, IO is done using the Stream interfaces, each one implements all the methods you'd probably need to work with streams. Tango, on the other hand, implements a very deep (if confusing) hierarchy of simple, component interfaces that get plugged together. Unlike Phobos, IO in Tango has many layers and components, each of which is very narrowly defined, allowing you to plug them together however you like. The problem is that neither of these approaches is WRONG. They're both valid and arguably better in certain circumstances. What's more, the continued existence of both shows that there are people who believe in each of them (not necessarily at the same time, but there you go.) So let's say we combined them into std.* and stdex.*. Why is Tango stdex? Why isn't Tango std.* and Phobos stdsimple? Ok, ignoring egos, the problem is that they wouldn't work together anyway. An old favourite of mine is (again, sorry about this) IO. Phobos strives to be compatible with the C IO library; so you can interleave Phobos and C IO calls and it's all gravy. Tango takes C out the back and shoots it before burying it upside-down at a crossroads with a steak through the heart and salting the earth. You CAN mix Tango and C IO calls, but you really have no idea what order the output's going to arrive in. I remember Andrei getting antsy about this a while back; why break compatibility?! Because Tango's IO was faster this way. Neither one of them was 'right' because they both had legitimate points of view. Really, it all boils down to this: there *is no* one right way. Yes, it's more confusing. But it's a problem with programming in general; programming is all about looking at your options and making a decision on the matter. -- Daniel

tends to be much more focused on the bleeding edge, with pretty much all development happening on the D2 branch, while Tango is more focused on targeting stable compilers.


 Also, another way I would summarize the situation is that Phobos
 focuses on first
 making simple operations simple first and foremost, and then worries
 about making
 complicated operations possible, while Tango does just the opposite.

I don't know if that is strictly true. In Tango's defense, I believe it has tried quite hard to move in the direction of making simple things simple even under the restrictions of its own philosophy :). If you examine the progression of Tango revisions, there has been a significant "cleanup" in progress that appears to be simplifying what was originally verbose.
 I've said this before, but I think it's not so bad for D to have two
 standard libraries with different design philosophies, at least in
 principle, though the inability to use both side by side on D1 is
 obviously a bad thing.  There are times when I like the Phobos "keep
 it simple, stupid" approach and times when I want Tango's "everything
 but the kitchen sink" approach.  There are a few things that I think
 would help a lot here:

 1.  Both Phobos and Tango should adopt these opposite design
 philosophies, which are true de facto anyhow, officially.  This will
 prevent excessive feature envy and duplication of effort and allow
 newcomers to determine which is best for their everyday use.

might think. I don't think Phobos cares to look at the opposite philosophy because it really doesn't merge well with it's intended goals. Tango can afford some brevity because it started at the verbose end.
 2.  The creation of druntime so that Phobos and Tango can be used side
 by side is a huge step forward.  Once D2 is out of alpha and Tango is
 ported to D2, people will be able to use their preferred lib most of
 the time and the other when their preferred lib has some missing
 functionality.  This will also greatly simplify 3rd party libs.

This somehow parallels my original thinking too which I've mentioned before. I am all for the druntime, and it certainly will be a net gain if both Tango V2 (if it ever surfaces complete) and Phobos can share it once D2 is stable. But I'm afraid, it is still a grave difficulty for new users to face two different libraries. Now that I've waited and think about it longer, I'm not sure what to make of it. How does one promote this twin package deal for D. I predict that the first person that finds a clever way to promote D 2.0 and it's shiny new twin-library / pick-your-style feature will be a D hero forever. ;-) No, it's not bad.

<small rant> I completely disagree. I think the two libraries is a disaster. I can see that so many people have been exposed to a lifetime of propaganda that "competition is a good thing", but it's just propaganda. Competition inevitably means wasted effort, and it's obvious in D. </small rant> Note, however that the gulf between Phobos and Tango mostly exists in I/O; and C++ also has two I/O packages (the one inherited from C, and the awful iostreams). So I don't think this is a big a problem as stated. If we work at it, we could move the difference to be entirely a I/O difference. But that would require willingless to do it, and I'm not sure that it's really there. <big rant> In my attempt to bring both libraries together I have experienced reactions from both sides which appeared hostile (or at least reluctant) to a merger. Apart from Sean and myself, I don't see much evidence that people actually want them to merge. They just want the other one to disappear. </big rant>
Jan 17 2009
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Don,

 This somehow parallels my original thinking too which I've mentioned
 before. I am all for the druntime, and it certainly will be a net
 gain if both Tango V2 (if it ever surfaces complete) and Phobos can
 share it once D2 is stable.  But I'm afraid, it is still a grave
 difficulty for new users to face two different libraries.  Now that
 I've waited and think about it longer, I'm not sure what to make of
 it.  How does one promote this twin package deal for D.  I predict
 that the first person that finds a clever way to promote D 2.0 and
 it's shiny new twin-library / pick-your-style feature will be a D
 hero forever. ;-)
 
 No, it's not bad.
 

I completely disagree. I think the two libraries is a disaster. I can see that so many people have been exposed to a lifetime of propaganda that "competition is a good thing", but it's just propaganda. Competition inevitably means wasted effort, and it's obvious in D. </small rant>

No, Don, some of it may be propoganda when that is the only reason put forward (ie. that competition is always a good thing). Others may merely be trying to be hopeful. In my case, you may call my hopefulness a delusion, but I think you will see by the context of my post that I'm rather clueless to know how it will work. I'm completely baffled to know how it can go forward, but I don't want to be the Spreader of Doom and Gloom if I don't know all the details that are going on behind the scenes. That's where I think more communication is absolutely critical for D to get along well. More honest perhaps would have been for me just to remove "it's not bad".
 Note, however that the gulf between Phobos and Tango mostly exists in
 I/O; and C++ also has two I/O packages (the one inherited from C, and
 the awful iostreams). So I don't think this is a big a problem as
 stated. If we work at it, we could move the difference to be entirely
 a I/O difference. But that would require willingless to do it, and I'm
 not sure that it's really there.
 
 <big rant>
 In my attempt to bring both libraries together I have experienced
 reactions from both sides which appeared hostile (or at least
 reluctant)
 to a merger. Apart from Sean and myself, I don't see much evidence
 that
 people actually want them to merge. They just want the other one to
 disappear.
 </big rant>

At this point, I think people (those not involved in Phobos or Tango development) would take it anyway it could be made to work. The reluctance appears mostly from those involved in both libraries. If there is a creative way to merge two very different styles, then I think it would be amazing. But, from what I see, there would have to be more interaction and dicussion among both project developers because the core team is the one carrying the D design banner. My personal opinion is that I don't know how a merger would work anymore. If you or anybody has got some detailed ideas, it would be fun to see them. :-P /How-to-do-an-about-face-on-"No, it's not bad"/ The danger, of course, is that Tango will not be taken seriously again for D 2.0. If Tango manages to garner the lion-share of popularity as they did with D 1.0 (LDC compiler suite is one example of the significant sway Tango has had on D 1.0 ), then I think I'm going to just throw up my hands. Yes, I think something has to be done: ignoring Tango is not going to be a healthy option for D. Either that or Phobos2 will have to be so good that people will drop Tango faster than they would a red-hot frying pan. Frankly, it will have to be absolutely extraordinary to manage that. Or maybe Tango v2 just won't appear because it lacks the d-insider connection. How's that for Doom and Gloom? :-( -JJR
Jan 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
John Reimer wrote:
 The danger, of course, is that Tango will not be taken seriously again 
 for D 2.0.  If Tango manages to garner the lion-share of popularity as 
 they did with D 1.0 (LDC compiler suite is one example of the 
 significant sway Tango has had on D 1.0 ), then I think I'm going to 
 just throw up my hands.  Yes, I think something has to be done: ignoring 
 Tango is not going to be a healthy option for D.  Either that or Phobos2 
 will have to be so good that people will drop Tango faster than they 
 would a red-hot frying pan.

Beware of the false choice. Ideally, Phobos2 will be so good, and Tango2 will be so good, that people will enjoy using either or both together. Andrei
Jan 18 2009
next sibling parent John Reimer <terminal.node gmail.com> writes:
Hello Andrei,

 John Reimer wrote:
 
 The danger, of course, is that Tango will not be taken seriously
 again for D 2.0.  If Tango manages to garner the lion-share of
 popularity as they did with D 1.0 (LDC compiler suite is one example
 of the significant sway Tango has had on D 1.0 ), then I think I'm
 going to just throw up my hands.  Yes, I think something has to be
 done: ignoring Tango is not going to be a healthy option for D.
 Either that or Phobos2 will have to be so good that people will drop
 Tango faster than they would a red-hot frying pan.
 

Tango2 will be so good, that people will enjoy using either or both together. Andrei

Heh, I forgot to enumerate that one at the spur of the moment in /this/ post. :P Like I said in my early post, you guys will have to be /very/ creative at promoting D to make that one work. I know I want to promote D, but I'm not sure I have the same optimism in this particular detail. I guess we'll see. In the meantime, I think the best approach is to keep "talking" to us. You and Walter's optimisim is important to keep things moving in some perceivable direction. At any rate, thank you both for your efforts... and restraint. -JJR
Jan 18 2009
prev sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Andrei Alexandrescu wrote:
 John Reimer wrote:
 The danger, of course, is that Tango will not be taken seriously again 
 for D 2.0.  If Tango manages to garner the lion-share of popularity as 
 they did with D 1.0 (LDC compiler suite is one example of the 
 significant sway Tango has had on D 1.0 ), then I think I'm going to 
 just throw up my hands.  Yes, I think something has to be done: 
 ignoring Tango is not going to be a healthy option for D.  Either that 
 or Phobos2 will have to be so good that people will drop Tango faster 
 than they would a red-hot frying pan.

Beware of the false choice. Ideally, Phobos2 will be so good, and Tango2 will be so good, that people will enjoy using either or both together. Andrei

People will be forced to use both together, which will be annoying, since they overlap. A third party library depending on Phobos will use Phobos time types and functions; one using Tango will depend on Tango time stuff; client code will be forced to convert back and forth. Or, for example, subtle differences in file path handling between Phobos and Tango (I recall some people on IRC having minor issues with Tango's path handling in obscure cases that were contrary to specifications but occasionally used). That sort of annoyance will not be extremely common, but it'll happen. It's another source of friction. It's a bad thing. It's okay if the means of working with data types are entirely different in Phobos and Tango. The types themselves should be the same.
Jan 18 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Christopher Wright wrote:
 Andrei Alexandrescu wrote:
 John Reimer wrote:
 The danger, of course, is that Tango will not be taken seriously 
 again for D 2.0.  If Tango manages to garner the lion-share of 
 popularity as they did with D 1.0 (LDC compiler suite is one example 
 of the significant sway Tango has had on D 1.0 ), then I think I'm 
 going to just throw up my hands.  Yes, I think something has to be 
 done: ignoring Tango is not going to be a healthy option for D.  
 Either that or Phobos2 will have to be so good that people will drop 
 Tango faster than they would a red-hot frying pan.

Beware of the false choice. Ideally, Phobos2 will be so good, and Tango2 will be so good, that people will enjoy using either or both together. Andrei

People will be forced to use both together, which will be annoying, since they overlap. A third party library depending on Phobos will use Phobos time types and functions; one using Tango will depend on Tango time stuff; client code will be forced to convert back and forth. Or, for example, subtle differences in file path handling between Phobos and Tango (I recall some people on IRC having minor issues with Tango's path handling in obscure cases that were contrary to specifications but occasionally used). That sort of annoyance will not be extremely common, but it'll happen. It's another source of friction. It's a bad thing.

I agree, but I don't quite see a solution to this.
 It's okay if the means of working with data types are entirely different 
 in Phobos and Tango. The types themselves should be the same.

Couldn't this cause trouble for code that is ported from one library to another? It may compile and then do unexpected things. Andrei
Jan 18 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Don wrote:
 <small rant>
 I completely disagree. I think the two libraries is a disaster. I can 
 see that so many people have been exposed to a lifetime of propaganda 
 that "competition is a good thing", but it's just propaganda. 
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

Well I've been exposed to "competition is wasted effort" for the first 19 years of my life, and believe me, you wouldn't want to be subjected to that :o). But, I hear your point.
 Note, however that the gulf between Phobos and Tango mostly exists in 
 I/O; and C++ also has two I/O packages (the one inherited from C, and 
 the awful iostreams). So I don't think this is a big a problem as 
 stated. If we work at it, we could move the difference to be entirely a 
 I/O difference. But that would require willingless to do it, and I'm not 
 sure that it's really there.
 
 <big rant>
 In my attempt to bring both libraries together I have experienced 
 reactions from both sides which appeared hostile (or at least reluctant) 
 to a merger. Apart from Sean and myself, I don't see much evidence that 
 people actually want them to merge. They just want the other one to 
 disappear.
 </big rant>

Well then you better start naming names :o). As far as yours truly is concerned, it's a good thing to be able to work on a library that meshes well with the power of D2. In many ways it's a dream language (sometimes literally so...), and it ought to come with a dream library. Andrei
Jan 18 2009
parent reply John Reimer <terminal.node gmail.com> writes:
Hello Andrei,

 Don wrote:
 
 <small rant>
 I completely disagree. I think the two libraries is a disaster. I can
 see that so many people have been exposed to a lifetime of propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

19 years of my life, and believe me, you wouldn't want to be subjected to that :o). But, I hear your point.

I've read a little bit of history on Romania and the conditions under Nicolae Ceauşescu's reign. I'd be interested to sit down with you sometime and hear your perspective as one who had first hand experience of it. It sounded pretty bad -- conditions with which most of our Western culture is completely unfamiliar. All the best, -JJR
Jan 18 2009
parent reply John Reimer <terminal.node gmail.com> writes:
Hello John,

 Hello Andrei,
 
 Don wrote:
 
 <small rant>
 I completely disagree. I think the two libraries is a disaster. I
 can
 see that so many people have been exposed to a lifetime of
 propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

first 19 years of my life, and believe me, you wouldn't want to be subjected to that :o). But, I hear your point.

Nicolae Ceauşescu's reign. I'd be interested to sit down with you sometime and hear your perspective as one who had first hand experience of it. It sounded pretty bad -- conditions with which most of our Western culture is completely unfamiliar. All the best, -JJR

I hope that didn't come across rude or presumptuous; I'm interested in people, history, and experience. :P -JJR
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
John Reimer wrote:
 Hello John,
 
 Hello Andrei,

 Don wrote:

 <small rant>
 I completely disagree. I think the two libraries is a disaster. I
 can
 see that so many people have been exposed to a lifetime of
 propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

first 19 years of my life, and believe me, you wouldn't want to be subjected to that :o). But, I hear your point.

Nicolae Ceauşescu's reign. I'd be interested to sit down with you sometime and hear your perspective as one who had first hand experience of it. It sounded pretty bad -- conditions with which most of our Western culture is completely unfamiliar. All the best, -JJR

I hope that didn't come across rude or presumptuous; I'm interested in people, history, and experience. :P

Sure. In all likelihood many of us will bump into one another at a conference sooner rather than later. Andrei
Jan 18 2009
parent John Reimer <terminal.node gmail.com> writes:
Hello Andrei,

<snip>

 

in people, history, and experience. :P

conference sooner rather than later. Andrei

True! :) -JJR
Jan 18 2009
prev sibling next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Don (nospam nospam.com)'s article

 <small rant>
 I completely disagree. I think the two libraries is a disaster. I can
 see that so many people have been exposed to a lifetime of propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

On a purely philosopical note, yes, cooperation is better than competition *if* there's enough of a consensus among the parties involved as to how things should be run. However, this is a *BIG* if. The problem with ideologies that are strongly against competition is that this is very seldom true in the real world. (Phobos vs. Tango is one example) In these cases, where there is simply no consensus, the only realistic alternative to competition is to have winners and losers picked in a dictatorial fashion by some form of authority. Yes, this authority could be selected democratically by voting, but tyranny of the majority is still tyranny. In the case of Phobos vs. Tango, Walter could hypothetically just try his absolute hardest to kill off Tango, in the name of preventing competition, but I'm sure noone wants that. Therefore, where no true consensus exists or ever realistically will exist, competition is often a lesser evil than having a winner arbitrarily picked by some form of authority.
Jan 18 2009
parent reply Don <nospam nospam.com> writes:
dsimcha wrote:
 == Quote from Don (nospam nospam.com)'s article
 
 <small rant>
 I completely disagree. I think the two libraries is a disaster. I can
 see that so many people have been exposed to a lifetime of propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

On a purely philosopical note, yes, cooperation is better than competition *if* there's enough of a consensus among the parties involved as to how things should be run. However, this is a *BIG* if. The problem with ideologies that are strongly against competition is that this is very seldom true in the real world. (Phobos vs. Tango is one example) In these cases, where there is simply no consensus, the only realistic alternative to competition is to have winners and losers picked in a dictatorial fashion by some form of authority. Yes, this authority could be selected democratically by voting, but tyranny of the majority is still tyranny. In the case of Phobos vs. Tango, Walter could hypothetically just try his absolute hardest to kill off Tango, in the name of preventing competition, but I'm sure noone wants that. Therefore, where no true consensus exists or ever realistically will exist, competition is often a lesser evil than having a winner arbitrarily picked by some form of authority.

I'm not convinced that there really is a major idealogical difference between Phobos and Tango. At the time Tango was formed, Phobos was virtually stagnant. It was a random accretion of contributions by various authors from various points in D's history. All changes to Phobos were manually made by Walter, who had too much on his plate already. _Nobody_ thought that that situation was ideal. Tango1 is in direct competition with Phobos1, but Phobos1 is frozen. Phobos2 is _not_ the same as Phobos1, and breaks compatibility with it in many serious ways. And Phobos1 and 2 are likely to diverge even more with time. There are in fact many similarities between Phobos2 and Tango1. Now we're getting some genuinely different approaches between Phobos2 and Tango1, but they seem to be driven as much by the new capabilities in D2, as by philosophical differences. So I see two critical questions: (1) to what extent will Tango2 embrace D2 features, at the expense of backward compatibility with Tango1? (The more it embraces D2, the closer it will become to Phobos2); and (2) are both libraries prepared to eliminate the many superficial differences between them? Can we merge Tango2 and Phobos2, given that neither of them completely exist yet?
Jan 19 2009
parent reply John Reimer <terminal.node gmail.com> writes:
Hello Don,

 dsimcha wrote:
 
 == Quote from Don (nospam nospam.com)'s article
 
 <small rant>
 I completely disagree. I think the two libraries is a disaster. I
 can
 see that so many people have been exposed to a lifetime of
 propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

competition *if* there's enough of a consensus among the parties involved as to how things should be run. However, this is a *BIG* if. The problem with ideologies that are strongly against competition is that this is very seldom true in the real world. (Phobos vs. Tango is one example) In these cases, where there is simply no consensus, the only realistic alternative to competition is to have winners and losers picked in a dictatorial fashion by some form of authority. Yes, this authority could be selected democratically by voting, but tyranny of the majority is still tyranny. In the case of Phobos vs. Tango, Walter could hypothetically just try his absolute hardest to kill off Tango, in the name of preventing competition, but I'm sure noone wants that. Therefore, where no true consensus exists or ever realistically will exist, competition is often a lesser evil than having a winner arbitrarily picked by some form of authority.

between Phobos and Tango. At the time Tango was formed, Phobos was virtually stagnant. It was a random accretion of contributions by various authors from various points in D's history. All changes to Phobos were manually made by Walter, who had too much on his plate already. _Nobody_ thought that that situation was ideal. Tango1 is in direct competition with Phobos1, but Phobos1 is frozen. Phobos2 is _not_ the same as Phobos1, and breaks compatibility with it in many serious ways. And Phobos1 and 2 are likely to diverge even more with time. There are in fact many similarities between Phobos2 and Tango1. Now we're getting some genuinely different approaches between Phobos2 and Tango1, but they seem to be driven as much by the new capabilities in D2, as by philosophical differences. So I see two critical questions: (1) to what extent will Tango2 embrace D2 features, at the expense of backward compatibility with Tango1? (The more it embraces D2, the closer it will become to Phobos2); and (2) are both libraries prepared to eliminate the many superficial differences between them? Can we merge Tango2 and Phobos2, given that neither of them completely exist yet?

I agree that these are the critical questions, and we will need to see them answered eventually. The question is "when?" I suppose, the Tango people probably can't answer that until they see a stable D 2.0 and a complete Phobos 2. On the other hand, perhaps its a very good time for Tango guys to be introduced to the Phobos 2 floor plan so that both sides can see if their goals can merge somehow. -JJR
Jan 19 2009
parent reply Don <nospam nospam.com> writes:
John Reimer wrote:
 Hello Don,
 
 dsimcha wrote:

 == Quote from Don (nospam nospam.com)'s article

 <small rant>
 I completely disagree. I think the two libraries is a disaster. I
 can
 see that so many people have been exposed to a lifetime of
 propaganda
 that "competition is a good thing", but it's just propaganda.
 Competition inevitably means wasted effort, and it's obvious in D.
 </small rant>

competition *if* there's enough of a consensus among the parties involved as to how things should be run. However, this is a *BIG* if. The problem with ideologies that are strongly against competition is that this is very seldom true in the real world. (Phobos vs. Tango is one example) In these cases, where there is simply no consensus, the only realistic alternative to competition is to have winners and losers picked in a dictatorial fashion by some form of authority. Yes, this authority could be selected democratically by voting, but tyranny of the majority is still tyranny. In the case of Phobos vs. Tango, Walter could hypothetically just try his absolute hardest to kill off Tango, in the name of preventing competition, but I'm sure noone wants that. Therefore, where no true consensus exists or ever realistically will exist, competition is often a lesser evil than having a winner arbitrarily picked by some form of authority.

between Phobos and Tango. At the time Tango was formed, Phobos was virtually stagnant. It was a random accretion of contributions by various authors from various points in D's history. All changes to Phobos were manually made by Walter, who had too much on his plate already. _Nobody_ thought that that situation was ideal. Tango1 is in direct competition with Phobos1, but Phobos1 is frozen. Phobos2 is _not_ the same as Phobos1, and breaks compatibility with it in many serious ways. And Phobos1 and 2 are likely to diverge even more with time. There are in fact many similarities between Phobos2 and Tango1. Now we're getting some genuinely different approaches between Phobos2 and Tango1, but they seem to be driven as much by the new capabilities in D2, as by philosophical differences. So I see two critical questions: (1) to what extent will Tango2 embrace D2 features, at the expense of backward compatibility with Tango1? (The more it embraces D2, the closer it will become to Phobos2); and (2) are both libraries prepared to eliminate the many superficial differences between them? Can we merge Tango2 and Phobos2, given that neither of them completely exist yet?

I agree that these are the critical questions, and we will need to see them answered eventually. The question is "when?" I suppose, the Tango people probably can't answer that until they see a stable D 2.0 and a complete Phobos 2. On the other hand, perhaps its a very good time for Tango guys to be introduced to the Phobos 2 floor plan so that both sides can see if their goals can merge somehow. -JJR

And in fact, a Tango2 floor plan would be a good idea, too. For example, now that D2 supports foreach ranges, Tango containers will almost certainly want to support them.
Jan 19 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Don wrote:
 [snip]
 
 And in fact, a Tango2 floor plan would be a good idea, too. For example,
 now that D2 supports foreach ranges, Tango containers will almost
 certainly want to support them.

For reference, from tango.util.collection.model.Iterator: public interface Iterator(V) { public bool more(); public V get(); int opApply (int delegate (inout V value) dg); } Basically, Tango's iterators use more (negation of empty,) and get (which is next and head combined.) This brings up a request I have for Andrei: please ensure there is an actual interface for ranges (preferably enforced.) Compile-time duck typing [1] is awesome, but sometimes you need run-time polymorphism. -- Daniel [1] There's a funny case of this falling to pieces in C#; they introduced templates in C# 2.0, I believe. However, to do anything moderately useful, you had to use interfaces to tell the compiler what was acceptable to pass. Of course, you can't have operator overloads in interfaces, which meant it's IMPOSSIBLE to do any form of arithmetic in templates in C#. Whoops.
Jan 19 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Daniel Keep wrote:
 
 Don wrote:
 [snip]

 And in fact, a Tango2 floor plan would be a good idea, too. For example,
 now that D2 supports foreach ranges, Tango containers will almost
 certainly want to support them.

For reference, from tango.util.collection.model.Iterator: public interface Iterator(V) { public bool more(); public V get(); int opApply (int delegate (inout V value) dg); } Basically, Tango's iterators use more (negation of empty,) and get (which is next and head combined.) This brings up a request I have for Andrei: please ensure there is an actual interface for ranges (preferably enforced.) Compile-time duck typing [1] is awesome, but sometimes you need run-time polymorphism.

There is a persistent misunderstanding about the two. They're not competing. Duck typing as used in foreach and ranges does not preclude definition and use of explicit interfaces and dynamic polymorphism. Andrei
Jan 19 2009
prev sibling parent reply Johan Granberg <lijat.meREM OVEgmail.com> writes:
Don wrote:

 John Reimer wrote:
 Hello dsimcha,
 
 == Quote from Daniel Keep (daniel.keep.lists gmail.com)'s article

 Piotrek wrote:

 Lars Ivar Igesund wrote:

 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.

Cheers

opinion is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up. It's best if you think of Phobos as being Python and Tango as being Java. Phobos implements a relatively flat (if messy) hierarchy of simple, fat classes. For example, IO is done using the Stream interfaces, each one implements all the methods you'd probably need to work with streams. Tango, on the other hand, implements a very deep (if confusing) hierarchy of simple, component interfaces that get plugged together. Unlike Phobos, IO in Tango has many layers and components, each of which is very narrowly defined, allowing you to plug them together however you like. The problem is that neither of these approaches is WRONG. They're both valid and arguably better in certain circumstances. What's more, the continued existence of both shows that there are people who believe in each of them (not necessarily at the same time, but there you go.) So let's say we combined them into std.* and stdex.*. Why is Tango stdex? Why isn't Tango std.* and Phobos stdsimple? Ok, ignoring egos, the problem is that they wouldn't work together anyway. An old favourite of mine is (again, sorry about this) IO. Phobos strives to be compatible with the C IO library; so you can interleave Phobos and C IO calls and it's all gravy. Tango takes C out the back and shoots it before burying it upside-down at a crossroads with a steak through the heart and salting the earth. You CAN mix Tango and C IO calls, but you really have no idea what order the output's going to arrive in. I remember Andrei getting antsy about this a while back; why break compatibility?! Because Tango's IO was faster this way. Neither one of them was 'right' because they both had legitimate points of view. Really, it all boils down to this: there *is no* one right way. Yes, it's more confusing. But it's a problem with programming in general; programming is all about looking at your options and making a decision on the matter. -- Daniel

tends to be much more focused on the bleeding edge, with pretty much all development happening on the D2 branch, while Tango is more focused on targeting stable compilers.


 Also, another way I would summarize the situation is that Phobos
 focuses on first
 making simple operations simple first and foremost, and then worries
 about making
 complicated operations possible, while Tango does just the opposite.

I don't know if that is strictly true. In Tango's defense, I believe it has tried quite hard to move in the direction of making simple things simple even under the restrictions of its own philosophy :). If you examine the progression of Tango revisions, there has been a significant "cleanup" in progress that appears to be simplifying what was originally verbose.
 I've said this before, but I think it's not so bad for D to have two
 standard libraries with different design philosophies, at least in
 principle, though the inability to use both side by side on D1 is
 obviously a bad thing.  There are times when I like the Phobos "keep
 it simple, stupid" approach and times when I want Tango's "everything
 but the kitchen sink" approach.  There are a few things that I think
 would help a lot here:

 1.  Both Phobos and Tango should adopt these opposite design
 philosophies, which are true de facto anyhow, officially.  This will
 prevent excessive feature envy and duplication of effort and allow
 newcomers to determine which is best for their everyday use.

might think. I don't think Phobos cares to look at the opposite philosophy because it really doesn't merge well with it's intended goals. Tango can afford some brevity because it started at the verbose end.
 2.  The creation of druntime so that Phobos and Tango can be used side
 by side is a huge step forward.  Once D2 is out of alpha and Tango is
 ported to D2, people will be able to use their preferred lib most of
 the time and the other when their preferred lib has some missing
 functionality.  This will also greatly simplify 3rd party libs.

This somehow parallels my original thinking too which I've mentioned before. I am all for the druntime, and it certainly will be a net gain if both Tango V2 (if it ever surfaces complete) and Phobos can share it once D2 is stable. But I'm afraid, it is still a grave difficulty for new users to face two different libraries. Now that I've waited and think about it longer, I'm not sure what to make of it. How does one promote this twin package deal for D. I predict that the first person that finds a clever way to promote D 2.0 and it's shiny new twin-library / pick-your-style feature will be a D hero forever. ;-) No, it's not bad.

<small rant> I completely disagree. I think the two libraries is a disaster. I can see that so many people have been exposed to a lifetime of propaganda that "competition is a good thing", but it's just propaganda. Competition inevitably means wasted effort, and it's obvious in D. </small rant> Note, however that the gulf between Phobos and Tango mostly exists in I/O; and C++ also has two I/O packages (the one inherited from C, and the awful iostreams). So I don't think this is a big a problem as stated. If we work at it, we could move the difference to be entirely a I/O difference. But that would require willingless to do it, and I'm not sure that it's really there. <big rant> In my attempt to bring both libraries together I have experienced reactions from both sides which appeared hostile (or at least reluctant) to a merger. Apart from Sean and myself, I don't see much evidence that people actually want them to merge. They just want the other one to disappear. </big rant>

As a user of D primarily and of the standard libraries secondly I see this reluctance to solve the library situation as the single biggest threat to D. It creates a division in the community and an uncertainty of which library to base my own libraries on. If I use one and the other wins the competition I have to redo a lot of work. It's also a headache when distributing code as I don't know which functions and packages I can assume exists. This split actually has made me put some of my own projects on hold while trying to see if we eventually get a merge or one side wins. Through here lack of time also contributes. I sinercelly hope this situation gets resolved as the current situation can be really discoraging for both new and old D developers.
Jan 21 2009
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Johan,


 As a user of D primarily and of the standard libraries secondly I see
 this reluctance to solve the library situation as the single biggest
 threat to D. It creates a division in the community and an uncertainty
 of which library to base my own libraries on. If I use one and the
 other wins the competition I have to redo a lot of work. It's also a
 headache when distributing code as I don't know which functions and
 packages I can assume exists.
 

I hear you. But the argument against this would probably be that you would not have to redo all your work... you just start integrating the use of the other (more popular) library in your work (since they have common runtimes). While this is convenient, yet it would seem to be cumbersome. Now projects will have dependencies on both full libraries including the libary that falls from favour (if that in fact happens). On the other hand, it wouldn't be so bad if one of Tango or Phobos became a 3rd-party/extension library (more suitably this should be Tango), in which case it would seem more natural and familiar to use it as an addon to the other library. -JJR
Jan 21 2009
parent reply Don <nospam nospam.com> writes:
John Reimer wrote:
 Hello Johan,
 
 
 As a user of D primarily and of the standard libraries secondly I see
 this reluctance to solve the library situation as the single biggest
 threat to D. It creates a division in the community and an uncertainty
 of which library to base my own libraries on. If I use one and the
 other wins the competition I have to redo a lot of work. It's also a
 headache when distributing code as I don't know which functions and
 packages I can assume exists.

I hear you. But the argument against this would probably be that you would not have to redo all your work... you just start integrating the use of the other (more popular) library in your work (since they have common runtimes). While this is convenient, yet it would seem to be cumbersome. Now projects will have dependencies on both full libraries including the libary that falls from favour (if that in fact happens). On the other hand, it wouldn't be so bad if one of Tango or Phobos became a 3rd-party/extension library (more suitably this should be Tango), in which case it would seem more natural and familiar to use it as an addon to the other library. -JJR

and encompass more of the common code from both. So that both Phobos and Tango became (crucial) extension libraries over a small core. And the bigger that common core becomes, the smaller the library problem becomes.
Jan 21 2009
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Don,

 John Reimer wrote:
 
 Hello Johan,
 
 As a user of D primarily and of the standard libraries secondly I
 see this reluctance to solve the library situation as the single
 biggest threat to D. It creates a division in the community and an
 uncertainty of which library to base my own libraries on. If I use
 one and the other wins the competition I have to redo a lot of work.
 It's also a headache when distributing code as I don't know which
 functions and packages I can assume exists.
 

you would not have to redo all your work... you just start integrating the use of the other (more popular) library in your work (since they have common runtimes). While this is convenient, yet it would seem to be cumbersome. Now projects will have dependencies on both full libraries including the libary that falls from favour (if that in fact happens). On the other hand, it wouldn't be so bad if one of Tango or Phobos became a 3rd-party/extension library (more suitably this should be Tango), in which case it would seem more natural and familiar to use it as an addon to the other library. -JJR

and encompass more of the common code from both. So that both Phobos and Tango became (crucial) extension libraries over a small core. And the bigger that common core becomes, the smaller the library problem becomes.

Actually, I very much like that idea. And it seems to make sense too. -JJR
Jan 21 2009
parent =?UTF-8?B?QWxleGFuZGVyIFDDoW5law==?= writes:
John Reimer wrote:
 Don wrote:
 The other option (which I would prefer) is for druntime to get bigger,
 and encompass more of the common code from both. So that both Phobos
 and Tango became (crucial) extension libraries over a small core. And
 the bigger that common core becomes, the smaller the library problem
 becomes.

Actually, I very much like that idea. And it seems to make sense too.

Seconded! That’s a nice idea.
Jan 21 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jan 22, 2009 at 1:53 AM, Alexander P=E1nek
<alexander.panek brainsware.org> wrote:
 John Reimer wrote:
 Don wrote:
 The other option (which I would prefer) is for druntime to get bigger,
 and encompass more of the common code from both. So that both Phobos
 and Tango became (crucial) extension libraries over a small core. And
 the bigger that common core becomes, the smaller the library problem
 becomes.

Actually, I very much like that idea. And it seems to make sense too.

Seconded! That's a nice idea.

Thirded.
Jan 22 2009
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 22 Jan 2009 18:11:02 +0100, Jarrett Billingsley  
<jarrett.billingsley gmail.com> wrote:

 On Thu, Jan 22, 2009 at 1:53 AM, Alexander Pánek
 <alexander.panek brainsware.org> wrote:
 John Reimer wrote:
 Don wrote:
 The other option (which I would prefer) is for druntime to get bigger,
 and encompass more of the common code from both. So that both Phobos
 and Tango became (crucial) extension libraries over a small core. And
 the bigger that common core becomes, the smaller the library problem
 becomes.

Actually, I very much like that idea. And it seems to make sense too.

Seconded! That's a nice idea.

Thirded.

Fourthed! -- Simen
Jan 22 2009
prev sibling next sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Don wrote:
<snip>
 The other option (which I would prefer) is for druntime to get bigger, 
 and encompass more of the common code from both. So that both Phobos and 
 Tango became (crucial) extension libraries over a small core. And the 
 bigger that common core becomes, the smaller the library problem becomes.

Up until the point at which somebody decides it's time to develop a library to rival druntime. Stewart.
Jan 22 2009
prev sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Don wrote:

 John Reimer wrote:
 Hello Johan,
 
 
 As a user of D primarily and of the standard libraries secondly I see
 this reluctance to solve the library situation as the single biggest
 threat to D. It creates a division in the community and an uncertainty
 of which library to base my own libraries on. If I use one and the
 other wins the competition I have to redo a lot of work. It's also a
 headache when distributing code as I don't know which functions and
 packages I can assume exists.

I hear you. But the argument against this would probably be that you would not have to redo all your work... you just start integrating the use of the other (more popular) library in your work (since they have common runtimes). While this is convenient, yet it would seem to be cumbersome. Now projects will have dependencies on both full libraries including the libary that falls from favour (if that in fact happens). On the other hand, it wouldn't be so bad if one of Tango or Phobos became a 3rd-party/extension library (more suitably this should be Tango), in which case it would seem more natural and familiar to use it as an addon to the other library. -JJR

and encompass more of the common code from both. So that both Phobos and Tango became (crucial) extension libraries over a small core. And the bigger that common core becomes, the smaller the library problem becomes.

druntime should certainly not become any bigger (in scope), as that would defeat the purpose of separating the runtime from userspace in the first place. The topic of common userspace functionality should be kept separate from the topic of druntime. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 23 2009
next sibling parent Christopher Wright <dhasenan gmail.com> writes:
Lars Ivar Igesund wrote:
 druntime should certainly not become any bigger (in scope), as that would
defeat the purpose of separating the runtime from userspace in the first place.
The topic of common userspace functionality should be kept separate from the
topic of druntime.

Okay, how about another library with shared Phobos / Tango components that do not fit in the runtime?
Jan 23 2009
prev sibling parent reply Don <nospam nospam.com> writes:
Lars Ivar Igesund wrote:
 Don wrote:
 
 John Reimer wrote:
 Hello Johan,


 As a user of D primarily and of the standard libraries secondly I see
 this reluctance to solve the library situation as the single biggest
 threat to D. It creates a division in the community and an uncertainty
 of which library to base my own libraries on. If I use one and the
 other wins the competition I have to redo a lot of work. It's also a
 headache when distributing code as I don't know which functions and
 packages I can assume exists.

I hear you. But the argument against this would probably be that you would not have to redo all your work... you just start integrating the use of the other (more popular) library in your work (since they have common runtimes). While this is convenient, yet it would seem to be cumbersome. Now projects will have dependencies on both full libraries including the libary that falls from favour (if that in fact happens). On the other hand, it wouldn't be so bad if one of Tango or Phobos became a 3rd-party/extension library (more suitably this should be Tango), in which case it would seem more natural and familiar to use it as an addon to the other library. -JJR

and encompass more of the common code from both. So that both Phobos and Tango became (crucial) extension libraries over a small core. And the bigger that common core becomes, the smaller the library problem becomes.

druntime should certainly not become any bigger (in scope), as that would defeat the purpose of separating the runtime from userspace in the first place. The topic of common userspace functionality should be kept separate from the topic of druntime.

I think you are confusing druntime (the project) with the D runtime. druntime includes the gc as well the runtime, though they are seperate. I see no reason why including core modules in the druntime project would destroy the seperation. Really, this is entirely a question of naming. core.XXX seems to me to be the perfect namespace, certainly for the key math modules which I'm most concerned about (std.math/(tango.math.Math, tango.math.IEEE), and possibly also the low-level bigint routines. These are all functionality which is closely tied to the compiler).
Jan 23 2009
parent reply Benji Smith <dlanguage benjismith.net> writes:
Don wrote:
 Lars Ivar Igesund wrote:
 Don wrote:
 druntime should certainly not become any bigger (in scope), as that 
 would defeat the purpose of separating the runtime from userspace in 
 the first place. The topic of common userspace functionality should be 
 kept separate from the topic of druntime.

I think you are confusing druntime (the project) with the D runtime. druntime includes the gc as well the runtime, though they are seperate. I see no reason why including core modules in the druntime project would destroy the seperation. Really, this is entirely a question of naming. core.XXX seems to me to be the perfect namespace, certainly for the key math modules which I'm most concerned about (std.math/(tango.math.Math, tango.math.IEEE), and possibly also the low-level bigint routines. These are all functionality which is closely tied to the compiler).

Totally agree. Although the name 'druntime' implies it'll only contain the runtime, I think it ought to contain all the common functionality that virtually all applications and libraries will absolutely need: the runtime itself, gc, TypeInfo, math, containers (including ranges), algorithms, string processing, date/time, and IO. Without those commonalities, any "compatibility" between Phobos and Tango will be purely illusory. Whether the commonality is realized within druntime, or within some other low-level common library (like "dcore"), is immaterial to me. And actually, I don't really care whether Phobos and Tango have their own implementations. But there should be an API (interfaces? concepts? some new template-interface mechanism? doesn't matter.) that both Phobos and Tango implement, so that library consumers can seamlessly pass low-level objects between Phobos and Tango dependent libraries. --benji
Jan 24 2009
parent Sean Kelly <sean invisibleduck.org> writes:
Benji Smith wrote:
 Don wrote:
 Lars Ivar Igesund wrote:
 Don wrote:
 druntime should certainly not become any bigger (in scope), as that 
 would defeat the purpose of separating the runtime from userspace in 
 the first place. The topic of common userspace functionality should 
 be kept separate from the topic of druntime.

I think you are confusing druntime (the project) with the D runtime. druntime includes the gc as well the runtime, though they are seperate. I see no reason why including core modules in the druntime project would destroy the seperation. Really, this is entirely a question of naming. core.XXX seems to me to be the perfect namespace, certainly for the key math modules which I'm most concerned about (std.math/(tango.math.Math, tango.math.IEEE), and possibly also the low-level bigint routines. These are all functionality which is closely tied to the compiler).

Totally agree. Although the name 'druntime' implies it'll only contain the runtime, I think it ought to contain all the common functionality that virtually all applications and libraries will absolutely need: the runtime itself, gc, TypeInfo, math, containers (including ranges), algorithms, string processing, date/time, and IO.

After the dsource project was created, someone suggested using the name 'd-core' instead--I think it's more appropriate than 'd-runtime'. That aside, I personally see the visible portion of the runtime to be roughly similar to java.lang. Basically, I think it should contain the stuff that's required for a D app to simply load and run, but anything that's sufficiently intrinsic to the language or language philosophy is appropriate as well. In addition to what's already there, I think an argument could be made for a range definition, essential math routines, and probably a few other things. But things that are simply commonly used belong in the standard library.
 Without those commonalities, any "compatibility" between Phobos and 
 Tango will be purely illusory.

True enough. But attempting to include all of the stuff you mentioned above would require design agreement between the Phobos and Tango folks on quite a bit in terms of API philosophy.
 Whether the commonality is realized within druntime, or within some 
 other low-level common library (like "dcore"), is immaterial to me. And 
 actually, I don't really care whether Phobos and Tango have their own 
 implementations. But there should be an API (interfaces? concepts? some 
 new template-interface mechanism? doesn't matter.) that both Phobos and 
 Tango implement, so that library consumers can seamlessly pass low-level 
 objects between Phobos and Tango dependent libraries.

I agree that this is a fine goal. It just isn't a task I have any intention of pursuing, personally. Sean
Jan 24 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jan 22, 2009 at 8:13 PM, Stewart Gordon <smjg_1998 yahoo.com> wrote:
 Don wrote:
 <snip>
 The other option (which I would prefer) is for druntime to get bigger, and
 encompass more of the common code from both. So that both Phobos and Tango
 became (crucial) extension libraries over a small core. And the bigger that
 common core becomes, the smaller the library problem becomes.

Up until the point at which somebody decides it's time to develop a library to rival druntime.

And we prevent that from happening by making as many people as possible happy with the development and features of druntime/core. This is exactly what caused the split in libraries in the first place - a sizable contingent of users who _weren't_ happy with the existing library or its development. In the end though, of course there's nothing we can do from stopping people from developing yet another library. But we can at least try to reduce the likelihood of it.
Jan 22 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Daniel Keep wrote:
 Piotrek wrote:
 Lars Ivar Igesund wrote:
 Tango will stay Tango (and tango.*). The above naming assumes that
 Tango will depend on Phobos, and it will not.

Cheers

(Note: speaking as merely an infrequent contributor to Tango; my opinion is my own and does not reflect on those of the Master Dancers, or the ruling council of glittery-shoed programmers.) (Warning: semi-rant ahead.) The problem is that Phobos and Tango are diametrically opposed in almost every conceivable way. Bringing them together would be like trying to bring matter and anti-matter together; you're just going to blow yourself up.

Nice comparison, but maybe a tad exaggerated. The two libraries are different in a number of ways, and reuniting them together might be difficult as they sometimes present different ways of approaching similar problems. For example, I'm not sure how code in std.algorithm could help containers or streams in Tango (as it should), or how to reconcile std.algorithm with std.core.array. One other issue is that phobos2 has the mixed blessing of a clean slate, or at least a slate that can be partially cleaned as needed without worrying about breaking backwards compatibility. D2 has made a definite departure from some of the styles and idioms of D1, and with the advent of the new threading model that departure will only be more pronounced. The capabilities of a language strongly influence its standard library, and at best Phobos2 will espouse and promote the idioms that we strove to make possible. After all, we wanted to introduce new features because they'd help in writing good code, so the standard library should take advantage of them almost by definition. That's why phobos is not being "ported" to D2, it is being rewritten for D2.
 It's best if you think of Phobos as being Python and Tango as being
 Java.  Phobos implements a relatively flat (if messy) hierarchy of
 simple, fat classes.  For example, IO is done using the Stream
 interfaces, each one implements all the methods you'd probably need to
 work with streams.

Well, I am really looking forward to deprecating the Stream interfaces. I think it's an ok design (alright: I actively dislike certain parts of it), it's just that a much better design can be put forth with D2's capabilities.
 Tango, on the other hand, implements a very deep (if confusing)
 hierarchy of simple, component interfaces that get plugged together.
 Unlike Phobos, IO in Tango has many layers and components, each of which
 is very narrowly defined, allowing you to plug them together however you
 like.
 
 The problem is that neither of these approaches is WRONG.  They're both
 valid and arguably better in certain circumstances.  What's more, the
 continued existence of both shows that there are people who believe in
 each of them (not necessarily at the same time, but there you go.)
 
 So let's say we combined them into std.* and stdex.*.  Why is Tango
 stdex?  Why isn't Tango std.* and Phobos stdsimple?
 
 Ok, ignoring egos, the problem is that they wouldn't work together
 anyway.  An old favourite of mine is (again, sorry about this) IO.
 
 Phobos strives to be compatible with the C IO library; so you can
 interleave Phobos and C IO calls and it's all gravy.
 
 Tango takes C out the back and shoots it before burying it upside-down
 at a crossroads with a steak through the heart and salting the earth.

Sweet. I mean salty.
 You CAN mix Tango and C IO calls, but you really have no idea what order
 the output's going to arrive in.
 
 I remember Andrei getting antsy about this a while back; why break
 compatibility?!  Because Tango's IO was faster this way.  Neither one of
 them was 'right' because they both had legitimate points of view.
 
 Really, it all boils down to this: there *is no* one right way.  Yes,
 it's more confusing.  But it's a problem with programming in general;
 programming is all about looking at your options and making a decision
 on the matter.

In wake of some recent trials, it looks like I/O can be sped up without necessarily giving up on C compatibility. The range design, which will be central to much of Phobos2 (notably I/O) will pay close attention to not stand in the way of streamlined transfers. In my opinion an embarrassment of riches isn't necessarily bad. It was real bad only when using one library precluded using the other. Speaking of D2 in general, I think 2009 will be a big year. There has been a lot of great work done on D2 in the past couple of years, but quite little to show for it in terms of code and publications. This has frustrated Walter and myself at times, but when we talked about it we always reached the conclusion that we have a sound plan and that sometimes you just have to keep on working for those mythical delayed rewards. Well, this year it looks like at least some of those rewards will materialize. Speaking of Phobos2 in particular, if I manage to execute at least part of my vision on Phobos2, it will become a powerful and thoroughly pleasant to use library. Andrei
Jan 17 2009
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Andrei,


 In my opinion an embarrassment of riches isn't necessarily bad. It was
 real bad only when using one library precluded using the other.

True.
 Speaking of D2 in general, I think 2009 will be a big year. There has
 been a lot of great work done on D2 in the past couple of years, but
 quite little to show for it in terms of code and publications. This
 has frustrated Walter and myself at times, but when we talked about it
 we always reached the conclusion that we have a sound plan and that
 sometimes you just have to keep on working for those mythical delayed
 rewards. Well, this year it looks like at least some of those rewards
 will materialize.  Speaking of Phobos2 in particular, if I manage to
 execute at least part of my vision on Phobos2, it will become a
 powerful and thoroughly pleasant to use library.
 
 Andrei
 

Sounds exciting. Hope it all works out. It's especially nice to hear even a general statement of direction here now and again. So thank-you. I know it must be tough slogging. :) -JJR
Jan 17 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
John Reimer wrote:
 Sounds exciting.  Hope it all works out.
 It's especially nice to hear even a general statement of direction here 
 now and again. So thank-you.  I know it must be tough slogging. :)

I know I've been quiet lately, but that doesn't mean I'm not working on D. In fact, I've been spending more hours on it than ever. There's a lot of cool stuff coming!
Jan 18 2009
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Walter Bright Wrote:

 John Reimer wrote:
 Sounds exciting.  Hope it all works out.
 It's especially nice to hear even a general statement of direction here 
 now and again. So thank-you.  I know it must be tough slogging. :)

I know I've been quiet lately, but that doesn't mean I'm not working on D. In fact, I've been spending more hours on it than ever. There's a lot of cool stuff coming!

Care to share your top 5 priorities? IIRC, when the user community was polled for their top 5, fixing the Tango/Phobos thing was on top of most lists. Druntime is a great step in that direction, but it's not enough. Without other communication on the topic from either side, it appears that the merger effort has fizzled and died. Can you (or whoever is qualified to answer) shed light on what's going on there?
Jan 18 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Jason House wrote:
 Care to share your top 5 priorities?

Support for threading is the biggest.
 IIRC, when the user community
 was polled for their top 5, fixing the Tango/Phobos thing was on top
 of most lists. Druntime is a great step in that direction, but it's
 not enough. Without other communication on the topic from either
 side, it appears that the merger effort has fizzled and died. Can you
 (or whoever is qualified to answer) shed light on what's going on
 there?

Druntime is there, and it's up to the Tango team now.
Jan 18 2009
next sibling parent John Reimer <terminal.node gmail.com> writes:
Hello Walter,

 Jason House wrote:
 
 Care to share your top 5 priorities?
 

 IIRC, when the user community
 was polled for their top 5, fixing the Tango/Phobos thing was on top
 of most lists. Druntime is a great step in that direction, but it's
 not enough. Without other communication on the topic from either
 side, it appears that the merger effort has fizzled and died. Can you
 (or whoever is qualified to answer) shed light on what's going on
 there?


Well, it's probably best to be a little more specific here. I'm assuming you mean to say that it's up to Tango to port to D2.0 and then integrate the druntime. This is true if we are merely talking about the common base. That step is not likely to happen until D2.0 is finalized (in the sense that there will be no support for the Tango 2 port until D2.0 is stable). In this regard, there's nothing to be done right now until that happens because it's not yet clear what Tango's plans are for D 2.0. But it appears that a port will happen (it's already partially done). And if it is completed, the Phobos 2 and Tango 2 /might/ be revisited at a higher level (now with a common druntime making things easier). As Andrei will be releasing a book in 2009, Phobos 2 will be the only library immediately visible to the public for the D 2.0 language. If Tango V2 popularity surges again... well, we just might have the same problem. I guess it's just a little "iffy", and it's good to be aware of this. I think it's good to keep brainstorming on it in case there is some sort of solution lurking in the dark recesses of this community or elsewhere. -JJR
Jan 18 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
Walter Bright wrote:

 Druntime is there, and it's up to the Tango team now.

As I understand it, the biggest fear of the Tango team is to make an official D2 version and then have to chase after a moving standard. If an official port of Tango 0.99.7 was ported to work with dmd v2.023 how willing would you be to ensure that the D2 Tango was functional prior to new releases of dmd? I don't necessarily mean that you personally hack at Tango D2 for every release with breaking changes but rather that you have people lined up to compile and run unit tests, and fix problems prior to each release? If the answer to that is yes, I'd be happy to sign up as a tester/fixer. I can guarantee that I won't be able to do a large number of fixes before a release, but would be able to do some. For most releases, that may be enough. For big breaking changes, we'd need several tester/fixer people. I also can't do a D2 + druntime port. I think there's already a pre-druntime port of Tango to D2. I doubt I could do that job, and won't sign up for it. I also won't sign up for porting new Tango functionality to D2 either. Even with all of these restrictions, I believe that this could work for the next year or two while D2 solidifies its design. I'd absolutely love to see this, which is why I'm willing to help maintain it. Maybe there will be other inspired individuals who would do the initial Tango D2 port and others who may periodically update D2 Tango to match the latest and greatest Tango D1 release.
Jan 19 2009
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jason House" wrote
 Walter Bright wrote:

 Druntime is there, and it's up to the Tango team now.

As I understand it, the biggest fear of the Tango team is to make an official D2 version and then have to chase after a moving standard. If an official port of Tango 0.99.7 was ported to work with dmd v2.023 how willing would you be to ensure that the D2 Tango was functional prior to new releases of dmd? I don't necessarily mean that you personally hack at Tango D2 for every release with breaking changes but rather that you have people lined up to compile and run unit tests, and fix problems prior to each release?

As far as I know, Walter has stated that he is willing to issue a quick fix release for easily fixed bugs that hurt Tango. This already happens with the D1 releases, and I'm sure he'd extend that courtesy for D2 releases once Tango D2 is relatively stable. I agree with Walter that the ball is fully in Tango's court. D2 not being stable is probably the largest reason that most of the Tango devs aren't yet interested, but it doesn't stop some of us from trying :) Probably the largest hurdle right now is const-ifying all of Tango. Most of the time, this doesn't just imply slapping a const or immutable label on something, but really rethinking how a particular module is implemented to cater to const properly. Thankfully, however, const is now a stable target. Once pure/shared/unshared gets introduced, it will probably require more effort, but probably not as much as with const.
 If the answer to that is yes, I'd be happy to sign up as a tester/fixer. 
 I can guarantee that I won't be able to do a large number of fixes before 
 a release, but would be able to do some.  For most releases, that may be 
 enough.  For big breaking changes, we'd need several tester/fixer people. 
 I also can't do a D2 + druntime port.  I think there's already a 
 pre-druntime port of Tango to D2.  I doubt I could do that job, and won't 
 sign up for it.  I also won't sign up for porting new Tango functionality 
 to D2 either.

 Even with all of these restrictions, I believe that this could work for 
 the next year or two while D2 solidifies its design.  I'd absolutely love 
 to see this, which is why I'm willing to help maintain it.  Maybe there 
 will be other inspired individuals who would do the initial Tango D2 port 
 and others who may periodically update D2 Tango to match the latest and 
 greatest Tango D1 release.

It's already being worked on, albeit slowly... Need more free time :) Any help is appreciated. My motivation for doing the port is to ensure D2's design is tested fully, as I believe many of the features aren't completely tested with Phobos alone. I've already found several D2 bugs just by porting some of Tango. My biggest fear is that D2 is released with some design decision that makes Tango impossible to port. -Steve
Jan 19 2009
parent Lars Ivar Igesund <larsivar igesund.net> writes:
Steven Schveighoffer wrote:

 "Jason House" wrote
 Walter Bright wrote:

 Druntime is there, and it's up to the Tango team now.

As I understand it, the biggest fear of the Tango team is to make an official D2 version and then have to chase after a moving standard. If an official port of Tango 0.99.7 was ported to work with dmd v2.023 how willing would you be to ensure that the D2 Tango was functional prior to new releases of dmd? I don't necessarily mean that you personally hack at Tango D2 for every release with breaking changes but rather that you have people lined up to compile and run unit tests, and fix problems prior to each release?

As far as I know, Walter has stated that he is willing to issue a quick fix release for easily fixed bugs that hurt Tango. This already happens with the D1 releases, and I'm sure he'd extend that courtesy for D2 releases once Tango D2 is relatively stable. I agree with Walter that the ball is fully in Tango's court. D2 not being stable is probably the largest reason that most of the Tango devs aren't yet interested, but it doesn't stop some of us from trying :) Probably the largest hurdle right now is const-ifying all of Tango. Most of the time, this doesn't just imply slapping a const or immutable label on something, but really rethinking how a particular module is implemented to cater to const properly. Thankfully, however, const is now a stable target. Once pure/shared/unshared gets introduced, it will probably require more effort, but probably not as much as with const.

There is also the question of how SafeD should be catered for. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Jason House wrote:
 Walter Bright wrote:
 
 Druntime is there, and it's up to the Tango team now.

As I understand it, the biggest fear of the Tango team is to make an official D2 version and then have to chase after a moving standard. If an official port of Tango 0.99.7 was ported to work with dmd v2.023 how willing would you be to ensure that the D2 Tango was functional prior to new releases of dmd? I don't necessarily mean that you personally hack at Tango D2 for every release with breaking changes but rather that you have people lined up to compile and run unit tests, and fix problems prior to each release?

Prior to a release, I send it around to a few people who build and check Tango and a couple other things against it.
 If the answer to that is yes, I'd be happy to sign up as a
 tester/fixer.  I can guarantee that I won't be able to do a large
 number of fixes before a release, but would be able to do some.  For
 most releases, that may be enough.  For big breaking changes, we'd
 need several tester/fixer people.  I also can't do a D2 + druntime
 port.  I think there's already a pre-druntime port of Tango to D2.  I
 doubt I could do that job, and won't sign up for it.  I also won't
 sign up for porting new Tango functionality to D2 either.
 
 Even with all of these restrictions, I believe that this could work
 for the next year or two while D2 solidifies its design.  I'd
 absolutely love to see this, which is why I'm willing to help
 maintain it.  Maybe there will be other inspired individuals who
 would do the initial Tango D2 port and others who may periodically
 update D2 Tango to match the latest and greatest Tango D1 release.

I (and others) keep Phobos2 up to date with every iteration of D2. It hasn't been much work, primarily because I avoid making changes in D2 that will silently break code. So when things break, they break noisily <g> and are easy to fix. Also contributing to the ease of keeping it up to date is a good set of unittests, although they could be better still. Even the simplest of unit tests save boatloads of grief down the line. I've got plenty of experience with them now <g>. I'm sure the Tango team will welcome your help!
Jan 19 2009
prev sibling parent John Reimer <terminal.node gmail.com> writes:
Hello Walter,

 John Reimer wrote:
 
 Sounds exciting.  Hope it all works out.
 It's especially nice to hear even a general statement of direction
 here
 now and again. So thank-you.  I know it must be tough slogging. :)

on D. In fact, I've been spending more hours on it than ever. There's a lot of cool stuff coming!

Thank you much for the feedback. I think the posts here are just a reminder that dealing with the human element is just as important (if not more important) than working with the design and implementation element... simply because without the former, the latter can fall flat. Perhaps I should have shown more restraint in my prior posts. I've persisted because I am really just hoping that you are aware of significance of the problem you are facing. The general silence on the matter makes things horribly inconclusive. At the same time, I don't like to be pushing a gloomy perspective on it all, but this particular point is something that really needs defusing... not with placations but with a clearly laid out game plan that shows you have it all in hand. I guess we'll see what 2009 holds and whether we can be as optimistic and you and Andrei are. :) -JJR
Jan 18 2009
prev sibling next sibling parent Piotrek <starpit tlen.pl> writes:
Andrei Alexandrescu pisze:

 The capabilities of a language strongly influence its standard library, 
 and at best Phobos2 will espouse and promote the idioms that we strove 
 to make possible. After all, we wanted to introduce new features because 
 they'd help in writing good code, so the standard library should take 
 advantage of them almost by definition. That's why phobos is not being 
 "ported" to D2, it is being rewritten for D2.

I'm 100% for that. To be clear. It wasn't my intention to ask for merging those libraries (in terms of philosophy, design strategy and development). I'm really happy as it is now (druntime for my future D2 usage). All I wanted was simple renaming (simple from my point of view - not from developers and maintainers) which in my opinion (not advanced programmer) could be cool.
 Speaking of D2 in general, I think 2009 will be a big year. There has 
 been a lot of great work done on D2 in the past couple of years, but 
 quite little to show for it in terms of code and publications. This has 
 frustrated Walter and myself at times, but when we talked about it we 
 always reached the conclusion that we have a sound plan and that 
 sometimes you just have to keep on working for those mythical delayed 
 rewards. 

I hope it will be like all you said. I'm really grateful for all you do (also Tango Team and all developers on dsource). And when I am good enough I will give my contribution too. Cheers
Jan 18 2009
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 For example, I'm not sure how code in std.algorithm
 could help containers or streams in Tango (as it should), or how to
 reconcile std.algorithm with std.core.array.

If the language (D2++) will have a new way of iteration and ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
next sibling parent BLS <nanali nospam.wanadoo.fr> writes:
Lars Ivar Igesund schrieb:
 Andrei Alexandrescu wrote:
 
 For example, I'm not sure how code in std.algorithm
 could help containers or streams in Tango (as it should), or how to
 reconcile std.algorithm with std.core.array.

If the language (D2++) will have a new way of iteration and ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

iteration. would be a proof of product too. Bjoern
Jan 18 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

If the language (D2++) will have a new way of iteration and ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

It's been there for a while now (since 25 Nov 2008). http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement." Andrei
Jan 18 2009
next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Sun, 18 Jan 2009 07:21:55 -0800, Andrei Alexandrescu wrote:

 It's been there for a while now (since 25 Nov 2008).
 
 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement
 
 Scroll down to "Foreach over Structs and Classes with Ranges".

Nice to finally have it in the docs. The properties table says '.rear', and an example says '.tail', which is correct?
Jan 18 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
Sergey Gromov wrote:
 The properties table says '.rear', and an example says '.tail', which is
 correct?

Neither. It's ".toe". I've corrected the docs.
Jan 18 2009
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

If the language (D2++) will have a new way of iteration and ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

It's been there for a while now (since 25 Nov 2008). http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement."

Ah, thanks :) However, replacing the "single" opApply with 5 properties seems somewhat excessive? At least it becomes even more obvious that a form of (runtime queryable) struct interfaces will be necessary - the one and only feature I really really want in D2. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 For example, I'm not sure how code in std.algorithm could help 
 containers or streams in Tango (as it should), or how to
 reconcile std.algorithm with std.core.array.

ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement."

Ah, thanks :) However, replacing the "single" opApply with 5 properties seems somewhat excessive? At least it becomes even more obvious that a form of (runtime queryable) struct interfaces will be necessary - the one and only feature I really really want in D2.

opApply was very inefficient and defining an abstraction that allows efficient iteration was a key goal of range design and foreach overhaul. Using duck typing and implicit interfaces was a tried and true technique. On top of this framework it is easy to define and use explicit interfaces. Using classic interfaces would have hamstrung efficiency of iteration from day one. I'd be curious to find out more about a runtime queryable struct interface. How would it work? What idioms would it enable? Andrei
Jan 18 2009
next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to
 reconcile std.algorithm with std.core.array.

ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement."

Ah, thanks :) However, replacing the "single" opApply with 5 properties seems somewhat excessive? At least it becomes even more obvious that a form of (runtime queryable) struct interfaces will be necessary - the one and only feature I really really want in D2.

opApply was very inefficient and defining an abstraction that allows efficient iteration was a key goal of range design and foreach overhaul. Using duck typing and implicit interfaces was a tried and true technique. On top of this framework it is easy to define and use explicit interfaces. Using classic interfaces would have hamstrung efficiency of iteration from day one. I'd be curious to find out more about a runtime queryable struct interface. How would it work? What idioms would it enable?

The point is that with classes and interfaces, you can query the class (at runtime) for whether it contains a certain set of functionality. Now, I know that the virtuality of doing so isn't the most efficient in most cases, but that is besides the point - if there is an efficient way of doing this with structs, then that should work with classes too. When you have functionality (at runtime) that relies only on a container to have a specific set of functions/properties/methods, then it seems unfair to restrict that to classes. In practice I see this as something that operates via additional type info. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 For example, I'm not sure how code in std.algorithm could 
 help containers or streams in Tango (as it should), or how 
 to reconcile std.algorithm with std.core.array.

ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement."

However, replacing the "single" opApply with 5 properties seems somewhat excessive? At least it becomes even more obvious that a form of (runtime queryable) struct interfaces will be necessary - the one and only feature I really really want in D2.

allows efficient iteration was a key goal of range design and foreach overhaul. Using duck typing and implicit interfaces was a tried and true technique. On top of this framework it is easy to define and use explicit interfaces. Using classic interfaces would have hamstrung efficiency of iteration from day one. I'd be curious to find out more about a runtime queryable struct interface. How would it work? What idioms would it enable?

The point is that with classes and interfaces, you can query the class (at runtime) for whether it contains a certain set of functionality.

I think there are a number of confusions and misunderstandings at work here on top of one another, so allow me to try and clarify a couple. "Five properties versus one opApply seems excessive. Therefore, a form of runtime-queryable interface for struct is necessary." The latter doesn't follow from the former. If five properties in an implicit interface seems too many, then what you might be asking for is explicit interfaces, not dynamic-polymorphic interfaces. Something along the lines of: interface InputRange(T) { void next(); bool empty(); T head(); } struct RandomGenerator : InputRange!(int) { ... } class IntStream : InputRange!(int) { ... } The two would follow different implementation strategies. For structs the interface would be statically checked. In all likelihood, this feature will be part of D2 because it allows for easy concept checking.
 Now, I know that the virtuality of doing so isn't the most efficient
 in most cases, but that is besides the point - if there is an
 efficient way of doing this with structs, then that should work with
 classes too.

This I don't understand at all. Yes, implicit interfaces do work with structs and classes and equally well.
 When you have functionality (at runtime) that relies only on a 
 container to have a specific set of functions/properties/methods, 
 then it seems unfair to restrict that to classes. In practice I see 
 this as something that operates via additional type info.

I confess I read this one more than a few times and couldn't understand it. So let me read it back in my own words: "You want to implement runtime functionality (?) by relying on the existence of a specific set of functions/properties/methods. It is unfair to restrict that to classes, so I'd like that to work for structs too. The way I see this working is by adding extra type info to structs." This doesn't do anything in terms of clarifying things for me, so I'd appreciate more info. Andrei
Jan 18 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
Andrei Alexandrescu wrote:

 I'd be curious to find out more about a runtime queryable struct
 interface. How would it work? What idioms would it enable?

I don't know what Lars is thinking of, but I think of struct interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions e.g. template usesRanges( T : ForwardRange ){ ... } usesRanges!(int) x; LameExample.d: 243: Error int does not implement ForwardRange concept Ranges.d: 12: head() not implemented Ranges.d: 13: empty() not implemented Ranges.d: 14: next() not implemented Looking really quickly at http://en.wikipedia.org/wiki/C%2B%2B0x#Concepts I think I'm probably thinking of what C++0x calls Concepts. I didn't read enough to see if it's exactly what I'm thinking or just a close match. While every template that uses forward ranges could make a messy criteria using if clauses after the template, it may simply be too hard to read and too long to write. The template above would work without any extra if criteria... Misuse of the template will give cryptic compiler errors oddly reminiscent of STL...
Jan 18 2009
next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Jason House wrote:

 Andrei Alexandrescu wrote:
 
 I'd be curious to find out more about a runtime queryable struct
 interface. How would it work? What idioms would it enable?

I don't know what Lars is thinking of, but I think of struct interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

Nope, I want something that works at runtime. Inheritance could/should be non-polymorphic and compile-time, but I want to know at runtime that a void* has implemented a given interface. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Jason House wrote:
 
 Andrei Alexandrescu wrote:
 
 I'd be curious to find out more about a runtime queryable struct 
 interface. How would it work? What idioms would it enable?

interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

Nope, I want something that works at runtime. Inheritance could/should be non-polymorphic and compile-time, but I want to know at runtime that a void* has implemented a given interface.

Consider you can avail yourself of a function: bool implements(Interface)(void* p); What would you do with it? Andrei
Jan 18 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 Jason House wrote:
 
 Andrei Alexandrescu wrote:
 
 I'd be curious to find out more about a runtime queryable struct
 interface. How would it work? What idioms would it enable?

interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

Nope, I want something that works at runtime. Inheritance could/should be non-polymorphic and compile-time, but I want to know at runtime that a void* has implemented a given interface.

Consider you can avail yourself of a function: bool implements(Interface)(void* p); What would you do with it?

Assuming that I (after getting a positive result from a call to the above, and that I have an interface with the member foo) can then safely call p.foo, I could do a lot of stuff that I can't do today. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Jason House wrote:
 
 Andrei Alexandrescu wrote:
 
 I'd be curious to find out more about a runtime queryable
 struct interface. How would it work? What idioms would it
 enable?

interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

could/should be non-polymorphic and compile-time, but I want to know at runtime that a void* has implemented a given interface.

bool implements(Interface)(void* p); What would you do with it?

Assuming that I (after getting a positive result from a call to the above, and that I have an interface with the member foo) can then safely call p.foo, I could do a lot of stuff that I can't do today.

I understand. So essentially you don't want to see whether a void* implements an interface, but instead you want to get that interface, i.e. obtain the pointers to the functions in the interface as implemented by whatever struct that void* stands for. In doing so you also claim that all of that is entirely possible to do so at low or no cost. After the functions in that interface are obtained, you also implicitly claim that they won't hurt performance of the design by using indirect calls. If my understanding of the above is correct, this is an extraordinary claim. It is, in fact, so extraordinary that I'll bite the bullet and claim myself that you are thoroughly confused about what you want and to what extent it is realizable. My guess is that if you follow your idea to its ultimate conclusion, you will be inexorably drawn to rediscovering how vtables work and what tradeoffs they embed when compared to direct function calls. Andrei
Jan 18 2009
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Andrei,

 Lars Ivar Igesund wrote:
 
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 
 Jason House wrote:
 
 Andrei Alexandrescu wrote:
 
 I'd be curious to find out more about a runtime queryable struct
 interface. How would it work? What idioms would it enable?
 

interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

could/should be non-polymorphic and compile-time, but I want to know at runtime that a void* has implemented a given interface.

bool implements(Interface)(void* p); What would you do with it?

above, and that I have an interface with the member foo) can then safely call p.foo, I could do a lot of stuff that I can't do today.

implements an interface, but instead you want to get that interface, i.e. obtain the pointers to the functions in the interface as implemented by whatever struct that void* stands for. In doing so you also claim that all of that is entirely possible to do so at low or no cost. After the functions in that interface are obtained, you also implicitly claim that they won't hurt performance of the design by using indirect calls. If my understanding of the above is correct, this is an extraordinary claim. It is, in fact, so extraordinary that I'll bite the bullet and claim myself that you are thoroughly confused about what you want and to what extent it is realizable. My guess is that if you follow your idea to its ultimate conclusion, you will be inexorably drawn to rediscovering how vtables work and what tradeoffs they embed when compared to direct function calls. Andrei

I wonder if anybody finds you intimidating in person. :D -JJR
Jan 18 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
John Reimer wrote:
 I wonder if anybody finds you intimidating in person. :D

That depends on who is buying the beer <g>.
Jan 18 2009
parent John Reimer <terminal.node gmail.com> writes:
Hello Walter,

 John Reimer wrote:
 
 I wonder if anybody finds you intimidating in person. :D
 


I'm bet its always free for him. ;-D -JJR
Jan 18 2009
prev sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Jason House wrote:
 
 Andrei Alexandrescu wrote:
 
 I'd be curious to find out more about a runtime queryable
 struct interface. How would it work? What idioms would it
 enable?

interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

could/should be non-polymorphic and compile-time, but I want to know at runtime that a void* has implemented a given interface.

bool implements(Interface)(void* p); What would you do with it?

Assuming that I (after getting a positive result from a call to the above, and that I have an interface with the member foo) can then safely call p.foo, I could do a lot of stuff that I can't do today.

I understand. So essentially you don't want to see whether a void* implements an interface, but instead you want to get that interface, i.e. obtain the pointers to the functions in the interface as implemented by whatever struct that void* stands for. In doing so you also claim that all of that is entirely possible to do so at low or no cost. After the functions in that interface are obtained, you also implicitly claim that they won't hurt performance of the design by using indirect calls. If my understanding of the above is correct, this is an extraordinary claim. It is, in fact, so extraordinary that I'll bite the bullet and claim myself that you are thoroughly confused about what you want and to what extent it is realizable. My guess is that if you follow your idea to its ultimate conclusion, you will be inexorably drawn to rediscovering how vtables work and what tradeoffs they embed when compared to direct function calls.

No, you misunderstand. I said safely call, not exceptionally efficient. To me a virtual call would be acceptable. However, at least in my cases, there would normally not be more than one imlemented interface and such it would be a tiny vtable. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not exceptionally
 efficient. To me a virtual call would be acceptable. However, at
 least in my cases, there would normally not be more than one
 imlemented interface and such it would be a tiny vtable.

Ok, so the scope is reducing nicely. We now have a few problems to solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments); where T is the result type of Interface.method. Is this what you want? Andrei
Jan 18 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not exceptionally
 efficient. To me a virtual call would be acceptable. However, at
 least in my cases, there would normally not be more than one
 imlemented interface and such it would be a tiny vtable.

Ok, so the scope is reducing nicely. We now have a few problems to solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments);

Since you used template lingo, it looks a bit like compile time functionality, but yes, very close now :) Also (I keep forgetting to mention important details) - I typically see this used in variadic functions, such that the typeinfo already is there. And an additional question only semi-related to the above; is it possible to have a function that works as a variadic function, but where the number of arguments is restricted to 1 (or 2 or 3 but not unbounded). Oh oh, I'm getting into a steam (and even less related ...) - variadic ref parameters. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not exceptionally 
 efficient. To me a virtual call would be acceptable. However, at 
 least in my cases, there would normally not be more than one 
 imlemented interface and such it would be a tiny vtable.

solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments);

Since you used template lingo, it looks a bit like compile time functionality, but yes, very close now :) Also (I keep forgetting to mention important details) - I typically see this used in variadic functions, such that the typeinfo already is there.

But what are you ultimately trying to accomplish, and why do you must lose all static information since it was just available to the caller? Isn't there a simpler way to achieve your goal (e.g. using the new variadics)? You are essentially asking for full-blown runtime scripting for all structs.
 And an additional question only semi-related to the above; is it
 possible to have a function that works as a variadic function, but
 where the number of arguments is restricted to 1 (or 2 or 3 but not
 unbounded).

void foo(R..)(R args) if (R.length == 2) { ... } It doesn't work now due to a bug in the compiler, you may want to submit it.
 Oh oh, I'm getting into a steam (and even less related ...) -
 variadic ref parameters.
 

That will be fixed. Andrei
Jan 20 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not exceptionally
 efficient. To me a virtual call would be acceptable. However, at
 least in my cases, there would normally not be more than one
 imlemented interface and such it would be a tiny vtable.

solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments);

Since you used template lingo, it looks a bit like compile time functionality, but yes, very close now :) Also (I keep forgetting to mention important details) - I typically see this used in variadic functions, such that the typeinfo already is there.

But what are you ultimately trying to accomplish, and why do you must lose all static information since it was just available to the caller? Isn't there a simpler way to achieve your goal (e.g. using the new variadics)? You are essentially asking for full-blown runtime scripting for all structs.

Sorry; new variadics? -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 21 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not exceptionally
 efficient. To me a virtual call would be acceptable. However, at
 least in my cases, there would normally not be more than one
 imlemented interface and such it would be a tiny vtable.

solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments);

functionality, but yes, very close now :) Also (I keep forgetting to mention important details) - I typically see this used in variadic functions, such that the typeinfo already is there.

lose all static information since it was just available to the caller? Isn't there a simpler way to achieve your goal (e.g. using the new variadics)? You are essentially asking for full-blown runtime scripting for all structs.

Sorry; new variadics?

http://www.digitalmars.com/d/2.0/variadic-function-templates.html Your use case suggests you are using the "look, ma, no templates" solution, whereas the new variadics are shown below that section. Andrei
Jan 21 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not exceptionally
 efficient. To me a virtual call would be acceptable. However, at
 least in my cases, there would normally not be more than one
 imlemented interface and such it would be a tiny vtable.

solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments);

functionality, but yes, very close now :) Also (I keep forgetting to mention important details) - I typically see this used in variadic functions, such that the typeinfo already is there.

lose all static information since it was just available to the caller? Isn't there a simpler way to achieve your goal (e.g. using the new variadics)? You are essentially asking for full-blown runtime scripting for all structs.

Sorry; new variadics?

http://www.digitalmars.com/d/2.0/variadic-function-templates.html Your use case suggests you are using the "look, ma, no templates" solution, whereas the new variadics are shown below that section.

Right, but the "new variadics" cannot (being templates) be virtual (which at least sometimes is useful). -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 21 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:
 
 Lars Ivar Igesund wrote:
 No, you misunderstand. I said safely call, not
 exceptionally efficient. To me a virtual call would be
 acceptable. However, at least in my cases, there would
 normally not be more than one imlemented interface and
 such it would be a tiny vtable.

problems to solve (some details glossed over for simplicity). a) Get from void* to the TypeInfo that's typing that void*. This will involve a search as the void* could point really anywhere, including untyped memory. So we have a core function: TypeInfo fromAddress(void * p); b) Starting from a TypeInfo, get an interface in case the underlying struct implements that interface: Object TypeInfo.QueryInterface(TypeInfo someInterface); c) Finally, given a void* and an interface, invoke a method of that interface: T structCast!(Interface)(p).method(arguments);

time functionality, but yes, very close now :) Also (I keep forgetting to mention important details) - I typically see this used in variadic functions, such that the typeinfo already is there.

you must lose all static information since it was just available to the caller? Isn't there a simpler way to achieve your goal (e.g. using the new variadics)? You are essentially asking for full-blown runtime scripting for all structs.


Your use case suggests you are using the "look, ma, no templates" solution, whereas the new variadics are shown below that section.

Right, but the "new variadics" cannot (being templates) be virtual (which at least sometimes is useful).

Templates can always forward to non-templates the void* and pointers to functions of interest that know how to handle the void*. The new code in std.format does that. The solution can be easily extended to forward to interfaces that are created and allocated suitably. Essentially what I'm saying is, if you're asking for a feature there should be a reasonably clear picture of the implementation possible attacks and of the various consequences of the tradeoffs involved. I understand it would be nice to have structs automatically offer runtime-queriable interfaces at no per-instance cost, no dynamic allocation, and with free bonus miles, but then that's only a deceptively little part of the story. Andrei
Jan 21 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jason House" wrote
 Andrei Alexandrescu wrote:

 I'd be curious to find out more about a runtime queryable struct
 interface. How would it work? What idioms would it enable?

I don't know what Lars is thinking of, but I think of struct interfaces as a non-polymorphic / compile-time inheritance. AKA, you can have a struct implement it, but you can't cast it to a base struct/interface. Outside of defining the struct, I'd expect it to only be usable in templates and is-expressions

I would expect a struct interface to be castable to the interface. Otherwise, you get no benefit from having it. You can already use compile-time interfaces with concepts and templates. The issue then becomes to make a struct interface act the same as a class interface. Unfortunately, a class interface value only contains a vtable pointer (I think), which contains the offset to get to the actual class pointer. If the class pointer was passed with the interface, this would be much easier, but might be slower when doing class interfaces (passing 2 pointers instead of 1). You could put an interface vtable pointer at the beginning of a struct, which then makes every struct carry that extra baggage. And then a virtual call is required, but would allow much more dynamic behavior. You could build a temporary interface "structure" which does the thunk to point to the real struct, since you don't have to deal with possible inheritance, to avoid putting a vtable in the struct. There are probably other ways. In any case, having struct interfaces probably is not the best method for ranges, where you would be doing a virtual call over and over again. But it would be hugely beneficial for things like non-templated I/O, or serialization. One problem to consider is that it is much easier for a struct to escape it's scope, so you may have to require a scope parameter to pass a struct as an interface. -Steve
Jan 19 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Sun, 18 Jan 2009 18:21:55 +0300, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

It's been there for a while now (since 25 Nov 2008). http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement." Andrei

There is a typo in docs (http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement): Foreach Range Properties: .rear return the rightmost element of the range ... for (auto __r = range; !__r.empty; __r.retreat) { auto e = __r.tail; //<- tail or rear? ... }

Turns out Walter didn't like "rear" for a certain reason. :o) He did take to my cute "toe" but in the end did not reflect that in the dox. The following code compiles and runs: struct S { bool empty() {return true;} void next() {} void retreat() {} int head() { return 0; } int toe() { return 0; } } void main() { S s; foreach (e; s) {} foreach_reverse (e; s) {} } Andrei
Jan 18 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu wrote:

 Denis Koroskin wrote:
 On Sun, 18 Jan 2009 18:21:55 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

It's been there for a while now (since 25 Nov 2008). http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement." Andrei

There is a typo in docs (http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement): Foreach Range Properties: .rear return the rightmost element of the range ... for (auto __r = range; !__r.empty; __r.retreat) { auto e = __r.tail; //<- tail or rear? ... }

Turns out Walter didn't like "rear" for a certain reason. :o) He did take to my cute "toe" but in the end did not reflect that in the dox. The following code compiles and runs: struct S { bool empty() {return true;} void next() {} void retreat() {} int head() { return 0; } int toe() { return 0; } } void main() { S s; foreach (e; s) {} foreach_reverse (e; s) {} } Andrei

toe() ?! tail() good, rear() not so good, toe() sucks. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Lars Ivar Igesund wrote:

 Andrei Alexandrescu wrote:
 
 Denis Koroskin wrote:
 On Sun, 18 Jan 2009 18:21:55 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

It's been there for a while now (since 25 Nov 2008). http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement." Andrei

There is a typo in docs (http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement): Foreach Range Properties: .rear return the rightmost element of the range ... for (auto __r = range; !__r.empty; __r.retreat) { auto e = __r.tail; //<- tail or rear? ... }

Turns out Walter didn't like "rear" for a certain reason. :o) He did take to my cute "toe" but in the end did not reflect that in the dox. The following code compiles and runs: struct S { bool empty() {return true;} void next() {} void retreat() {} int head() { return 0; } int toe() { return 0; } } void main() { S s; foreach (e; s) {} foreach_reverse (e; s) {} } Andrei

toe() ?! tail() good, rear() not so good, toe() sucks.

I think I remember there being a discussion about this, but I wasn't aware that the outcome was this bad so let me qualify my opinion. Only on humans (and possibly some apes) can toe be considered the other end, but even with humans the heel is more correct with the toes being a sort of peripherals. On most animals (and birds), the tail will be the other end of the head. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 18 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks. 

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().
Jan 18 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...
Jan 18 2009
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-01-18 16:43:30 -0500, Yigal Chripun <yigal100 gmail.com> said:

 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

e) front, back. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 18 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Yigal Chripun wrote:
 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

There doesn't really need to be anything wrong with them. What's wrong with head/toe?
Jan 18 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Walter Bright wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

There doesn't really need to be anything wrong with them. What's wrong with head/toe?

It sounds stupid.
Jan 18 2009
next sibling parent Yigal Chripun <yigal100 gmail.com> writes:
Christopher Wright wrote:
 Walter Bright wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

There doesn't really need to be anything wrong with them. What's wrong with head/toe?

It sounds stupid.

it sounds stupid and is uninformative. for example, auto cars = new BinaryTree!(Car)(); auto a = cars.toe; auto b = cars.last; now, reading the above, what's the toe of cars? that's just silly. Does this make sense to English speakers? most likly. but for say, chinese? I don't know. instead of inveting terms than imply something based on some phrase that not all non-native English speakers will recognize, it is far better to just use the proper English term for the last item - "last". KISS solution.
Jan 18 2009
prev sibling next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Christopher,

 Walter Bright wrote:
 
 Yigal Chripun wrote:
 
 Walter Bright wrote:
 
 Lars Ivar Igesund wrote:
 
 toe() ?! tail() good, rear() not so good, toe() sucks.
 

programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

wrong with head/toe?


I agree that its ugly. Although, be prepared to see it turn into just another feature that we're going to have to get used to. :) -JJR
Jan 19 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
John Reimer wrote:
 Hello Christopher,
 
 Walter Bright wrote:

 Yigal Chripun wrote:

 Walter Bright wrote:

 Lars Ivar Igesund wrote:

 toe() ?! tail() good, rear() not so good, toe() sucks.

programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

wrong with head/toe?


I agree that its ugly. Although, be prepared to see it turn into just another feature that we're going to have to get used to. :)

If there's widespread opinion that the current choice of names is unfortunate, now is the perfect time to fix that as the names haven't been put in heavy use. Things to keep in mind: * The operations next and retreat are not necessarily antonyms. I mean retreat does NOT undo what next does. So next and previous aren't quite desirable. * "head" will be used much more often than "toe". Most of the time, empty, head, and next will be used. These are the elements that support input ranges. "toe" and "retreat" are for bidirectional ranges. * The terms should be applicable equally well to generators (series, random numbers...), streams (files, sockets...), collections (lists, arrays...) and the such. * Short, one-word terms are preferred. Last but not least, keep in mind that these discussions could go on forever and that someone's best naming convention is another's worst. Happy hunting :o). Andrei
Jan 19 2009
parent reply aarti_pl <aarti interia.pl> writes:
Andrei Alexandrescu pisze:
 John Reimer wrote:
 Hello Christopher,

 Walter Bright wrote:

 Yigal Chripun wrote:

 Walter Bright wrote:

 Lars Ivar Igesund wrote:

 toe() ?! tail() good, rear() not so good, toe() sucks.

programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

wrong with head/toe?


I agree that its ugly. Although, be prepared to see it turn into just another feature that we're going to have to get used to. :)

If there's widespread opinion that the current choice of names is unfortunate, now is the perfect time to fix that as the names haven't been put in heavy use. Things to keep in mind: * The operations next and retreat are not necessarily antonyms. I mean retreat does NOT undo what next does. So next and previous aren't quite desirable. * "head" will be used much more often than "toe". Most of the time, empty, head, and next will be used. These are the elements that support input ranges. "toe" and "retreat" are for bidirectional ranges. * The terms should be applicable equally well to generators (series, random numbers...), streams (files, sockets...), collections (lists, arrays...) and the such. * Short, one-word terms are preferred. Last but not least, keep in mind that these discussions could go on forever and that someone's best naming convention is another's worst. Happy hunting :o). Andrei

first - last advance - retreat Above seems to me much more streamlined, than current choice. BR Marcin Kuszczak (aarti_pl)
Jan 19 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
aarti_pl wrote:
 first - last
 advance - retreat

My preference: head - rhead next - rnext (or advance - radvance) The purpose of "retreat" and "toe" is to allow reverse iteration. "retreat" in not the opposite of "advance"/"next", it's the same operation applied to the other end of the range. So why not make this explicit by prefixing an 'r' to these reverse iteration functions? -- Rainer Deyke - rainerd eldwood.com
Jan 19 2009
prev sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Christopher Wright wrote:

 Walter Bright wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

There doesn't really need to be anything wrong with them. What's wrong with head/toe?

It sounds stupid.

Wholeheartedly agree. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
prev sibling next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

If the language (D2++) will have a new way of iteration and ranges known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement." Andrei

Nice. Glad to see that this is documented somewhere so I can start playing with it. One thing, though: In my dstats library, I have a custom hash table implementation that's used very heavily in my information theory module. (I have my reasons for using a custom hash table instead of the builtin, but they're beyond the scope of this post.) Right now, the hash table uses opApply. Now that I realize how horribly slow opApply is, I'd like to port this to ranges. However, I need to be able to iterate over either key, value pairs or just values. Is there any way to make this work with ranges?
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Sun, Jan 18, 2009 at 1:00 PM, dsimcha <dsimcha yahoo.com> wrote:
 Nice.  Glad to see that this is documented somewhere so I can start playing
with
 it.  One thing, though:  In my dstats library, I have a custom hash table
 implementation that's used very heavily in my information theory module.  (I
have
 my reasons for using a custom hash table instead of the builtin, but they're
 beyond the scope of this post.)  Right now, the hash table uses opApply.  Now
that
 I realize how horribly slow opApply is, I'd like to port this to ranges. 
However,
 I need to be able to iterate over either key, value pairs or just values.  Is
 there any way to make this work with ranges?

You could handle key or value iteration by using a proxy struct type that follows the range protocol, and have your hash table return one of those structs from methods such as "keysIter" or "valuesIter". But unless I'm mistaken, D2 still doesn't support returning tuples, so you still can't have keys _and_ values at the same time. (Unless you're content with using a Pair or something.)

Returning a std.typecons.Tuple is entirely possible. Andrei
Jan 18 2009
next sibling parent reply BLS <nanali nospam.wanadoo.fr> writes:
Andrei Alexandrescu schrieb:
 Jarrett Billingsley wrote:
 On Sun, Jan 18, 2009 at 1:00 PM, dsimcha <dsimcha yahoo.com> wrote:
 Nice.  Glad to see that this is documented somewhere so I can start 
 playing with
 it.  One thing, though:  In my dstats library, I have a custom hash 
 table
 implementation that's used very heavily in my information theory 
 module.  (I have
 my reasons for using a custom hash table instead of the builtin, but 
 they're
 beyond the scope of this post.)  Right now, the hash table uses 
 opApply.  Now that
 I realize how horribly slow opApply is, I'd like to port this to 
 ranges.  However,
 I need to be able to iterate over either key, value pairs or just 
 values.  Is
 there any way to make this work with ranges?

You could handle key or value iteration by using a proxy struct type that follows the range protocol, and have your hash table return one of those structs from methods such as "keysIter" or "valuesIter". But unless I'm mistaken, D2 still doesn't support returning tuples, so you still can't have keys _and_ values at the same time. (Unless you're content with using a Pair or something.)

Returning a std.typecons.Tuple is entirely possible. Andrei

tuple(K,V) foo(K,V)(K k, V v) { ... } ????, I have no idea, pls help Bjoern
Jan 18 2009
parent reply BLS <nanali nospam.wanadoo.fr> writes:
BLS schrieb:
 Andrei Alexandrescu schrieb:
 Jarrett Billingsley wrote:
 On Sun, Jan 18, 2009 at 1:00 PM, dsimcha <dsimcha yahoo.com> wrote:
 Nice.  Glad to see that this is documented somewhere so I can start 
 playing with
 it.  One thing, though:  In my dstats library, I have a custom hash 
 table
 implementation that's used very heavily in my information theory 
 module.  (I have
 my reasons for using a custom hash table instead of the builtin, but 
 they're
 beyond the scope of this post.)  Right now, the hash table uses 
 opApply.  Now that
 I realize how horribly slow opApply is, I'd like to port this to 
 ranges.  However,
 I need to be able to iterate over either key, value pairs or just 
 values.  Is
 there any way to make this work with ranges?

You could handle key or value iteration by using a proxy struct type that follows the range protocol, and have your hash table return one of those structs from methods such as "keysIter" or "valuesIter". But unless I'm mistaken, D2 still doesn't support returning tuples, so you still can't have keys _and_ values at the same time. (Unless you're content with using a Pair or something.)

Returning a std.typecons.Tuple is entirely possible. Andrei

tuple(K,V) foo(K,V)(K k, V v) { ... } ????, I have no idea, pls help Bjoern

Look like this works... However it would be nice if we could place the alias Tuple Pair stuff outside of foo() module tt; import std.stdio; import std.typecons; //alias Tuple!(K, "key", V, "value") Pair; This don't work auto foo(K,V)(K k, V v) { alias Tuple!(K, "key", V, "value") Pair; Pair P; P.key = ++k; P.value = v; return P; } void main() { //Pair KV; auto KV = foo!(int,string) (10,"Hello"); writefln("%8s %s\n", KV.key, KV.value); } This is a really nice feature, guess there are smarter ways to implement tuple returns.. Bjoern
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
BLS wrote:
 Look like this works... However it would be nice if we could place the 
 alias Tuple Pair stuff outside of foo()

I'm glad I waited a bit on that one :o). Nice work.
 module tt;
 import std.stdio;
 import std.typecons;
 
 //alias Tuple!(K, "key", V, "value") Pair; This don't work

It doesn't work because at that time the symbols K and V are not visible. But this little simplification should work: template Pair(K, V) { alias Tuple!(K, "key", V, "value") Pair; } Andrei
Jan 18 2009
parent reply BLS <nanali nospam.wanadoo.fr> writes:
Andrei Alexandrescu schrieb:
 BLS wrote:
 Look like this works... However it would be nice if we could place the 
 alias Tuple Pair stuff outside of foo()

I'm glad I waited a bit on that one :o). Nice work.
 module tt;
 import std.stdio;
 import std.typecons;

 //alias Tuple!(K, "key", V, "value") Pair; This don't work

It doesn't work because at that time the symbols K and V are not visible. But this little simplification should work: template Pair(K, V) { alias Tuple!(K, "key", V, "value") Pair; } Andrei

std.typecons docs. IMO this a not very well known cool D2 feature. Bjoern
Jan 18 2009
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
BLS wrote:
 Andrei Alexandrescu schrieb:
 BLS wrote:
 Look like this works... However it would be nice if we could place
 the alias Tuple Pair stuff outside of foo()

I'm glad I waited a bit on that one :o). Nice work.
 module tt;
 import std.stdio;
 import std.typecons;

 //alias Tuple!(K, "key", V, "value") Pair; This don't work

It doesn't work because at that time the symbols K and V are not visible. But this little simplification should work: template Pair(K, V) { alias Tuple!(K, "key", V, "value") Pair; } Andrei

std.typecons docs. IMO this a not very well known cool D2 feature. Bjoern

auto cheez() { return tuple(42, "burger"); } void main() { auto a,b = cheez(); } http://mine.icanhascheezburger.com/view.aspx?ciid=3163244 -- Daniel
Jan 18 2009
prev sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 Jarrett Billingsley wrote:
 On Sun, Jan 18, 2009 at 1:00 PM, dsimcha <dsimcha yahoo.com> wrote:
 Nice.  Glad to see that this is documented somewhere so I can start playing
with
 it.  One thing, though:  In my dstats library, I have a custom hash table
 implementation that's used very heavily in my information theory module.  (I
have
 my reasons for using a custom hash table instead of the builtin, but they're
 beyond the scope of this post.)  Right now, the hash table uses opApply.  Now



 I realize how horribly slow opApply is, I'd like to port this to ranges.



 I need to be able to iterate over either key, value pairs or just values.  Is
 there any way to make this work with ranges?

You could handle key or value iteration by using a proxy struct type that follows the range protocol, and have your hash table return one of those structs from methods such as "keysIter" or "valuesIter". But unless I'm mistaken, D2 still doesn't support returning tuples, so you still can't have keys _and_ values at the same time. (Unless you're content with using a Pair or something.)

Andrei

So there's no way to do this without requiring any extra boilerplate on the caller's end, i.e. as cleanly (from the caller's perspective) as opApply?
Jan 18 2009
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-01-18 10:21:55 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 It's been there for a while now (since 25 Nov 2008).
 
 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

.next move the left edge of the range right one .retreat move the right edge of the range left one Each time I see this I get annoyed by the dissimilarity of the terms. "advance" and "retreat" would be much better words. Even if "advance" is three more characters, it carries much better the meaning of what is happening; "next" isn't even a verb. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 18 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2009-01-18 10:21:55 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 It's been there for a while now (since 25 Nov 2008).

 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

.next move the left edge of the range right one .retreat move the right edge of the range left one Each time I see this I get annoyed by the dissimilarity of the terms. "advance" and "retreat" would be much better words. Even if "advance" is three more characters, it carries much better the meaning of what is happening; "next" isn't even a verb.

I understand. Next was rather consecrated so we used that one. "Toe" comes from the "head to toe" phrase; "tail" would have been nice but its meaning in all other languages is "everything but the head". At the highest level, any nomenclature cannot please everybody. Andrei
Jan 18 2009
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
== Quote from Michel Fortin (michel.fortin michelf.com)'s article
 On 2009-01-18 10:21:55 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 It's been there for a while now (since 25 Nov 2008).

 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

.retreat move the right edge of the range left one Each time I see this I get annoyed by the dissimilarity of the terms. "advance" and "retreat" would be much better words. Even if "advance" is three more characters, it carries much better the meaning of what is happening; "next" isn't even a verb.

advance/retreat or next/prev. I use the latter in my own code, but perhaps an abbreviation isn't appropriate here. Sean
Jan 19 2009
prev sibling next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Sun, 18 Jan 2009 07:21:55 -0800, Andrei Alexandrescu wrote:

 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement
 
 Scroll down to "Foreach over Structs and Classes with Ranges". The 
 changelog reflects that too:

How do I implement a range that supports more than one pass? From the docs, all ranges seem to be essentially Input ranges currently. That is MyIterable collection; foreach (element; collection) {} // OK, iterates foreach (element; collection) {} // oops, it's empty!
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Sun, 18 Jan 2009 07:21:55 -0800, Andrei Alexandrescu wrote:
 
 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

 Scroll down to "Foreach over Structs and Classes with Ranges". The 
 changelog reflects that too:

How do I implement a range that supports more than one pass? From the docs, all ranges seem to be essentially Input ranges currently. That is MyIterable collection; foreach (element; collection) {} // OK, iterates foreach (element; collection) {} // oops, it's empty!

Note that the range is being copied into a hidden variable, so after the first iteration the collection will still hold its ground. Andrei
Jan 18 2009
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Sun, 18 Jan 2009 15:32:26 -0800, Andrei Alexandrescu wrote:

 Sergey Gromov wrote:
 Sun, 18 Jan 2009 07:21:55 -0800, Andrei Alexandrescu wrote:
 
 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

 Scroll down to "Foreach over Structs and Classes with Ranges". The 
 changelog reflects that too:

How do I implement a range that supports more than one pass? From the docs, all ranges seem to be essentially Input ranges currently. That is MyIterable collection; foreach (element; collection) {} // OK, iterates foreach (element; collection) {} // oops, it's empty!

Note that the range is being copied into a hidden variable, so after the first iteration the collection will still hold its ground.

Unless it's a class you mean?
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Sun, 18 Jan 2009 15:32:26 -0800, Andrei Alexandrescu wrote:
 
 Sergey Gromov wrote:
 Sun, 18 Jan 2009 07:21:55 -0800, Andrei Alexandrescu wrote:

 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

 Scroll down to "Foreach over Structs and Classes with Ranges". The 
 changelog reflects that too:

docs, all ranges seem to be essentially Input ranges currently. That is MyIterable collection; foreach (element; collection) {} // OK, iterates foreach (element; collection) {} // oops, it's empty!

first iteration the collection will still hold its ground.

Unless it's a class you mean?

Yah, ranges are meant to have value semantics. If you have a class container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {} Andrei
Jan 18 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Unless it's a class you mean?

Yah, ranges are meant to have value semantics. If you have a class container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Otherwise it looks like a step backwards. --bb

One point of clarification: opApply isn't going to be deprecated anytime soon, is it? It seems like ranges still have a bunch of rough edges, and although I like the idea in principle, I'm only willing to convert to ranges if I can define iterable objects with the same level of syntactic sugar as opApply gives me. For simple cases this is already true and I have begun converting some stuff. However, for more complicated cases, opApply is still a lot more flexible.
Jan 18 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
dsimcha wrote:
 One point of clarification:  opApply isn't going to be deprecated anytime
soon, is
 it?  It seems like ranges still have a bunch of rough edges, and although I
like
 the idea in principle, I'm only willing to convert to ranges if I can define
 iterable objects with the same level of syntactic sugar as opApply gives me. 
For
 simple cases this is already true and I have begun converting some stuff.
 However, for more complicated cases, opApply is still a lot more flexible.

opApply isn't going away. For one thing, it works very well with recursive data structures.
Jan 18 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Walter Bright (newshound1 digitalmars.com)'s article
 dsimcha wrote:
 One point of clarification:  opApply isn't going to be deprecated anytime
soon, is
 it?  It seems like ranges still have a bunch of rough edges, and although I
like
 the idea in principle, I'm only willing to convert to ranges if I can define
 iterable objects with the same level of syntactic sugar as opApply gives me. 
For
 simple cases this is already true and I have begun converting some stuff.
 However, for more complicated cases, opApply is still a lot more flexible.

recursive data structures.

So besides performance, what advantages does using ranges instead of opApply for iteration over structs/classes offer? According to some testing that I just finished on the hash table implementation I was talking about earlier today, the penalty for using opApply is small enough that, if using ranges requires a bunch of extra bookkeeping overhead that opApply doesn't, then opApply can reasonably be faster.
Jan 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
dsimcha wrote:
 == Quote from Walter Bright (newshound1 digitalmars.com)'s article
 dsimcha wrote:
 One point of clarification:  opApply isn't going to be deprecated anytime
soon, is
 it?  It seems like ranges still have a bunch of rough edges, and although I
like
 the idea in principle, I'm only willing to convert to ranges if I can define
 iterable objects with the same level of syntactic sugar as opApply gives me. 
For
 simple cases this is already true and I have begun converting some stuff.
 However, for more complicated cases, opApply is still a lot more flexible.

recursive data structures.

So besides performance, what advantages does using ranges instead of opApply for iteration over structs/classes offer? According to some testing that I just finished on the hash table implementation I was talking about earlier today, the penalty for using opApply is small enough that, if using ranges requires a bunch of extra bookkeeping overhead that opApply doesn't, then opApply can reasonably be faster.

Speed is a small part of the equation, in fact a perk only. Ranges are composable; you can combine them to e.g. do parallel iteration over two ranges. Ranges really open std.algorithm to all data structures. I find opApply incredibly obtuse and fostering bad design. I wish it goes away. Andrei
Jan 18 2009
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-01-18 22:00:17 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 dsimcha wrote:
 == Quote from Walter Bright (newshound1 digitalmars.com)'s article
 dsimcha wrote:
 One point of clarification:  opApply isn't going to be deprecated 
 anytime soon, is
 it?  It seems like ranges still have a bunch of rough edges, and 
 although I like
 the idea in principle, I'm only willing to convert to ranges if I can define
 iterable objects with the same level of syntactic sugar as opApply 
 gives me.  For
 simple cases this is already true and I have begun converting some stuff.
 However, for more complicated cases, opApply is still a lot more flexible.

recursive data structures.

So besides performance, what advantages does using ranges instead of opApply for iteration over structs/classes offer? According to some testing that I just finished on the hash table implementation I was talking about earlier today, the penalty for using opApply is small enough that, if using ranges requires a bunch of extra bookkeeping overhead that opApply doesn't, then opApply can reasonably be faster.

Speed is a small part of the equation, in fact a perk only. Ranges are composable; you can combine them to e.g. do parallel iteration over two ranges. Ranges really open std.algorithm to all data structures. I find opApply incredibly obtuse and fostering bad design. I wish it goes away. Andrei

But if it goes away, that'd prevent a lot of cool things that could be done with foreach. You could create a template that automatically distributes iterations to various threads with very little code (assuming the loop delegate is pure): foreach (i; paralelize(myArray)) doSomethingComplicated(); All the complexity would lay in the opApply. You can't do this with ranges. Other possible things involves a rudimentary profiler (checking for the elapsed time at each loop iteration), or a progress monitoring template (notifying another thread of the progress of a particular task). foreach (task; progessUpdater(timeProfiler(listOfTasks))) { ... } For basic data manipulation algorithms, ranges are better. But for more fancy stuff, opApply still rules. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 19 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2009-01-18 22:00:17 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 dsimcha wrote:
 == Quote from Walter Bright (newshound1 digitalmars.com)'s article
 dsimcha wrote:
 One point of clarification:  opApply isn't going to be deprecated 
 anytime soon, is
 it?  It seems like ranges still have a bunch of rough edges, and 
 although I like
 the idea in principle, I'm only willing to convert to ranges if I 
 can define
 iterable objects with the same level of syntactic sugar as opApply 
 gives me.  For
 simple cases this is already true and I have begun converting some 
 stuff.
 However, for more complicated cases, opApply is still a lot more 
 flexible.

recursive data structures.

So besides performance, what advantages does using ranges instead of opApply for iteration over structs/classes offer? According to some testing that I just finished on the hash table implementation I was talking about earlier today, the penalty for using opApply is small enough that, if using ranges requires a bunch of extra bookkeeping overhead that opApply doesn't, then opApply can reasonably be faster.

Speed is a small part of the equation, in fact a perk only. Ranges are composable; you can combine them to e.g. do parallel iteration over two ranges. Ranges really open std.algorithm to all data structures. I find opApply incredibly obtuse and fostering bad design. I wish it goes away. Andrei

But if it goes away, that'd prevent a lot of cool things that could be done with foreach. You could create a template that automatically distributes iterations to various threads with very little code (assuming the loop delegate is pure): foreach (i; paralelize(myArray)) doSomethingComplicated(); All the complexity would lay in the opApply. You can't do this with ranges.

Parallelization crossed my mind too, although in the context of finding files in subdirectories recursively. Using foreach for such stuff looks cute, maybe too cute. Let's not forget that there is always the option of calling a higher-order function: distribute(myArray, &doSomethingComplicated);
 Other possible things involves a rudimentary profiler (checking for the 
 elapsed time at each loop iteration), or a progress monitoring template 
 (notifying another thread of the progress of a particular task).
 
     foreach (task; progessUpdater(timeProfiler(listOfTasks)))
     { ... }

You can't compose iteration based on opApply. How would progessUpdater and timeProfiler look like? This example pretty much transforms your argument into mine :o).
 For basic data manipulation algorithms, ranges are better. But for more 
 fancy stuff, opApply still rules.

Depends on how you define "fancy". If "fancy" includes "composable", opApply isn't that. Andrei
Jan 19 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 Depends on how you define "fancy". If "fancy" includes "composable",
 opApply isn't that.
 Andrei

Can you give an example of composable ranges, because I'm not sure exactly what you mean or how it works.
Jan 19 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 Depends on how you define "fancy". If "fancy" includes "composable",
 opApply isn't that.
 Andrei

Can you give an example of composable ranges, because I'm not sure exactly what you mean or how it works.

Given two ranges, iterate both in lockstep. Andrei
Jan 19 2009
prev sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Mon, 19 Jan 2009 06:15:06 -0800, Andrei Alexandrescu wrote:

 Michel Fortin wrote:
 Other possible things involves a rudimentary profiler (checking for the 
 elapsed time at each loop iteration), or a progress monitoring template 
 (notifying another thread of the progress of a particular task).
 
     foreach (task; progessUpdater(timeProfiler(listOfTasks)))
     { ... }

You can't compose iteration based on opApply. How would progessUpdater and timeProfiler look like? This example pretty much transforms your argument into mine :o).

I think "can't" is a bit strong a statement. Let's see: With opApply: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { composed_ = dg; return collection_.opApply(&fancifier); } private: int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } Collection collection_; int delegate(ref ElementType!(Collection)) composed_; } With ranges: struct progressUpdater(Collection) { this(Collection c) { collection_ = c; } typeof(collection_.head) head() { return collection_.head; } void next() { globalOnProgress(); collection_.next(); } bool empty() { return collection_.empty; } private Collection collection_; } Cannot see anything impossible with both.
Jan 19 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Mon, 19 Jan 2009 06:15:06 -0800, Andrei Alexandrescu wrote:
 
 Michel Fortin wrote:
 Other possible things involves a rudimentary profiler (checking for the 
 elapsed time at each loop iteration), or a progress monitoring template 
 (notifying another thread of the progress of a particular task).

     foreach (task; progessUpdater(timeProfiler(listOfTasks)))
     { ... }

and timeProfiler look like? This example pretty much transforms your argument into mine :o).

I think "can't" is a bit strong a statement. Let's see: With opApply: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { composed_ = dg; return collection_.opApply(&fancifier); } private: int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } Collection collection_; int delegate(ref ElementType!(Collection)) composed_; }

I see. Very ingenious! Reversed flow of control all the way. Thanks. Andrei
Jan 22 2009
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-01-19 18:11:15 -0500, Sergey Gromov <snake.scaly gmail.com> said:

 I think "can't" is a bit strong a statement.  Let's see:
 
 With opApply:
 
 class progressUpdater(Collection)
 {
   this(Collection c)
   {
     collection_ = c;
   }
 
   int opApply(int delegate(ref ElementType!(Collection)) dg)
   {
     composed_ = dg;
     return collection_.opApply(&fancifier);
   }
 
   private:
 
   int fancifier(ref ElementType!(Collection) el)
   {
     globalOnProgress();
     return composed_(el);
   }
 
   Collection collection_;
   int delegate(ref ElementType!(Collection)) composed_;
 }

I think it's the same as this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } composed_ = dg; return collection_.opApply(&fancifier); } private: Collection collection_; } Or this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { foreach(ref ElementType!(Collection) el; collection_) { globalOnProgress(); if (dg(el)) return 1; } return 0; } private: Collection collection_; } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 22 2009
parent Sergey Gromov <snake.scaly gmail.com> writes:
Thu, 22 Jan 2009 21:53:02 -0500, Michel Fortin wrote:

 On 2009-01-19 18:11:15 -0500, Sergey Gromov <snake.scaly gmail.com> said:
 
 I think "can't" is a bit strong a statement.  Let's see:
 
 With opApply:
 
 class progressUpdater(Collection)
 {
   this(Collection c)
   {
     collection_ = c;
   }
 
   int opApply(int delegate(ref ElementType!(Collection)) dg)
   {
     composed_ = dg;
     return collection_.opApply(&fancifier);
   }
 
   private:
 
   int fancifier(ref ElementType!(Collection) el)
   {
     globalOnProgress();
     return composed_(el);
   }
 
   Collection collection_;
   int delegate(ref ElementType!(Collection)) composed_;
 }

I think it's the same as this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { int fancifier(ref ElementType!(Collection) el) { globalOnProgress(); return composed_(el); } composed_ = dg; return collection_.opApply(&fancifier); } private: Collection collection_; } Or this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { foreach(ref ElementType!(Collection) el; collection_) { globalOnProgress(); if (dg(el)) return 1; } return 0; } private: Collection collection_; }

Or even this: class progressUpdater(Collection) { this(Collection c) { collection_ = c; } int opApply(int delegate(ref ElementType!(Collection)) dg) { return collection_.opApply( (ref ElementType!(Collection) el) { globalOnProgress(); return dg(el); } ); } private Collection collection_; }
Jan 24 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
Andrei Alexandrescu wrote:

 Speed is a small part of the equation, in fact a perk only. Ranges are
 composable; you can combine them to e.g. do parallel iteration over two
 ranges. Ranges really open std.algorithm to all data structures. I find
 opApply incredibly obtuse and fostering bad design. I wish it goes away.

I'd really hate to see opApply go away. I'm glad Walter says it's sticking around ;) opApply is really nice in how *simple* it is to write. I think it's possible to use druntime's fibers to convert an opApply implementation into a range implementation. It'd be an interesting challenge to write a templated struct that handles all of this. Once that is done, maybe someone could discuss using Fibers to implement opApply in D2. I suspect the code inside an opApply would only change a little bit and it'd allow iteration over multiple "ranges" at the same time.
Jan 19 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jason House wrote:
 Andrei Alexandrescu wrote:
 
 Speed is a small part of the equation, in fact a perk only. Ranges
 are composable; you can combine them to e.g. do parallel iteration
 over two ranges. Ranges really open std.algorithm to all data
 structures. I find opApply incredibly obtuse and fostering bad
 design. I wish it goes away.

I'd really hate to see opApply go away. I'm glad Walter says it's sticking around ;)

I know. Its popularity is part of what makes it dangerous. It's to good programming what fast food is to food :o).
 opApply is really nice in how *simple* it is to write.  I think it's
 possible to use druntime's fibers to convert an opApply
 implementation into a range implementation.  It'd be an interesting
 challenge to write a templated struct that handles all of this.  Once
 that is done, maybe someone could discuss using Fibers to implement
 opApply in D2.  I suspect the code inside an opApply would only
 change a little bit and it'd allow iteration over multiple "ranges"
 at the same time.

But that's making the mythical bear dance. Iterating over multiple ranges is only one example. How do you feed one range to another range with opApply? At the end of the day, if what you want is to iterate, you need to define what the state of iteration is, how to make a step, and how to get to the current element being iterated. That is a good design, not opApply and fibers! Andrei
Jan 19 2009
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Andrei Alexandrescu wrote:

 Jason House wrote:
 Andrei Alexandrescu wrote:
 
 Speed is a small part of the equation, in fact a perk only. Ranges
 are composable; you can combine them to e.g. do parallel iteration
 over two ranges. Ranges really open std.algorithm to all data
 structures. I find opApply incredibly obtuse and fostering bad
 design. I wish it goes away.

I'd really hate to see opApply go away. I'm glad Walter says it's sticking around ;)

I know. Its popularity is part of what makes it dangerous. It's to good programming what fast food is to food :o).
 opApply is really nice in how *simple* it is to write.  I think it's
 possible to use druntime's fibers to convert an opApply
 implementation into a range implementation.  It'd be an interesting
 challenge to write a templated struct that handles all of this.  Once
 that is done, maybe someone could discuss using Fibers to implement
 opApply in D2.  I suspect the code inside an opApply would only
 change a little bit and it'd allow iteration over multiple "ranges"
 at the same time.

But that's making the mythical bear dance. Iterating over multiple ranges is only one example. How do you feed one range to another range with opApply? At the end of the day, if what you want is to iterate, you need to define what the state of iteration is, how to make a step, and how to get to the current element being iterated. That is a good design, not opApply and fibers! Andrei

Are you saying that nobody should ever use coroutines? A coroutine version of opApply keeps the state of iteration as part of the natural flow of making steps and getting the current element being iterated. Let's look at various implementation examples: current opApply style: int opApply(int delegate( ref T ) dg){ int unknown; foreach(i; 0..length){ unknown = dg(arr[i]); if (unknown != 0) return unknown; } return 0; } With coroutine: void iterateOverArray(T)(T[] arr){ foreach (i; 0..arr.length) yield(arr[i]); } ... or maybe something more complex like the following is required? void iterateOverArray(T)(T[] arr){ foreach (i; 0..arr.length){ yield!("empty") = false; yield!("next") = arr[i]; } yield!("empty") = true; } A range-based struct: struct arrayIterator(T){ int _i; T[] _arr; this(T[] arr){ arr = _arr; } T next(){ return arr[i++]; } bool empty{ return i<_arr.length; } } Here are the line counts for the above implementations: current opApply style: 9 coroutine with implied empty: 4 coroutine with explicit empty: 7 range-based: 13 Which one would D users want to write? Personally, I want the coroutine with implied empty. I could see having to explicitly state empty or at least specify when it changes. If the above examples don't convince you that D should consider allowing alternate implementations to basic range structs, then I'll stop trying to convince you.
Jan 19 2009
next sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Jason House (jason.james.house gmail.com)'s article
 Andrei Alexandrescu wrote:
 Jason House wrote:
 Andrei Alexandrescu wrote:

 Speed is a small part of the equation, in fact a perk only. Ranges
 are composable; you can combine them to e.g. do parallel iteration
 over two ranges. Ranges really open std.algorithm to all data
 structures. I find opApply incredibly obtuse and fostering bad
 design. I wish it goes away.

I'd really hate to see opApply go away. I'm glad Walter says it's sticking around ;)

I know. Its popularity is part of what makes it dangerous. It's to good programming what fast food is to food :o).
 opApply is really nice in how *simple* it is to write.  I think it's
 possible to use druntime's fibers to convert an opApply
 implementation into a range implementation.  It'd be an interesting
 challenge to write a templated struct that handles all of this.  Once
 that is done, maybe someone could discuss using Fibers to implement
 opApply in D2.  I suspect the code inside an opApply would only
 change a little bit and it'd allow iteration over multiple "ranges"
 at the same time.

But that's making the mythical bear dance. Iterating over multiple ranges is only one example. How do you feed one range to another range with opApply? At the end of the day, if what you want is to iterate, you need to define what the state of iteration is, how to make a step, and how to get to the current element being iterated. That is a good design, not opApply and fibers! Andrei


and getting the current element being iterated. Let's look at various implementation examples:
 current opApply style:
 int opApply(int delegate( ref T ) dg){
   int unknown;
   foreach(i; 0..length){
     unknown = dg(arr[i]);
     if (unknown != 0)
       return unknown;
   }
   return 0;
 }
 With coroutine:
 void iterateOverArray(T)(T[] arr){
   foreach (i; 0..arr.length)
     yield(arr[i]);
 }
 ... or maybe something more complex like the following is required?
 void iterateOverArray(T)(T[] arr){
   foreach (i; 0..arr.length){
     yield!("empty") = false;
     yield!("next") = arr[i];
   }
   yield!("empty") = true;
 }
 A range-based struct:
 struct arrayIterator(T){
   int _i;
   T[] _arr;
   this(T[] arr){
     arr = _arr;
   }
   T next(){
     return arr[i++];
   }
   bool empty{
     return i<_arr.length;
   }
 }
 Here are the line counts for the above implementations:
 current opApply style: 9
 coroutine with implied empty: 4
 coroutine with explicit empty: 7
 range-based: 13
 Which one would D users want to write?  Personally, I want the coroutine with

when it changes. If the above examples don't convince you that D should consider allowing alternate implementations to basic range structs, then I'll stop trying to convince you. Yeah, but we also want decent performance and even compared to opApply, coroutines/fibers are slow as molasses in January at the North Pole during the last Ice Age.
Jan 19 2009
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Jason House wrote:
 void iterateOverArray(T)(T[] arr){
   foreach (i; 0..arr.length)
     yield(arr[i]);
 }

Coroutines are the slowest option, but the easiest to write. It takes 32 instructions or so to switch to or from a coroutine on x86. I'm not sure how that translates in terms of memory usage, though. A delegate is reasonably fast. A range struct's methods can be inlined (though opApply could be, too, in some cases). However, any collection library using polymorphism will have to use polymorphic iterators. This means you probably won't get any benefit in terms of speed from using ranges -- quite the opposite. But there are benefits.
Jan 19 2009
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 I know. Its popularity is part of what makes it dangerous. It's to good 
 programming what fast food is to food :o).

I think that's a false analogy: fast food kills you slowly, while experience shows me that in many programs a significant (large) percentage of lines of code don't need to be a the top performance. So a good thing to do in such parts is to use the most handy, easy to remember, safer (as in anti-bug-prone), and short syntax/semantics you have. In the other small percentage of the code where performance is all important and/or you need full flexibility, you can tolerate something less easy to remember and harder to understand syntax/semantics (that you may also need to look into the docs if you don't know how to write). This may lead to have two different syntaxes/solutions in the D2 language. Duplication is generally bad. But if the first syntax/solution is simple enough (like, simpler than the current opApply, that I have to look up each time despite using it often), then the summed complexity of both solutions isn't much bigger than the complexity of the second solution alone :-) So I think having a syntax simpler than the opApply plus a full ranged syntax can be acceptable. The simpler syntax may look for example more or less like this (as you can see there is very little noise and very little to remember): struct DoubleRange(int n) { int opIter() { for (int i; i < n; i++) yield(i * 2); yield(1000); } } The following handy lazy iterable may even become syntactic sugar for the struct I have just shown, as you can see even less noise, for a really common programming pattern: yield int doubleRange(int n) { for (int i; i < n; i++) yield(i * 2); yield(1000); } Currently with my libs you have to write the following, that is less nice (and it's not compiler-supported, so it's probably slower than necessary) (idea adapted and modified from Witold Baryluk): http://www.fantascienza.net/leonardo/so/dlibs/generators.html struct DoubleRange(int n) { void generator() { for (int i; i < n; i++) yield(i * 2); yield(1000); } mixin Generator!(int); } Bye, bearophile
Jan 19 2009
parent reply Sean Kelly <sean invisibleduck.org> writes:
== Quote from bearophile (bearophileHUGS lycos.com)'s article
 Andrei Alexandrescu:
 I know. Its popularity is part of what makes it dangerous. It's to good
 programming what fast food is to food :o).


 So a good thing to do in such parts is to use the most handy, easy to
remember, safer (as in anti-bug-prone), and short

flexibility, you can tolerate something less easy to remember and harder to understand syntax/semantics (that you may also need to look into the docs if you don't know how to write). This assumes that the easy approach is slow and the fast approach is complex. I'd hope that we could find something that's both easy and fast :-) Sean
Jan 19 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Sean Kelly:
 This assumes that the easy approach is slow and the fast approach is
 complex.  I'd hope that we could find something that's both easy and
 fast :-)

I agree that certain times it's possible to have something that is both simple, safe, short and fast (but if that yield can be used for parallel iterations, then it may become slowish). But here there's another thing to consider: you may also want something quite flexible (see the complexity of Range). This is very difficult to do, that's why I have suggested two syntaxes, one simpler than opApply that requires you no brain to use it, plus the Range syntax developed so far (that may need small improvements but I doubt I'll ever be able to improve a lot, because Alex is good). Bye, bearophile
Jan 19 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
dsimcha wrote:
 == Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Unless it's a class you mean?

exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Otherwise it looks like a step backwards. --bb

One point of clarification: opApply isn't going to be deprecated anytime soon, is it?

I hope to be able to deprecate it.
 It seems like ranges still have a bunch of rough edges, and although I like
 the idea in principle, I'm only willing to convert to ranges if I can define
 iterable objects with the same level of syntactic sugar as opApply gives me. 
For
 simple cases this is already true and I have begun converting some stuff.
 However, for more complicated cases, opApply is still a lot more flexible.

Ranges do have a number of rough edges, and IMHO the best way to address those is to improve ranges, not keep opApply. Andrei
Jan 18 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Unless it's a class you mean?

exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Add .opRange so that's not necessary? Or allow opApply to return a range? Otherwise it looks like a step backwards.

Why is it a step backwards? A given container may define a number of ranges. Arrays are deceivingly simple because they have one obvious way of iteration, but even for them you'd have to write: int[] a; foreach (element; a.retro) { ... } Andrei
Jan 18 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Andrei Alexandrescu" wrote
 Bill Baxter wrote:
 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Unless it's a class you mean?

container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Add .opRange so that's not necessary? Or allow opApply to return a range? Otherwise it looks like a step backwards.

Why is it a step backwards? A given container may define a number of ranges. Arrays are deceivingly simple because they have one obvious way of iteration, but even for them you'd have to write: int[] a; foreach (element; a.retro) { ... }

I have to side with the others on this. foreach(element; collection) is so damned intuitive ("for each element in a collection"), it should at least try to call a default range function first, before trying to use collection as a range. I'm for having opRange, and ditching opApply. I don't really see the need for opApply (and I used a lot of forwarding opApply calls in dcollections, so I'll probably have to rewrite that now!). You could also write cool things like (for instance in a string-indexed collection): foreach(element; collection["a".."m"]) instead of foreach(element; collection["a".."m"].all) While we're on the subject of ditching, can we get rid of foreach_reverse? How hard is it for a range to just have a reverse property: foreach(element; myrange.reverse) Which simply reverses the order of traversal? That also would moot the toe/last/tail/etc. debate ;) -Steve
Jan 19 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 "Andrei Alexandrescu" wrote
 Bill Baxter wrote:
 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Unless it's a class you mean?

container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

range? Otherwise it looks like a step backwards.

ranges. Arrays are deceivingly simple because they have one obvious way of iteration, but even for them you'd have to write: int[] a; foreach (element; a.retro) { ... }

I have to side with the others on this. foreach(element; collection) is so damned intuitive ("for each element in a collection"), it should at least try to call a default range function first, before trying to use collection as a range. I'm for having opRange, and ditching opApply. I don't really see the need for opApply (and I used a lot of forwarding opApply calls in dcollections, so I'll probably have to rewrite that now!). You could also write cool things like (for instance in a string-indexed collection): foreach(element; collection["a".."m"]) instead of foreach(element; collection["a".."m"].all)

Ok, I understand.
 While we're on the subject of ditching, can we get rid of foreach_reverse? 
 How hard is it for a range to just have a reverse property:
 
 foreach(element; myrange.reverse)
 
 Which simply reverses the order of traversal?  That also would moot the 
 toe/last/tail/etc. debate ;)

I wish that debate went away. But eliminating toe and retreat would require requiring .reverse as a primitive for *all* ranges, which is wasteful and repetitive. Instead, a better design is to have ranges (those that can) offer toe and retreat primitives such that a generic function retro offers backward iteration for any range. In addition, certain algorithms (such as the one that reverses a range in place) need to manipulate the same range from two ends. Implementing them using .reverse and a second range would be more difficult. Andrei
Jan 19 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Andrei Alexandrescu" wrote
 Steven Schveighoffer wrote:
 While we're on the subject of ditching, can we get rid of 
 foreach_reverse? How hard is it for a range to just have a reverse 
 property:

 foreach(element; myrange.reverse)

 Which simply reverses the order of traversal?  That also would moot the 
 toe/last/tail/etc. debate ;)

I wish that debate went away. But eliminating toe and retreat would require requiring .reverse as a primitive for *all* ranges, which is wasteful and repetitive. Instead, a better design is to have ranges (those that can) offer toe and retreat primitives such that a generic function retro offers backward iteration for any range. In addition, certain algorithms (such as the one that reverses a range in place) need to manipulate the same range from two ends. Implementing them using .reverse and a second range would be more difficult.

I didn't say you couldn't provide toe and retreat in Phobos' ranges (for the reverse-a-range function). Most likely such an algorithm is not using foreach and foreach_reverse, but using the functions directly. My point was, foreach_reverse is an eyesore and a hack, and there really is no need for it. And what a perfect time to get rid of it, since we are already changing how foreach works ;) I realize that this wouldn't really kill the toe debate for Phobos, but at least it would be a library decision, and not part of the compiler. -Steve
Jan 19 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 "Andrei Alexandrescu" wrote
 Steven Schveighoffer wrote:
 While we're on the subject of ditching, can we get rid of 
 foreach_reverse? How hard is it for a range to just have a reverse 
 property:

 foreach(element; myrange.reverse)

 Which simply reverses the order of traversal?  That also would moot the 
 toe/last/tail/etc. debate ;)

require requiring .reverse as a primitive for *all* ranges, which is wasteful and repetitive. Instead, a better design is to have ranges (those that can) offer toe and retreat primitives such that a generic function retro offers backward iteration for any range. In addition, certain algorithms (such as the one that reverses a range in place) need to manipulate the same range from two ends. Implementing them using .reverse and a second range would be more difficult.

I didn't say you couldn't provide toe and retreat in Phobos' ranges (for the reverse-a-range function). Most likely such an algorithm is not using foreach and foreach_reverse, but using the functions directly. My point was, foreach_reverse is an eyesore and a hack, and there really is no need for it. And what a perfect time to get rid of it, since we are already changing how foreach works ;) I realize that this wouldn't really kill the toe debate for Phobos, but at least it would be a library decision, and not part of the compiler.

Yah, that makes sense. I vote for foreach_reverse to go away, too. Andrei
Jan 19 2009
parent aarti_pl <aarti interia.pl> writes:
Andrei Alexandrescu pisze:
 Steven Schveighoffer wrote:
 "Andrei Alexandrescu" wrote
 Steven Schveighoffer wrote:
 While we're on the subject of ditching, can we get rid of 
 foreach_reverse? How hard is it for a range to just have a reverse 
 property:

 foreach(element; myrange.reverse)

 Which simply reverses the order of traversal?  That also would moot 
 the toe/last/tail/etc. debate ;)

require requiring .reverse as a primitive for *all* ranges, which is wasteful and repetitive. Instead, a better design is to have ranges (those that can) offer toe and retreat primitives such that a generic function retro offers backward iteration for any range. In addition, certain algorithms (such as the one that reverses a range in place) need to manipulate the same range from two ends. Implementing them using .reverse and a second range would be more difficult.

I didn't say you couldn't provide toe and retreat in Phobos' ranges (for the reverse-a-range function). Most likely such an algorithm is not using foreach and foreach_reverse, but using the functions directly. My point was, foreach_reverse is an eyesore and a hack, and there really is no need for it. And what a perfect time to get rid of it, since we are already changing how foreach works ;) I realize that this wouldn't really kill the toe debate for Phobos, but at least it would be a library decision, and not part of the compiler.

Yah, that makes sense. I vote for foreach_reverse to go away, too. Andrei

vote++ BR Marcin Kuszczak (aarti_pl)
Jan 19 2009
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Mon, 19 Jan 2009 09:47:14 +0900, Bill Baxter wrote:

 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Unless it's a class you mean?

Yah, ranges are meant to have value semantics. If you have a class container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Add .opRange so that's not necessary? Or allow opApply to return a range? Otherwise it looks like a step backwards.

I already proposed that foreach should first try collection.opSlice() and work with that if successful, otherwise resort to iterating over the collection itself. You would probably implement opSlice anyway so this solution comes at little cost.
Jan 19 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Jan 19, 2009 at 3:57 PM, Yigal Chripun <yigal100 gmail.com> wrote:
 Christopher Wright wrote:
 Walter Bright wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

There doesn't really need to be anything wrong with them. What's wrong with head/toe?

It sounds stupid.

it sounds stupid and is uninformative. for example, auto cars = new BinaryTree!(Car)(); auto a = cars.toe; auto b = cars.last; now, reading the above, what's the toe of cars? that's just silly. Does this make sense to English speakers? most likly. but for say, chinese? I don't know. instead of inveting terms than imply something based on some phrase that not all non-native English speakers will recognize, it is far better to just use the proper English term for the last item - "last". KISS solution.

Hmm, what *is* the problem with first/last? I seem to remember there was something against it but I think that was when the semantics were slightly different and .last was going to mean one past the end. Current docs make it looks like it .toe does mean the last element itself, not the one just past. --bb
Jan 18 2009
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Andrei Alexandrescu" wrote
 It's been there for a while now (since 25 Nov 2008).

 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

Strange that I never noticed that. I remember when 2.022 came out, I did not see it there, but I guess I could have overlooked it. It definitely was not there when 2.021 came out (I remember many people asking for docs on it, including myself). One question, it mentions that you must define all 5 properties. In the case where you are only going to use foreach (and not foreach_reverse) on a struct, is it still required that you implement toe and retreat? If not, then that probably should be mentioned in the docs. -Steve
Jan 19 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 "Andrei Alexandrescu" wrote
 It's been there for a while now (since 25 Nov 2008).

 http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement

Strange that I never noticed that. I remember when 2.022 came out, I did not see it there, but I guess I could have overlooked it. It definitely was not there when 2.021 came out (I remember many people asking for docs on it, including myself). One question, it mentions that you must define all 5 properties. In the case where you are only going to use foreach (and not foreach_reverse) on a struct, is it still required that you implement toe and retreat? If not, then that probably should be mentioned in the docs.

Yah, only the minimum is required. Walter should change the docs :o). Andrei
Jan 19 2009
prev sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Jan 20, 2009 at 12:50 PM, Lars Ivar Igesund
<larsivar igesund.net> wrote:
 There doesn't really need to be anything wrong with them. What's wrong
 with head/toe?

It sounds stupid.

Wholeheartedly agree.

Agreed too, what's wrong with first/last? They're completely obvious and have no connotations.
Jan 20 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Jan 19, 2009 at 2:00 PM, Christopher Wright <dhasenan gmail.com> wrote:
 Walter Bright wrote:
 Yigal Chripun wrote:
 Walter Bright wrote:
 Lars Ivar Igesund wrote:
 toe() ?! tail() good, rear() not so good, toe() sucks.

tail() is no good because it has a well-established meaning in programming of being everything but the first element of a list. I just didn't like rear(), as it is not normally thought of as the opposite of head().

What was the reason for the use of body parts in the first place? What's wrong with: a) begin, end b) start, finish c) initial, final d) first, last etc...

There doesn't really need to be anything wrong with them. What's wrong with head/toe?

It sounds stupid.

Here's from the previous discussion: http://www.digitalmars.com/d/archives/digitalmars/D/announce/Re_Revised_RFC_on_range_design_for_D2_13303.html I think toe sounds fine. I'm just glad 'tip' was abandoned in favor of 'head'. --bb
Jan 18 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Jan 19, 2009 at 11:54 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Unless it's a class you mean?

Yah, ranges are meant to have value semantics. If you have a class container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Add .opRange so that's not necessary? Or allow opApply to return a range? Otherwise it looks like a step backwards.

Why is it a step backwards? A given container may define a number of ranges. Arrays are deceivingly simple because they have one obvious way of iteration, but even for them you'd have to write: int[] a; foreach (element; a.retro) { ... }

It's a step backwards because with opApply we can define a default forward iteration scheme that works like so: foreach(element; a) { ... } Now you're saying that'll still work for structs, but for classes folks will have to use some other convention like .all. I also presume built-ins like arrays still won't require you to use "a.all" to do a basic forward foreach iteration. If it will, I suppose I could live with that. As long as the rules are consistent and don't make class-based containters into second class citizens requiring different syntax. But there's really no technical reason why we can't have the simpler syntax work. As a class writer I would also find myself very tempted to provide an opApply just to enable that simpler syntax for users, assuming you stick to your guns and require something like .all to use ranges. --bb
Jan 18 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, Jan 19, 2009 at 9:16 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 Unless it's a class you mean?

Yah, ranges are meant to have value semantics. If you have a class container exposing ranges, define the range separately from the container itself: MyIterable collection; foreach (element; collection.all) {} foreach (element; collection.all) {}

Add .opRange so that's not necessary? Or allow opApply to return a range? Otherwise it looks like a step backwards. --bb
Jan 18 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 18 Jan 2009 18:21:55 +0300, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 Lars Ivar Igesund wrote:
 Andrei Alexandrescu wrote:

 For example, I'm not sure how code in std.algorithm could help
 containers or streams in Tango (as it should), or how to reconcile
 std.algorithm with std.core.array.

known and enforced by the compiler, then I expect Tango to support those at some point, and std.algorithm would presumably just work. However, if it is based on some interface, ad hoc (these methods must be present) or properly via an interface Range { }, I would expect Tango developers to be involved in the process of defining those interfaces (if Tango is meant to use/know about them). Since I have seen neither, it is somewhat difficult to make a well informed comment on the subject.

It's been there for a while now (since 25 Nov 2008). http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement Scroll down to "Foreach over Structs and Classes with Ranges". The changelog reflects that too: http://www.digitalmars.com/d/2.0/changelog.html Version 2.021 mentions "Added range support to foreach statement." Andrei

There is a typo in docs (http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement): Foreach Range Properties: .rear return the rightmost element of the range ... for (auto __r = range; !__r.empty; __r.retreat) { auto e = __r.tail; //<- tail or rear? ... }
Jan 18 2009
prev sibling next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sun, Jan 18, 2009 at 12:17 PM, Stewart Gordon <smjg_1998 yahoo.com> wrote:
 IUnknown wrote:
 <snip>
 Really, D's community needs to grow up and create ONE standard library for
 D2. D2 would be a nice time to break backwards compatibility in the
 libraries.

<snip> D already has ONE standard library. It's called Phobos. http://www.digitalmars.com/d/archives/digitalmars/D/Two_standard_libraries_58530.html

Yes Stewart, we know you love semantics. You know what is being discussed here.
Jan 18 2009
prev sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sun, Jan 18, 2009 at 1:00 PM, dsimcha <dsimcha yahoo.com> wrote:
 Nice.  Glad to see that this is documented somewhere so I can start playing
with
 it.  One thing, though:  In my dstats library, I have a custom hash table
 implementation that's used very heavily in my information theory module.  (I
have
 my reasons for using a custom hash table instead of the builtin, but they're
 beyond the scope of this post.)  Right now, the hash table uses opApply.  Now
that
 I realize how horribly slow opApply is, I'd like to port this to ranges. 
However,
 I need to be able to iterate over either key, value pairs or just values.  Is
 there any way to make this work with ranges?

You could handle key or value iteration by using a proxy struct type that follows the range protocol, and have your hash table return one of those structs from methods such as "keysIter" or "valuesIter". But unless I'm mistaken, D2 still doesn't support returning tuples, so you still can't have keys _and_ values at the same time. (Unless you're content with using a Pair or something.)
Jan 18 2009
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Piotrek" wrote
 Hello!

 It's just an idea. After reading about issues on disallowing DWT to stay 
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some 
 question appeared in my mind. For propaganda sake isn't it better to not 
 make such a big division between phobos and tango in the module naming? 
 Logically:

 phobos -> std
 tango  -> stdex (not tango -> tango)

Let's not forget the licensing issues. Tango is incompatible with some developers license wise, as you must include attribution for Tango in any derivative works (i.e. compiled binaries). Phobos has a less restrictive opt-in policy. I think Walter intends to keep it that way, at least for DMD. Note that other compilers are free to use Tango or their own standard library, the D spec is pretty free from library references. With regards to Tango for D2. It is going to happen. It may not be tomorrow, but it will probably be done this year. To answer some questions throughout this discussion, it will look similar to Tango/D1, but will utilize many of the features of D2, as well as obey the requirements. For example, it's not simply going to cast away const to keep the implementation closer to D1. So it will look different than Tango/D1 and most likely, will not be one code base. Which means, people will have to maintain both, which is no small feat. But it can (and will) be done. I like D2 too much to not do it :) The Tango D2 branch currently in SVN compiles and runs on Linux DMD 2.019. We have basic functionality for many of the examples, but not all unit tests pass. However, it should be usable to test simple code. So far, we have ported completely tango.core and tango.util.log. We have yet to incorporate druntime, as I didn't want to tackle issues that might be in druntime as well as porting issues. I think I will try to upgrade to 2.023, as it seems druntime/compiler interaction is getting a lot more stable, and then continue porting. I don't see Tango and Phobos becoming more like one or the other, but as others have said, there are definite sections of code that can be used from both without interference. I/O is not one of them, and I don't see that changing. But due to the open source nature, you can port or re-implement features of one library into the other, so while you may be choosing between two different styles, you shouldn't have to choose one or the other for functionality. I also don't think this is a bad thing. One of two things will happen. Either one library totally dominates the other, and eventually everyone starts using the more popular one (the Beta/VHS route), or both libraries flourish, and due to the common runtime, can be used concurrently in projects (the KDE/GNOME route). Either way, I don't see the current rift between Tango/Phobos being a major detriment to D. It will be short-lived IMO. -Steve
Jan 19 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 "Piotrek" wrote
 Hello!

 It's just an idea. After reading about issues on disallowing DWT to stay 
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some 
 question appeared in my mind. For propaganda sake isn't it better to not 
 make such a big division between phobos and tango in the module naming? 
 Logically:

 phobos -> std
 tango  -> stdex (not tango -> tango)

Let's not forget the licensing issues. Tango is incompatible with some developers license wise, as you must include attribution for Tango in any derivative works (i.e. compiled binaries). Phobos has a less restrictive opt-in policy. I think Walter intends to keep it that way, at least for DMD. Note that other compilers are free to use Tango or their own standard library, the D spec is pretty free from library references.

Yah. This also creates some asymmetry, as e.g. Walter avoids looking at Tango whereas Phobos is out in the clear. Given that I work on Phobos too and know next to nothing about licensing issues, I myself defaulted to not looking at Tango (I did look cursory a couple of years ago, before being involved with Phobos.)
 I also don't think this is a bad thing.  One of two things will happen. 
 Either one library totally dominates the other, and eventually everyone 
 starts using the more popular one (the Beta/VHS route), or both libraries 
 flourish, and due to the common runtime, can be used concurrently in 
 projects (the KDE/GNOME route).  Either way, I don't see the current rift 
 between Tango/Phobos being a major detriment to D.  It will be short-lived 
 IMO.

Nicely put. I believe the same. Andrei
Jan 19 2009
prev sibling next sibling parent reply John Reimer <terminal.node gmail.com> writes:
Hello Steven,

 "Piotrek" wrote
 
 Hello!
 
 It's just an idea. After reading about issues on disallowing DWT to
 stay in standardization area (Anomaly on Wiki4D GuiLibraries page)
 some question appeared in my mind. For propaganda sake isn't it
 better to not make such a big division between phobos and tango in
 the module naming? Logically:
 
 phobos -> std
 tango  -> stdex (not tango -> tango)

some developers license wise, as you must include attribution for Tango in any derivative works (i.e. compiled binaries). Phobos has a less restrictive opt-in policy. I think Walter intends to keep it that way, at least for DMD. Note that other compilers are free to use Tango or their own standard library, the D spec is pretty free from library references. With regards to Tango for D2. It is going to happen. It may not be tomorrow, but it will probably be done this year. To answer some questions throughout this discussion, it will look similar to Tango/D1, but will utilize many of the features of D2, as well as obey the requirements. For example, it's not simply going to cast away const to keep the implementation closer to D1. So it will look different than Tango/D1 and most likely, will not be one code base. Which means, people will have to maintain both, which is no small feat. But it can (and will) be done. I like D2 too much to not do it :) The Tango D2 branch currently in SVN compiles and runs on Linux DMD 2.019. We have basic functionality for many of the examples, but not all unit tests pass. However, it should be usable to test simple code. So far, we have ported completely tango.core and tango.util.log. We have yet to incorporate druntime, as I didn't want to tackle issues that might be in druntime as well as porting issues. I think I will try to upgrade to 2.023, as it seems druntime/compiler interaction is getting a lot more stable, and then continue porting. I don't see Tango and Phobos becoming more like one or the other, but as others have said, there are definite sections of code that can be used from both without interference. I/O is not one of them, and I don't see that changing. But due to the open source nature, you can port or re-implement features of one library into the other, so while you may be choosing between two different styles, you shouldn't have to choose one or the other for functionality. I also don't think this is a bad thing. One of two things will happen. Either one library totally dominates the other, and eventually everyone starts using the more popular one (the Beta/VHS route), or both libraries flourish, and due to the common runtime, can be used concurrently in projects (the KDE/GNOME route). Either way, I don't see the current rift between Tango/Phobos being a major detriment to D. It will be short-lived IMO. -Steve

A fair analysis, but I think incomplete. Once again, the problem has more to do with the perception of new users and outsiders. I believe those of is in here, those of us who have frustrated and agonized over D over the last few years are going to be in a much better position of accepting the situation as it develops: we've grown with it, so our sympathies are well rooted -- we may very much enjoy having the option of using either of or both of two great libraries. I can easily agree that your analysis has some sense to it because of that. But, as I said before, the hardest part remains in finding a method to promote it as a "good thing" to everyone else who has no real emotional attatchment to the language, those who see learning a language as a synonymous with learning one "standard" library (because that seems to be the general history of programming languages). Maybe I'm wrong about this one (I hope I am wrong, and you are right), but I don't think it's wise to completely discredit the possibility of a problem in having two popular libraries at the core of D 2.0. If the libraries do go the Beta/VHS route... well that's just a mercy for D. Still trying to think positively, of course. :) -JJR
Jan 19 2009
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"John Reimer" wrote
 Hello Steven,
 I don't see Tango and Phobos becoming more like one or the other, but
 as others have said, there are definite sections of code that can be
 used from both without interference.  I/O is not one of them, and I
 don't see that changing.  But due to the open source nature, you can
 port or re-implement features of one library into the other, so while
 you may be choosing between two different styles, you shouldn't have
 to choose one or the other for functionality.

 I also don't think this is a bad thing.  One of two things will
 happen. Either one library totally dominates the other, and eventually
 everyone starts using the more popular one (the Beta/VHS route), or
 both libraries flourish, and due to the common runtime, can be used
 concurrently in projects (the KDE/GNOME route).  Either way, I don't
 see the current rift between Tango/Phobos being a major detriment to
 D.  It will be short-lived IMO.

 -Steve

A fair analysis, but I think incomplete. Once again, the problem has more to do with the perception of new users and outsiders. I believe those of is in here, those of us who have frustrated and agonized over D over the last few years are going to be in a much better position of accepting the situation as it develops: we've grown with it, so our sympathies are well rooted -- we may very much enjoy having the option of using either of or both of two great libraries. I can easily agree that your analysis has some sense to it because of that. But, as I said before, the hardest part remains in finding a method to promote it as a "good thing" to everyone else who has no real emotional attatchment to the language, those who see learning a language as a synonymous with learning one "standard" library (because that seems to be the general history of programming languages). Maybe I'm wrong about this one (I hope I am wrong, and you are right), but I don't think it's wise to completely discredit the possibility of a problem in having two popular libraries at the core of D 2.0. If the libraries do go the Beta/VHS route... well that's just a mercy for D. Still trying to think positively, of course. :)

Keep thinking positively :) There will always be naysayers, people who think D sucks, no matter how many of their objections you fix, they will find something else to gripe about. There's not much you can do about those people. The ones I am interested in convincing are those who turn to D to fill a need, such as "C++ sucks, I wonder if there's something better", or "I like language X, but I need something that compiles to native code", or whatever the reason. These are the people who are willing to invest the time necessary to learn the core language. If those people, after learning D and about the standard library situation still turn away, then there would be something wrong. But I don't think we are in that situation. Most of the people in this newsgroup are in that category and have stuck it out and want to make D work. Every once in a while, a fierce Phobos vs. Tango debate arises, and it sucks so much time out of people that they are sure it is the main reason people don't like D. When you start using D, you pick a library, and most likely stick to it. There are plenty of resources that work for both the libraries, that I don't think it's that terrible. There are so many other holes in the D regime that I think the fact that you have a choice between two standard libraries is the least of our concern. How about a good integrated IDE/Compiler/Debugger? A visual GUI editor? A better doc system? And most of all an EASY way to install such tools. Following 18 different web pages on unpacking zip files and installing source control systems does not foster new use. I'd say the issue brought up about dsource considered harmful is a huge legitimate deterrent. It takes a long time to scour through all the abandoned projects to find out if the functionality you're looking for is implemented and maintained or not. I know at least one newbie that I helped learn D on IRC from knowing only Python that decided to implement 2 projects that had already been done but were buried in dsource somewhere. Me, I don't care about the library debate, I've already picked Tango as my standard library. I don't care if it's not the standard library. I don't care about the brand name, as long as it does what I need it to do. I've moved on to more important tasks. If other people like Phobos, fine, it doesn't bother me at all. I don't need to have a battle about it. I just want to write code and have it work. And Tango helps me do that better, so that was my choice. I feel like this debate about which standard library wears the official crown is useless noise. No offense to the OP, but this is a never-ending loop that just seems to take up too much of people's time. On that note, I'll bow out of the discussion. I need to get some work done :) -Steve
Jan 20 2009
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with some 
 developers license wise, as you must include attribution for Tango in any 
 derivative works (i.e. compiled binaries). 

Are you sure? Where is that written down? I can't find that anywhere in the Tango license.
Jan 19 2009
next sibling parent reply Don <nospam nospam.com> writes:
Bill Baxter wrote:
 On Tue, Jan 20, 2009 at 3:00 PM, Don <nospam nospam.com> wrote:
 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with some
 developers license wise, as you must include attribution for Tango in any
 derivative works (i.e. compiled binaries).

Tango license.

Probably this: 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. I think it's just saying you can't remove stuff from the source code that says who wrote it. But it's got a thick legal accent that's a little difficult to understand.

Yes, it explicitly states that it's source code-only requirement. Perhaps the page should include an approximate explanation, to remove confusion
Jan 20 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Don" wrote
 Bill Baxter wrote:
 On Tue, Jan 20, 2009 at 3:00 PM, Don <nospam nospam.com> wrote:
 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with some
 developers license wise, as you must include attribution for Tango in 
 any
 derivative works (i.e. compiled binaries).

the Tango license.

Probably this: 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. I think it's just saying you can't remove stuff from the source code that says who wrote it. But it's got a thick legal accent that's a little difficult to understand.

Yes, it explicitly states that it's source code-only requirement. Perhaps the page should include an approximate explanation, to remove confusion

I'm not a lawyer, but I think that the artistic license requires source redistribution (I agree the license is difficult to comprehend), whereas the BSD style license requires attribution with binaries. So either way, you must provide attribution. Some companies may frown upon that, especially when we're talking about a standard library. I'm not saying it should change, but that is one other reason that I think Walter has not considered adopting Tango as *the* standard library. -Steve
Jan 20 2009
parent reply Sean Kelly <sean invisibleduck.org> writes:
Steven Schveighoffer wrote:
 "Don" wrote
 Bill Baxter wrote:
 On Tue, Jan 20, 2009 at 3:00 PM, Don <nospam nospam.com> wrote:
 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with some
 developers license wise, as you must include attribution for Tango in 
 any
 derivative works (i.e. compiled binaries).

the Tango license.

6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. I think it's just saying you can't remove stuff from the source code that says who wrote it. But it's got a thick legal accent that's a little difficult to understand.

Perhaps the page should include an approximate explanation, to remove confusion

I'm not a lawyer, but I think that the artistic license requires source redistribution (I agree the license is difficult to comprehend), whereas the BSD style license requires attribution with binaries. So either way, you must provide attribution. Some companies may frown upon that, especially when we're talking about a standard library.

I've read the BSD license very carefully and I think it only requires attribution with binary distributions of the library, not apps written with the library. If I'm wrong I'd love to know, because druntime is currently BSD licensed (something I've been meaning to reconsider). Sean
Jan 20 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Sean Kelly" wrote
 Steven Schveighoffer wrote:
 "Don" wrote
 Bill Baxter wrote:
 On Tue, Jan 20, 2009 at 3:00 PM, Don <nospam nospam.com> wrote:
 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with 
 some
 developers license wise, as you must include attribution for Tango in 
 any
 derivative works (i.e. compiled binaries).

in the Tango license.

6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. I think it's just saying you can't remove stuff from the source code that says who wrote it. But it's got a thick legal accent that's a little difficult to understand.

Perhaps the page should include an approximate explanation, to remove confusion

I'm not a lawyer, but I think that the artistic license requires source redistribution (I agree the license is difficult to comprehend), whereas the BSD style license requires attribution with binaries. So either way, you must provide attribution. Some companies may frown upon that, especially when we're talking about a standard library.

I've read the BSD license very carefully and I think it only requires attribution with binary distributions of the library, not apps written with the library. If I'm wrong I'd love to know, because druntime is currently BSD licensed (something I've been meaning to reconsider).

As D currently is statically linked, any application is a binary distribution of the library. However, even with shared libraries, I believe it is still considered a binary distribution if your application uses the library (as your code needs the dynamic library to run). This is why the LGPL exists. I don't know if there is an equivalent BSD version. Again, not a lawyer :) -steve
Jan 20 2009
parent Sean Kelly <sean invisibleduck.org> writes:
== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s article
 "Sean Kelly" wrote
 Steven Schveighoffer wrote:
 "Don" wrote
 Bill Baxter wrote:
 On Tue, Jan 20, 2009 at 3:00 PM, Don <nospam nospam.com> wrote:
 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with
 some
 developers license wise, as you must include attribution for Tango in
 any
 derivative works (i.e. compiled binaries).

in the Tango license.

6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. I think it's just saying you can't remove stuff from the source code that says who wrote it. But it's got a thick legal accent that's a little difficult to understand.

Perhaps the page should include an approximate explanation, to remove confusion

I'm not a lawyer, but I think that the artistic license requires source redistribution (I agree the license is difficult to comprehend), whereas the BSD style license requires attribution with binaries. So either way, you must provide attribution. Some companies may frown upon that, especially when we're talking about a standard library.

I've read the BSD license very carefully and I think it only requires attribution with binary distributions of the library, not apps written with the library. If I'm wrong I'd love to know, because druntime is currently BSD licensed (something I've been meaning to reconsider).

distribution of the library. However, even with shared libraries, I believe it is still considered a binary distribution if your application uses the library (as your code needs the dynamic library to run). This is why the LGPL exists. I don't know if there is an equivalent BSD version. Again, not a lawyer :)

You don't need to be :-). People's perception of a license is as important as what it means in fact. None of this is an issue for the DMD distribution because I've granted Walter permission to distribute druntime under the Phobos license, but it's something I want to take care of regardless. I may just make the darn thing public domain to save myself the hassle of finding a license everyone is happy with. Sean
Jan 20 2009
prev sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Don wrote:

 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with some
 developers license wise, as you must include attribution for Tango in any
 derivative works (i.e. compiled binaries).

Are you sure? Where is that written down? I can't find that anywhere in the Tango license.

Steve is wrong in this matter. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jan 20, 2009 at 3:00 PM, Don <nospam nospam.com> wrote:
 Steven Schveighoffer wrote:
 Let's not forget the licensing issues.  Tango is incompatible with some
 developers license wise, as you must include attribution for Tango in any
 derivative works (i.e. compiled binaries).

Are you sure? Where is that written down? I can't find that anywhere in the Tango license.

Probably this: 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. I think it's just saying you can't remove stuff from the source code that says who wrote it. But it's got a thick legal accent that's a little difficult to understand. --bb
Jan 19 2009
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Steven Schveighoffer wrote:

 "Piotrek" wrote
 Hello!

 It's just an idea. After reading about issues on disallowing DWT to stay
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some
 question appeared in my mind. For propaganda sake isn't it better to not
 make such a big division between phobos and tango in the module naming?
 Logically:

 phobos -> std
 tango  -> stdex (not tango -> tango)

Let's not forget the licensing issues. Tango is incompatible with some developers license wise, as you must include attribution for Tango in any derivative works (i.e. compiled binaries). Phobos has a less restrictive opt-in policy. I think Walter intends to keep it that way, at least for DMD. Note that other compilers are free to use Tango or their own standard library, the D spec is pretty free from library references.

Sorry, where do you find this attribution clause? The only two restrictions put on Tango source is: * You cannot relicense the source - can't possibly be a problem to anyone * You cannot take the source and say you wrote it (unless you actually did) - not a problem for a single person unless he'd like to be dishonest. Saying that Tango is license-encumbered in any way is a gross misunderstanding. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Lars Ivar Igesund" wrote
 Steven Schveighoffer wrote:

 "Piotrek" wrote
 Hello!

 It's just an idea. After reading about issues on disallowing DWT to stay
 in standardization area (Anomaly on Wiki4D GuiLibraries page) some
 question appeared in my mind. For propaganda sake isn't it better to not
 make such a big division between phobos and tango in the module naming?
 Logically:

 phobos -> std
 tango  -> stdex (not tango -> tango)

Let's not forget the licensing issues. Tango is incompatible with some developers license wise, as you must include attribution for Tango in any derivative works (i.e. compiled binaries). Phobos has a less restrictive opt-in policy. I think Walter intends to keep it that way, at least for DMD. Note that other compilers are free to use Tango or their own standard library, the D spec is pretty free from library references.

Sorry, where do you find this attribution clause? The only two restrictions put on Tango source is: * You cannot relicense the source - can't possibly be a problem to anyone * You cannot take the source and say you wrote it (unless you actually did) - not a problem for a single person unless he'd like to be dishonest. Saying that Tango is license-encumbered in any way is a gross misunderstanding.

Sorry if I'm spreading misinformation, but I understood this clause in the BSD license to mean that any binary distribution must contain attribution: "Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution." The mentioned copyright notice being "Copyright (c) 2004-2008, Tango contributors All rights reserved." As D is statically compiled, any application which uses Tango is effectively a binary distribution of it. At least that's what I interpret it as. How do youi interpret the above line? Conversely, the Phobos license's clause is: "The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required." Which I interpret to mean that you cannot misrepresent that you wrote Phobos, but it is appreciated if you give Digital Mars credit for it in your application. I can't really understand whether it is required to distribute the source code of a derivative work under the Academic Free License, so I don't really understand that. Maybe that is the license you can use for distributing binaries without attribution? I'd love to be wrong, because that would mean Tango is a lot more open than I originally thought. -Steve
Jan 20 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Steven Schveighoffer wrote:

 "Lars Ivar Igesund" wrote
 Steven Schveighoffer wrote:

 "Piotrek" wrote
 Hello!

 It's just an idea. After reading about issues on disallowing DWT to
 stay in standardization area (Anomaly on Wiki4D GuiLibraries page) some
 question appeared in my mind. For propaganda sake isn't it better to
 not make such a big division between phobos and tango in the module
 naming? Logically:

 phobos -> std
 tango  -> stdex (not tango -> tango)

Let's not forget the licensing issues. Tango is incompatible with some developers license wise, as you must include attribution for Tango in any derivative works (i.e. compiled binaries). Phobos has a less restrictive opt-in policy. I think Walter intends to keep it that way, at least for DMD. Note that other compilers are free to use Tango or their own standard library, the D spec is pretty free from library references.

Sorry, where do you find this attribution clause? The only two restrictions put on Tango source is: * You cannot relicense the source - can't possibly be a problem to anyone * You cannot take the source and say you wrote it (unless you actually did) - not a problem for a single person unless he'd like to be dishonest. Saying that Tango is license-encumbered in any way is a gross misunderstanding.

Sorry if I'm spreading misinformation, but I understood this clause in the BSD license to mean that any binary distribution must contain attribution: "Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution." The mentioned copyright notice being "Copyright (c) 2004-2008, Tango contributors All rights reserved." As D is statically compiled, any application which uses Tango is effectively a binary distribution of it. At least that's what I interpret it as. How do youi interpret the above line?

You are correct about the BSD license, but where you are wrong is the fact that you as a user choose which of the two available licenses you wish to agree with. BSD with the binary clause is necessary for compatibility with (L)GPL, whereas APL, stands for completely free binary use, but the source restriction that you cannot remove the name of the authors (although you can freely augment the list if that is a correct picture). So it is not both licenses, but the one that suits you.
 Conversely, the Phobos license's clause is:
 
 "The origin of this software must not be misrepresented; you must not
 claim that you wrote the original software. If you use this software in a
 product, an acknowledgment in the product documentation would be
 appreciated but is not required."

In practice this should be the same as the APL, only that the APL is written in legalese for better or worse.
 I can't really understand whether it is required to distribute the source
 code of a derivative work under the Academic Free License, so I don't
 really
 understand that. 

It is not required, AFAIK only LGPL and GPL of the common licenses require that.
 Maybe that is the license you can use for distributing
 binaries without attribution?

Yes. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Lars Ivar Igesund" wrote
 Steven Schveighoffer wrote:
 I can't really understand whether it is required to distribute the source
 code of a derivative work under the Academic Free License, so I don't
 really
 understand that.

It is not required, AFAIK only LGPL and GPL of the common licenses require that.

That is good to hear. Can a statement like this be made on the license page? Or in the license itself? I found it very difficult to discern what was meant, at some point it states that you must provide a copy of the source code, but I wasn't sure how that applies. Sorry for the confusion... -Steve
Jan 20 2009
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Steven Schveighoffer wrote:

 "Lars Ivar Igesund" wrote
 Steven Schveighoffer wrote:
 I can't really understand whether it is required to distribute the
 source code of a derivative work under the Academic Free License, so I
 don't really
 understand that.

It is not required, AFAIK only LGPL and GPL of the common licenses require that.

That is good to hear. Can a statement like this be made on the license page? Or in the license itself? I found it very difficult to discern what was meant, at some point it states that you must provide a copy of the source code, but I wasn't sure how that applies.

I thought the license page (.../wiki/License) was pretty clear ... even if the licenses themselves aren't. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jan 20 2009
next sibling parent =?UTF-8?B?QWxleGFuZGVyIFDDoW5law==?= writes:
Bill Baxter wrote:
 On Wed, Jan 21, 2009 at 6:29 AM, Lars Ivar Igesund <larsivar igesund.net>
wrote:
 
 I thought the license page (.../wiki/License) was pretty clear  ... even if
the licenses themselves aren't.

Actually this was something I meant to bring up. I couldn't actually find that page when I was looking for it. I ended up doing a search on the Tango site for "license". I think there should be a link to the license page somewhere on the front page. Right now the word "license" doesn't appear anywhere on that page.

There’s a link on the front page “All Documentation” where you find the link to the “License Agreement” page, but having the latter on the front page wouldn’t be a bad idea either, I suppose.
Jan 20 2009
prev sibling next sibling parent Yigal Chripun <yigal100 gmail.com> writes:
Bill Baxter wrote:
 On Wed, Jan 21, 2009 at 6:29 AM, Lars Ivar Igesund<larsivar igesund.net> 
wrote:

 I thought the license page (.../wiki/License) was pretty clear  ... even if
the licenses themselves aren't.

Actually this was something I meant to bring up. I couldn't actually find that page when I was looking for it. I ended up doing a search on the Tango site for "license". I think there should be a link to the license page somewhere on the front page. Right now the word "license" doesn't appear anywhere on that page. --bb

The link is on the "about" page.
Jan 20 2009
prev sibling parent =?UTF-8?B?QWxleGFuZGVyIFDDoW5law==?= writes:
Lars Ivar Igesund wrote:
 Steven Schveighoffer wrote:
 
 "Lars Ivar Igesund" wrote
 Steven Schveighoffer wrote:
 I can't really understand whether it is required to distribute the
 source code of a derivative work under the Academic Free License, so I
 don't really
 understand that.

require that.

page? Or in the license itself? I found it very difficult to discern what was meant, at some point it states that you must provide a copy of the source code, but I wasn't sure how that applies.

I thought the license page (.../wiki/License) was pretty clear ... even if the licenses themselves aren't.

It’s actually /wiki/LibraryLicense. I’ve created /wiki/License including and displaying the contents of LibraryLicense.
Jan 20 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Jan 21, 2009 at 6:29 AM, Lars Ivar Igesund <larsivar igesund.net> wrote:

 I thought the license page (.../wiki/License) was pretty clear  ... even if
the licenses themselves aren't.

Actually this was something I meant to bring up. I couldn't actually find that page when I was looking for it. I ended up doing a search on the Tango site for "license". I think there should be a link to the license page somewhere on the front page. Right now the word "license" doesn't appear anywhere on that page. --bb
Jan 20 2009