
Hello, I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own? I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail. Thanks, Andrei

Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
We use boost.optional extensively in Boost.Spirit. IIRC, we collapse such things. Usually they occur in generic code. I see no real need for optional<optional<T>>. If there's a use for it, I too would like to hear it. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Wed, Sep 2, 2009 at 8:52 PM, Joel de Guzman<joel@boost-consulting.com> wrote:
Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
We use boost.optional extensively in Boost.Spirit. IIRC, we collapse such things. Usually they occur in generic code. I see no real need for optional<optional<T>>. If there's a use for it, I too would like to hear it.
Slightly off-topic, but I consider D to be a *fascinating* language, kind of like how C++ should have been. It would actually be *much* easier to create Spirit in D then it would have been in C++, and you could have used real PEG syntax instead of C++/D'ifying it. I never really played around with D due to the lack of a Visual Assist quality IDE for it though, but I have read through the language spec (much better read then C++'s) multiple times just for the heck of it, and it is absolutely fascinating! Kind of bugs me that it has two 'generic' libraries that do the same things in different ways though, and you cannot mix code that uses both...

OvermindDL1 wrote:
Slightly off-topic, but I consider D to be a *fascinating* language, kind of like how C++ should have been. It would actually be *much* easier to create Spirit in D then it would have been in C++, and you could have used real PEG syntax instead of C++/D'ifying it.
I've been looking at D a bit myself recently, and i just saw this on the D mailing list: http://lists.puremagic.com/pipermail/digitalmars-d-announce/2009-August/0139... -- View this message in context: http://www.nabble.com/optional%3Coptional%3CT%3E%3E-tp25268985p25272737.html Sent from the Boost - Dev mailing list archive at Nabble.com.

On Thu, Sep 3, 2009 at 3:45 AM, Richard Webb<richard.webb@boldonjames.com> wrote:
OvermindDL1 wrote:
Slightly off-topic, but I consider D to be a *fascinating* language, kind of like how C++ should have been. It would actually be *much* easier to create Spirit in D then it would have been in C++, and you could have used real PEG syntax instead of C++/D'ifying it.
I've been looking at D a bit myself recently, and i just saw this on the D mailing list: http://lists.puremagic.com/pipermail/digitalmars-d-announce/2009-August/0139...
<still off-topic> Heh, interesting, but they are going about it the completely wrong way. First Spirit 1's design is quite a bit more convoluted then Spirit2's. Second, thanks to mixin's and the fact that templates can operate on strings in D (not just integers and types like in C++), they could implement a *real* PEG syntax that gets completely lowered to pure D code at compile-time. Yes, D is that powerful. Heck, if C++ added D style templates and mixin support and compile-time functions (which I guess is kind of getting added to C++1x), I would be happier then you could believe. :) For an example, I even saw a pure compile-time regex parser that you use like: static_regex!("gh.+a") r; regex_info info = r(someString); In D a template is !() unlike in C++ where it is <>. I personally like <> better since I am used to it, but !() is certainly easier to parse and is unambiguous... But yes, that regex is completely lowered to pure D code at compile time, ala Boost.Xpressive's static regex parser. D really does mix in a lot of LISP's power into a C++ syntax (not all of LISP's power, but it gets *REALLY* close).

In D a template is !() unlike in C++ where it is <>. I personally like <> better since I am used to it, but !() is certainly easier to parse and is unambiguous... But yes, that regex is completely lowered to pure D code at compile time, ala Boost.Xpressive's static regex parser.
D really does mix in a lot of LISP's power into a C++ syntax (not all of LISP's power, but it gets *REALLY* close) Same here, I'm really enticed to jump into the D bandwagon. Alas lack of
OvermindDL1 wrote: proper std and industrial support makes it awkward for me to use :( even more off topic: Andrei, anyway random dev. can particiapte to D's development ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

On Thu, Sep 3, 2009 at 5:14 AM, joel<joel.falcou@lri.fr> wrote:
OvermindDL1 wrote:
In D a template is !() unlike in C++ where it is <>. I personally like <> better since I am used to it, but !() is certainly easier to parse and is unambiguous... But yes, that regex is completely lowered to pure D code at compile time, ala Boost.Xpressive's static regex parser.
D really does mix in a lot of LISP's power into a C++ syntax (not all of LISP's power, but it gets *REALLY* close)
Same here, I'm really enticed to jump into the D bandwagon. Alas lack of proper std and industrial support makes it awkward for me to use :(
even more off topic: Andrei, anyway random dev. can particiapte to D's development ?
D has it own list, and D version 2.0 has been in development for like 3 years now, it basically took anything that was considered wrong in D1.0 and fixed it, it is not backwards compatible, yet another reason that helps its stability, but is a detriment to it actually being used...

I'd avoid special rules; optional<T> should be optional<T> regardless of what T actually is - and some people have presented actual use cases where optional< optional<T> > is being used that would be broken by a reduction to optional<T>.

joel wrote:
In D a template is !() unlike in C++ where it is <>. I personally like <> better since I am used to it, but !() is certainly easier to parse and is unambiguous... But yes, that regex is completely lowered to pure D code at compile time, ala Boost.Xpressive's static regex parser.
D really does mix in a lot of LISP's power into a C++ syntax (not all of LISP's power, but it gets *REALLY* close) Same here, I'm really enticed to jump into the D bandwagon. Alas lack of
OvermindDL1 wrote: proper std and industrial support makes it awkward for me to use :(
even more off topic: Andrei, anyway random dev. can particiapte to D's development ?
(I'll very briefly answer two points to keep off-topicness to a minimum: (1) I agree that Spirit should be redesigned for D instead of merely ported because D's ability to manipulate strings statically and generate code from strings opens additional opportunities. (2) Random devices cannot participate because they tend to generate uncompilable code. But people can, and a good point to start is the newsgroup digitalmars.d off NNTP server news.digitalmars.com, no registration required.) Thanks everyone who responded. My understanding is that the best way to go about Optional<Optional<T>> is to leave it be and offer a metafunction that folds it if needed. Thanks! Andrei

On Thu, Sep 3, 2009 at 12:59 PM, OvermindDL1<overminddl1@gmail.com> wrote:
On Thu, Sep 3, 2009 at 3:45 AM, Richard Webb<richard.webb@boldonjames.com> wrote:
OvermindDL1 wrote:
Slightly off-topic, but I consider D to be a *fascinating* language, kind of like how C++ should have been. It would actually be *much* easier to create Spirit in D then it would have been in C++, and you could have used real PEG syntax instead of C++/D'ifying it.
I've been looking at D a bit myself recently, and i just saw this on the D mailing list: http://lists.puremagic.com/pipermail/digitalmars-d-announce/2009-August/0139...
<still off-topic>
Heh, interesting, but they are going about it the completely wrong way. First Spirit 1's design is quite a bit more convoluted then Spirit2's. Second, thanks to mixin's and the fact that templates can operate on strings in D (not just integers and types like in C++), they could implement a *real* PEG syntax that gets completely lowered to pure D code at compile-time.
Yes, D is that powerful. Heck, if C++ added D style templates and mixin support and compile-time functions (which I guess is kind of getting added to C++1x), I would be happier then you could believe. :)
For an example, I even saw a pure compile-time regex parser that you use like: static_regex!("gh.+a") r; regex_info info = r(someString);
In D a template is !() unlike in C++ where it is <>. I personally like <> better since I am used to it, but !() is certainly easier to parse and is unambiguous... But yes, that regex is completely lowered to pure D code at compile time, ala Boost.Xpressive's static regex parser.
D really does mix in a lot of LISP's power into a C++ syntax (not all of LISP's power, but it gets *REALLY* close). _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
(further continuing the off-topic trail here) For what it's worth, I've written a proof-of-concept compile-time recursive descent string parser in pure C++: http://arcticinteractive.com/2009/08/15/cpp-compile-time-string-parser-proto... It even comes with a static regex string to Xpressive transformation grammar (through a layer of indirection) :) although it's currently limited to MPL strings, so the syntax isn't as pretty as it could be with C++1x user-defined literals. Just shows that it is possible to do even with "vanilla" C++. Best regards, Tor Brede Vekterli

Joel de Guzman wrote:
Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
We use boost.optional extensively in Boost.Spirit. IIRC, we collapse such things. Usually they occur in generic code. I see no real need for optional<optional<T>>. If there's a use for it, I too would like to hear it.
I use double optionals. Indeed, this appears in a generic code, but it's intended. The point is that I use the outer optional to in-place construct objects, and it sometimes happens that the objects themselves are optionals. Making them not optional would not be correct from the application logic point of view.

Andrey Semashev wrote:
Joel de Guzman wrote:
Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
We use boost.optional extensively in Boost.Spirit. IIRC, we collapse such things. Usually they occur in generic code. I see no real need for optional<optional<T>>. If there's a use for it, I too would like to hear it.
I use double optionals. Indeed, this appears in a generic code, but it's intended.
The point is that I use the outer optional to in-place construct objects, and it sometimes happens that the objects themselves are optionals. Making them not optional would not be correct from the application logic point of view.
Use case, please? Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

Joel de Guzman wrote:
Andrey Semashev wrote:
Joel de Guzman wrote:
Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
We use boost.optional extensively in Boost.Spirit. IIRC, we collapse such things. Usually they occur in generic code. I see no real need for optional<optional<T>>. If there's a use for it, I too would like to hear it.
I use double optionals. Indeed, this appears in a generic code, but it's intended.
The point is that I use the outer optional to in-place construct objects, and it sometimes happens that the objects themselves are optionals. Making them not optional would not be correct from the application logic point of view.
Use case, please?
Ah, I see. Disregard that. I typed too quickly. That is a valid use-case indeed. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Wed, Sep 2, 2009 at 8:43 PM, Andrei Alexandrescu<andrei@metalanguage.com> wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
Personally I would find it interesting as it can hold extended data, but perhaps it would be nice to fold someway so it takes less data, perhaps one bit per sub-optional used up to the overall max of a char or int or something (would anyone really have 8 optionals embedded?)

OvermindDL1 wrote:
On Wed, Sep 2, 2009 at 8:43 PM, Andrei Alexandrescu<andrei@metalanguage.com> wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
Personally I would find it interesting as it can hold extended data, but perhaps it would be nice to fold someway so it takes less data, perhaps one bit per sub-optional used up to the overall max of a char or int or something (would anyone really have 8 optionals embedded?)
I think, if folding should be supported then it should be done through an external metafunction, something like: typedef typename fold_optionals< T, 7 >::type single_optional; I think, the default behavior of optional should stay as is.

Andrey Semashev wrote:
OvermindDL1 wrote:
On Wed, Sep 2, 2009 at 8:43 PM, Andrei Alexandrescu<andrei@metalanguage.com> wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
Personally I would find it interesting as it can hold extended data, but perhaps it would be nice to fold someway so it takes less data, perhaps one bit per sub-optional used up to the overall max of a char or int or something (would anyone really have 8 optionals embedded?)
I think, if folding should be supported then it should be done through an external metafunction, something like:
typedef typename fold_optionals< T, 7 >::type single_optional;
I think, the default behavior of optional should stay as is.
I agree. It is easy enough to detect and collapse in an application specific way. Your recipe is similar to what we do. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
Why make optional<optional<T> > an exception to the normal case ? Even if you imagined no practical use for it, that's no reason to create a one-off situation.

Hi Andrei,
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I guess it depends on the context where the recursive optionals would appear. Clearly, you can only fold while the initialization state is the same. That is, if the outer optional<> is initialized but the inner is not, then you can't fold it. OTOH, for a run of consistently initialized optionals, folding could make sense. But then again it still depends on the context: if the very *structure* of the recursion matters, the folding would be wrong. So, I would allow optionals to recurse AND provide an explicit function/method to "reduce" a given recursive optional as far as possible (i.e. up to the point the initialization state changes) HTH -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

I'm new to boost::optional<>. I quickly looked through the online docs to see what this class does, and this was my first impression: boost::optional< char > c; if ( c ) { // should not enter this block } c = 'a'; if ( c ) { // should enter this block }
From what I was able to make out in 10-minutes, the class has a built-in boolean for the 'initialized' state so that it can be used in 'if()' statements. Also, the object it represents is not allocated until it is assigned ( if I'm not mistaken. )
I'm curious, what other bag of tricks does it come with? Regards, -Sid Sacek

On 03.09.2009, at 04:43, Andrei Alexandrescu wrote:
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I think optional<optional<T>> should not be folded into optional<T>. One use-case occurs with databases. Consider "SELECT myint FROM mytable WHERE mywhatever='foo'". When returning the result of such a query, the C++ function that executed it could return an empty outer optional if the database returned no row (WHERE-clause didn't match anything), an empty inner optional when myint is SQL's NULL and the integer value of myint in the then non-empty inner optional<int> otherwise. Regards, Daniel

On 3 Sep 2009, at 03:43, Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
Only a related note, I use a version of optional which takes the "m_initalized", effectively the boolean that tells you if a value is present, as a template parameter. This is because for many types, it is possible to know there is some value in the object itself which cannot take certain values, so can be overloaded. As an example, given a vector<T> implemented as: struct vector<T> { T* begin; T* end; size_t length }; Then I know that (on my system) begin will never take (void*)(1), (it might be NULL), so I can reuse that to implement optional<T> without any extra space usage. The main problem with this, at least in C++, this is basically impossible to implement generically and legally, as you are effectively poking into an objects memory without knowing what it is, so I haven't tried to carefully formalise it. Chris

Christopher Jefferson wrote:
On 3 Sep 2009, at 03:43, Andrei Alexandrescu wrote:
Hello,
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
I thought I'd ask here because by now there's a significant body of experience with optional<T>. I perused the online documentation and the forum and couldn't find information about that specific detail.
Only a related note, I use a version of optional which takes the "m_initalized", effectively the boolean that tells you if a value is present, as a template parameter.
This is because for many types, it is possible to know there is some value in the object itself which cannot take certain values, so can be overloaded.
As an example, given a vector<T> implemented as:
struct vector<T> { T* begin; T* end; size_t length };
Then I know that (on my system) begin will never take (void*)(1), (it might be NULL), so I can reuse that to implement optional<T> without any extra space usage.
The main problem with this, at least in C++, this is basically impossible to implement generically and legally, as you are effectively poking into an objects memory without knowing what it is, so I haven't tried to carefully formalise it.
Chris
Yah, good point. The solution I had in mind for that was to also define a two-parameter Optional: Optional<T, T nullValue>. Then if you want to use it with e.g. getchar(), you'd use Optional<int, EOF>. Unfortunately, in C++ this is not as general as it could because T is limited to a few types (D does not have this particular restriction). Something I think could work nicely for C++ would be to parameterize on an address, e.g. Optional<T, const T* nullValuePtr>. Continuing on the getchar example, this could work: const int EOF_global = EOF; typedef Optional<int, &EOF_global> GetcharResult; In your case, you'd have to define a global vector object with the pointers forged appropriately. Andrei

G'day. Andrei Alexandrescu <andrei <at> metalanguage.com> writes:
I'm defining an "optional" type for D's standard library modeled similarly to Boost.optional. An interesting question came up - should optional<optional<T>> fold itself into optional<T>, or is "double optional" an interesting concept of its own?
Automatically folding optional<optional<T>> doesn't make any more sense than automatically folding vector<vector<T>>. The reason is very simple: It's reasonable for templated code to use optional<T> (where T is a template argument) for its own internal purposes. This code should not misbehave just because a client wants that template argument to be optional<U>. Don't break parametricity without an extremely good reason. Andrew Bromage
participants (14)
-
Andrei Alexandrescu
-
Andrew Bromage
-
Andrey Semashev
-
Christopher Jefferson
-
Daniel Frey
-
Edward Diener
-
Fernando Cacciola
-
joel
-
Joel de Guzman
-
Joseph Gauterin
-
OvermindDL1
-
Richard Webb
-
Sid Sacek
-
Tor Brede Vekterli