proto::tag naming convention

What is the rationale for not having proto::tags match the corresponding mpl metafunctions? For instance mpl has plus and proto has add (but unary_plus). Since people will often mix the two, it would be nice to have the same name. (I basically have to look them up everytime I use one of them) If the intention was to make them different so that they can be mixed without namespace qualification I think they're not different enough. Given divide and divides, which is proto's and which is mpl's? Clearly one gets used to these things, but maybe it is something to consider before finalizing proto for inclusion in boost. regards Maurizio

Maurizio Vitale wrote:
What is the rationale for not having proto::tags match the corresponding mpl metafunctions?
For instance mpl has plus and proto has add (but unary_plus).
Oh my. You're right, that's awful. I'll fix these. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 04/27/2007 01:17 PM, Eric Niebler wrote:
Maurizio Vitale wrote:
What is the rationale for not having proto::tags match the corresponding mpl metafunctions?
For instance mpl has plus and proto has add (but unary_plus).
Oh my. You're right, that's awful. I'll fix these.
Well, as long as you're aiming for consistency, why not do the following renames: proto::_ -> proto::true_ proto::not_<_> -> proto::false_ ?

Eric Niebler <eric@boost-consulting.com> writes:
No, proto::_ is a placeholder. And proto::not_<> can logically negate any grammar, not just proto::_.
FWIW I kind of like proto::_. It gives me warm memories of ML and Haskell patterns in the land of...brrr...I digress. But I'd appreciate if you could elaborate on why you see it as a placeholder. Technically I guess it is: it certainly takes space in the parse tree, but I tend to think about placeholders as things that mark a spot that I can then reference from somewhere else (and from here stems my confusion on transformations from another thread. This and the fact that mpl lambda placeholders are mentioned in the documentation). Now I see proto::_ more like a wildcard pattern that matches anything but doesn't have additional meaning (or features for the user). Is there anything I'm missing about proto::_ ?

Maurizio Vitale wrote:
Eric Niebler <eric@boost-consulting.com> writes:
No, proto::_ is a placeholder. And proto::not_<> can logically negate any grammar, not just proto::_.
FWIW I kind of like proto::_. It gives me warm memories of ML and Haskell patterns in the land of...brrr...I digress.
But I'd appreciate if you could elaborate on why you see it as a placeholder.
Technically I guess it is: it certainly takes space in the parse tree, but I tend to think about placeholders as things that mark a spot that I can then reference from somewhere else (and from here stems my confusion on transformations from another thread. This and the fact that mpl lambda placeholders are mentioned in the documentation).
I suppose I hadn't thought very hard about what the difference between the term "placeholder" and "wildcard" might be.
Now I see proto::_ more like a wildcard pattern that matches anything but doesn't have additional meaning (or features for the user).
OK.
Is there anything I'm missing about proto::_ ?
No, I think you got it. Proto::_ is a wildcard pattern that matches anything. In the sense that it is never /substituted/ with anything, it is not a placeholder. I misspoke. I could rename proto::_ to proto::anything, and that would be more evocative of its meaning, but I still like proto::_ better. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 27/04/07, Eric Niebler <eric@boost-consulting.com> wrote:
No, I think you got it. Proto::_ is a wildcard pattern that matches anything. In the sense that it is never /substituted/ with anything, it is not a placeholder. I misspoke.
I could rename proto::_ to proto::anything, and that would be more evocative of its meaning, but I still like proto::_ better.
-- Eric Niebler
I think proto::_ is fine as well - there *is* precedent for _ - as Maurizio said, all the best functional languages (Haskell, ML, Erlang) use _ as a wildcard in pattern matching. Stick with it. Stuart Dootson

On 04/27/2007 03:25 PM, Eric Niebler wrote:
Larry Evans wrote:
why not do the following renames:
proto::_ -> proto::true_
proto::not_<_> -> proto::false_
?
No, proto::_ is a placeholder. And proto::not_<> can logically negate any grammar, not just proto::_.
Actaully, the following is what I had in mind: namespace boost { namespace proto { struct true_ : _ {}; struct false_ : not_<true_> {}; }}//exit boost::proto namespace Why? Because I think (I haven't tested it) the same laws for mpl::bool_ and it's associated operations: mpl::not_ mpl::and_ mpl::or_ would apply to proto's true_, false_, not_,....

Larry Evans wrote:
On 04/27/2007 03:25 PM, Eric Niebler wrote:
Larry Evans wrote:
why not do the following renames:
proto::_ -> proto::true_
proto::not_<_> -> proto::false_
?
No, proto::_ is a placeholder. And proto::not_<> can logically negate any grammar, not just proto::_.
Actaully, the following is what I had in mind:
namespace boost { namespace proto { struct true_ : _ {}; struct false_ : not_<true_> {};
}}//exit boost::proto namespace
Why? Because I think (I haven't tested it) the same laws for mpl::bool_ and it's associated operations:
mpl::not_ mpl::and_ mpl::or_
would apply to proto's true_, false_, not_,....
I guess I don't see how these types would be used. In what contexts would using proto::true_ make more sense than using proto::_ ? -- Eric Niebler Boost Consulting www.boost-consulting.com

On 04/29/2007 12:26 PM, Eric Niebler wrote: [snip]
I guess I don't see how these types would be used. In what contexts would using proto::true_ make more sense than using proto::_ ?
Just as someone seeing: mpl::or_<mpl::true_,X> for any X, would expect the same result as: mpl::true_ so someone seeing: matches<Y,proto::or_<proto::true_,X> > for any X and Y, would expect the same result as: matches<Y,proto::true_ > IOW, the name proto::true_ is more consistent with mpl::true_, which is what the OP was suggesting w.r.t. proto::unary_plus and mpl::plus. OTOH, as already mentioned in one of Maurizio's posts, proto::_ is best because it's more consistent with other languages' wildcard character.

Eric Niebler wrote:
Maurizio Vitale wrote:
What is the rationale for not having proto::tags match the corresponding mpl metafunctions?
For instance mpl has plus and proto has add (but unary_plus).
Oh my. You're right, that's awful. I'll fix these.
I've changed the names of some types in proto to bring it in line with conventions established in <functional> and Boost.MPL. This should affect just about everybody currently using proto. In particular: proto::multiply -> proto::multiplies proto::divide -> proto::divides proto::add -> proto::plus proto::subtract -> proto::minus proto::equal -> proto::equal_to proto::not_equal -> proto::not_equal_to proto::unary_plus -> proto::posit proto::unary_minus -> proto::negate proto::unary_star -> proto::dereference proto::multiply_assign -> proto::multiplies_assign proto::divide_assign -> proto::divides_assign proto::add_assign -> proto::plus_assign proto::subtract_assign -> proto::minus_assign The corresponding tag types have also changed accordingly. For the complete list of tags, see: <http://boost.cvs.sourceforge.net/boost/boost/boost/xpressive/proto/tags.hpp?view=markup> The docs, tests and examples have been updated to reflect the new names. Get the latest from CVS, or from proto.zip in the Vault. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler <eric@boost-consulting.com> writes:
For instance mpl has plus and proto has add (but unary_plus).
Oh my. You're right, that's awful. I'll fix these.
I've changed the names of some types in proto to bring it in line with conventions established in <functional> and Boost.MPL. This should affect just about everybody currently using proto. In particular:
I've just noticed you still have {left,right}_shift vs. shift_{left,right} of boost::mpl. Best regards, Maurizio

Maurizio Vitale wrote:
Eric Niebler <eric@boost-consulting.com> writes:
For instance mpl has plus and proto has add (but unary_plus). Oh my. You're right, that's awful. I'll fix these. I've changed the names of some types in proto to bring it in line with conventions established in <functional> and Boost.MPL. This should affect just about everybody currently using proto. In particular:
I've just noticed you still have {left,right}_shift vs. shift_{left,right} of boost::mpl.
You're right. I'll change this, but probably not until after BoostCon. Thanks! -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler <eric@boost-consulting.com> writes:
I've just noticed you still have {left,right}_shift vs. shift_{left,right} of boost::mpl.
You're right. I'll change this, but probably not until after BoostCon.
Found some more: bitwise_{and,or,xor} for boost::mpl bit{and,or,xor}_ And then you have these, although here is a tougher call: logical_{and,or,not} for boost::mpl::{and,or,not}_ The problem here is that proto already has and_, or_ and not_ (although not in the tag namespace) and it might be confusing to have the same name denoting different things. (although personally I find having the same name for different things in different namespaces less confusing than having different names for the same thing across proto/mpl). The reason I discovered these is that I'm writing a transform that evaluates proto expressions as mpl expressions, as long as terminals gets transformed to mpl::int_/long_/bool_. In that context it is nice to have exactly the same name so that ancillary macros can take a single argument, rather than two which are almost always the same. But I wouldn't consider this a determining factor in deciding. Before taking a decision also consider uniformity in bitwise_{and,or,xor}_assign. These are not in mpl, but I think that if bitwise_ gets dropped in the normal operator it should be dropped for assigning operators as well. Also, I wouldn't drop bitwise unless logical gets dropped as well. So on these I have no strong feelings, but I mention them anyhow so that you can think about the issue. Maybe here it would be better if boost::mpl offered the proto names as well (while preserving the existing ones for backward compatibility). Regards, Maurizio

Maurizio Vitale wrote:
Eric Niebler <eric@boost-consulting.com> writes:
I've just noticed you still have {left,right}_shift vs. shift_{left,right} of boost::mpl. You're right. I'll change this, but probably not until after BoostCon.
Found some more: bitwise_{and,or,xor} for boost::mpl bit{and,or,xor}_
And then you have these, although here is a tougher call: logical_{and,or,not} for boost::mpl::{and,or,not}_ The problem here is that proto already has and_, or_ and not_
This is tough. Proto has bitwise_or, logical_or and or_, and they mean different things. For instance, you can make a grammar like: struct MyGrammar : proto::or_< proto::logical_or<_, _> // match "a || b" , proto::bitwise_or<_, _> // match "a | b" > {}; Logical_or and bitwise_or correspond to operator|| and operator|, respectively. Proto::or_, on the other hand, is used to express alternates in a proto grammar. If we followed mpl's naming convention here, I would rename bitwise_or to bitor_, logical_or to or_, and or_ to something else. But I don't really like that. For the moment, I'm inclined to leave this as-is. I'm open to suggestions. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler <eric@boost-consulting.com> writes:
Maurizio Vitale wrote:
Eric Niebler <eric@boost-consulting.com> writes:
I've just noticed you still have {left,right}_shift vs. shift_{left,right} of boost::mpl. You're right. I'll change this, but probably not until after BoostCon.
Found some more: bitwise_{and,or,xor} for boost::mpl bit{and,or,xor}_
And then you have these, although here is a tougher call: logical_{and,or,not} for boost::mpl::{and,or,not}_ The problem here is that proto already has and_, or_ and not_
This is tough. Proto has bitwise_or, logical_or and or_, and they mean different things. For instance, you can make a grammar like:
struct MyGrammar : proto::or_< proto::logical_or<_, _> // match "a || b" , proto::bitwise_or<_, _> // match "a | b" > {};
Logical_or and bitwise_or correspond to operator|| and operator|, respectively. Proto::or_, on the other hand, is used to express alternates in a proto grammar.
If we followed mpl's naming convention here, I would rename bitwise_or to bitor_, logical_or to or_, and or_ to something else. But I don't really like that. For the moment, I'm inclined to leave this as-is. I'm open to suggestions.
I know you've already stated you feel proto::or_ and proto::and_ are the right names. And if it wasn't for trying to solve the naming conflicts with the MPL I wouldn't have any issues with this choice. But I'll try anyhow. What about following Haskell (from the list prelude, not pattern handling) and having proto::or_ become proto::any[1] and proto::and_ become proto::all? This would free the present names for the other changes. I think the follwing doesn't look bad: struct My_Grammar : proto::any< proto::or_<_,_>, proto::bitor_<_,_> > {}; But you certainly have more usages in mind than I do to decide whether proto::any and proto::all are good choices. Regards, Maurizio Footnotes: [1] actually I have a fundamental problem with 'or_' (and 'any') as they both focus on one part of what they do: certainly the pattern matches if any of the component patterns match. What they fail to convey is that the _first_ pattern that matches is used for further processing, like evaluating the result of a transform. But I cannot come up with a name that describe these two facets satisfactorily, so I guess documentation will have to supplement the name. And now that I think of it, I have no clue of what a transform with a proto::and_ at the toplevel would do. Time to look at docs/source code I guess.

Maurizio Vitale wrote:
I know you've already stated you feel proto::or_ and proto::and_ are the right names. And if it wasn't for trying to solve the naming conflicts with the MPL I wouldn't have any issues with this choice.
But I'll try anyhow.
What about following Haskell (from the list prelude, not pattern handling) and having proto::or_ become proto::any[1] and proto::and_ become proto::all? This would free the present names for the other changes.
Heh, I almost called proto::_, the wildcard pattern, proto::any. Regardless, any<> and all<> are not bad, but I see a few problems: 1) any<> doesn't suggest that alternates are tried in order 2) Neither suggest short-circuiting 3) You haven't said what proto::if_ and proto::not_ should be. (3) is the killer. Taken together, and_, or_, not_ and if_ give users an expressive and intuitive framework for reasoning about their grammars. Changing just "and_" and "or_" to "all" and "any" would break the symmetry.
Footnotes: [1] actually I have a fundamental problem with 'or_' (and 'any') as they both focus on one part of what they do: certainly the pattern matches if any of the component patterns match. What they fail to convey is that the _first_ pattern that matches is used for further processing, like evaluating the result of a transform.
True. Many of the types in proto have 2 and sometimes 3 roles. For instance, proto::plus<> is: - An expression generator. (proto::plus<A,B>::type is the type of a plus node in an expression tree, where A and B are the types of the children expressions.) - A pattern. (proto::plus<A',B'> matches the expression generated by the above if A' and B' are patterns that match A and B, for instance.) - A transform. (proto::plus<A',B'>::apply< E, S, V >::type will apply a pass-through transform to E, with S state and V visitor.) If_ and not_ also have default "identity" transforms. Even proto::expr<> can be used as a pattern (it matches itself) and as a transform (the identity transform)!
But I cannot come up with a name that describe these two facets satisfactorily, so I guess documentation will have to supplement the name.
I don't think it's a problem.
And now that I think of it, I have no clue of what a transform with a proto::and_ at the toplevel would do. Time to look at docs/source code I guess.
By default, proto::and_ applies the transform of the last branch that matches, just as proto::or_ applies the transform of the first branch that matches. It's somewhat arbitrary, I admit, but I've found this a useful default. -- Eric Niebler Boost Consulting www.boost-consulting.com

On May 20, 2007, at 4:26 PM, Eric Niebler wrote:
1) any<> doesn't suggest that alternates are tried in order
neither does or_, at least not to me.
2) Neither suggest short-circuiting
ditto. Unless you mean: given that people will come from C++ they're probably likely to read C++ semantics when presented with C++ names. So yes, I agree or_ and and_ may mean a bit more than any and all to C++ people. I guess the tradeoff is whether introducing new names and documenting their behaviour is more or less problematic than the naming conflict w/ the mpl.
3) You haven't said what proto::if_ and proto::not_ should be.
I didn't indeed. The reason is that I was concerned with tags that can appear in expressions and have a different name in MPL. Then if_ wouldn't be a problem and not_ could stay (I'd say should stay) because has the same meaning as mpl::not_. If you want to change both, a possibility would when (for if_) and unless (for not_). But I'd maintain that the not_ in expressions should stay unchanged.
(3) is the killer. Taken together, and_, or_, not_ and if_ give users an expressive and intuitive framework for reasoning about their grammars. Changing just "and_" and "or_" to "all" and "any" would break the symmetry.
all, any, when, unless seem reasonable to me. But again my point was not a "my names are better than yours" kind of contest, rather finding an acceptable way for giving the same names to things that are the same across proto and mpl.
Footnotes: [1] actually I have a fundamental problem with 'or_' (and 'any') as they both focus on one part of what they do: certainly the pattern matches if any of the component patterns match. What they fail to convey is that the _first_ pattern that matches is used for further processing, like evaluating the result of a transform.
True. Many of the types in proto have 2 and sometimes 3 roles. For instance, proto::plus<> is:
- An expression generator. (proto::plus<A,B>::type is the type of a plus node in an expression tree, where A and B are the types of the children expressions.) - A pattern. (proto::plus<A',B'> matches the expression generated by the above if A' and B' are patterns that match A and B, for instance.) - A transform. (proto::plus<A',B'>::apply< E, S, V >::type will apply a pass-through transform to E, with S state and V visitor.)
If_ and not_ also have default "identity" transforms. Even proto::expr<> can be used as a pattern (it matches itself) and as a transform (the identity transform)!
But I cannot come up with a name that describe these two facets satisfactorily, so I guess documentation will have to supplement the name.
I don't think it's a problem.
And now that I think of it, I have no clue of what a transform with a proto::and_ at the toplevel would do. Time to look at docs/source code I guess.
By default, proto::and_ applies the transform of the last branch that matches, just as proto::or_ applies the transform of the first branch that matches. It's somewhat arbitrary, I admit, but I've found this a useful default.
-- Eric Niebler Boost Consulting www.boost-consulting.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/ listinfo.cgi/boost

Maurizio Vitale wrote:
On May 20, 2007, at 4:26 PM, Eric Niebler wrote:
3) You haven't said what proto::if_ and proto::not_ should be.
I didn't indeed. The reason is that I was concerned with tags that can appear in expressions and have a different name in MPL. Then if_ wouldn't be a problem and not_ could stay (I'd say should stay) because has the same meaning as mpl::not_.
No, mpl::not_ corresponds to proto::logical_not, and proto::not_ sticks out just as proto::or_ does.
If you want to change both, a possibility would when (for if_) and unless (for not_).
Interesting. All, any, when, and unless are not unreasonable. I know you retracted this suggestion in another message, but I want you to bring it up again when proto is under review. Naming is super-important, and I want more feedback on this issue. I'll remind you when the time comes. The mpl names come from the standard. "bitor" is an alternate token for |. Extending this, bitor_eq is an alternate token for |=, which suggests that bitwise_or_assign should be bitor_eq_. But then what about operator=? Should that be eq or eq_? These are a bit too terse for my taste, and could be confused with ==, which is equal_to. And <functional> has equal_to but greater_equal (not greater_equal_to). A perfectly consistent set of names may simply be impossible. -- Eric Niebler Boost Consulting www.boost-consulting.com

AMDG Eric Niebler <eric <at> boost-consulting.com> writes:
If you want to change both, a possibility would when (for if_) and unless (for not_).
Interesting. All, any, when, and unless are not unreasonable. I know you retracted this suggestion in another message, but I want you to bring it up again when proto is under review. Naming is super-important, and I want more feedback on this issue. I'll remind you when the time comes.
Another possibility is to use separate namespaces proto::operators::or_ proto::control::or_ In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Eric Niebler <eric <at> boost-consulting.com> writes:
If you want to change both, a possibility would when (for if_) and unless (for not_). Interesting. All, any, when, and unless are not unreasonable. I know you retracted this suggestion in another message, but I want you to bring it up again when proto is under review. Naming is super-important, and I want more feedback on this issue. I'll remind you when the time comes.
Another possibility is to use separate namespaces proto::operators::or_ proto::control::or_
I thought about that, and it's not unreasonable, either. It might cause less confusion. However, the different or_'s will often be used together, making qualification a requirement. Compare the following (assumes using namespace proto;): struct MyGrammar : control::or_< operators::or_<_,_> , operators::bitor_<_,_> > {}; to struct MyGrammar : or_< logical_or<_,_> , bitwise_or<_,_> > {}; IMO, eliminating the operators:: namespace would be better. This isn't half bad: struct MyGrammar : control::or_< or_<_,_> , bitor_<_,_> > {}; But control::or_ is likely to be more common than or_ (the operator), so the Huffman coding is lousy. Gah, naming is hard! Opinions? Maurizio? Joel? Hartmut? -- Eric Niebler Boost Consulting www.boost-consulting.com

On May 21, 2007, at 4:13 PM, Eric Niebler wrote:
Steven Watanabe wrote:
AMDG
Eric Niebler <eric <at> boost-consulting.com> writes:
If you want to change both, a possibility would when (for if_) and unless (for not_). Interesting. All, any, when, and unless are not unreasonable. I know you retracted this suggestion in another message, but I want you to bring it up again when proto is under review. Naming is super-important, and I want more feedback on this issue. I'll remind you when the time comes.
Another possibility is to use separate namespaces proto::operators::or_ proto::control::or_
[snip]
IMO, eliminating the operators:: namespace would be better. This isn't half bad:
struct MyGrammar : control::or_< or_<_,_> , bitor_<_,_>
{};
But control::or_ is likely to be more common than or_ (the operator), so the Huffman coding is lousy. Gah, naming is hard! Opinions? Maurizio? Joel? Hartmut?
I think this is getting somewhere. I would focus on making this nice to read rather than cheap to type in, so I'm not too concerned with the number of characters in the string control::or_. I'm more concerned that: - the or_ part doesn't stand out. It comes after some other characters that the reader has to parse while reading. And those will be shared by all control::{and,or,if,not}_. If you have a deeply nested grammar full of control:or_, control::and_ and friends it might be difficult to tell what it means. - and the error message (because hopefully we get one) when somebody uses the (operators::) or_ at the grammar toplevel needs to be crystal clear. Because somebody will forget the namespace qualification sometimes. For a large number of somebody and sometimes. Would it be criminal to consider or_, and_, not_, if_ "namespaces" ? This way we can get something like: or_::match< or_< > bitor_<> > Clearly they cannot be real namespaces, otherwise the template (operator::)or_ would shadow it, hence the match template should be stuffed into the (operator)::or_ template, which may or may not work depending on the partial specializations needed. Even if it worked, seems very poor coding taste. But maybe there's some other way to allow the or_::match look and feel. Don't know. I'll probably be ashamed of this suggestion in a couple of hours. Regards, Maurizio

AMDG Maurizio Vitale <maurizio.vitale <at> polymath-solutions.com> writes:
- and the error message (because hopefully we get one) when somebody uses the (operators::) or_ at the grammar toplevel needs to be crystal clear. Because somebody will forget the namespace qualification sometimes. For a large number of somebody and sometimes.
Is that more likely that mixing up which form of or to use? In general is there any way to detect the problem? Maybe there should be a way to assert that a pattern matches an expression which tells what didn't match on failure? In Christ, Steven Watanabe

Eric Niebler wrote:
I thought about that, and it's not unreasonable, either. It might cause less confusion. However, the different or_'s will often be used together, making qualification a requirement. Compare the following (assumes using namespace proto;):
struct MyGrammar : control::or_< operators::or_<_,_> , operators::bitor_<_,_> > {};
to
struct MyGrammar : or_< logical_or<_,_> , bitwise_or<_,_> > {};
I don't mind having it the first way. Explicit is always better than implicit. If that's too longish somebody could always use a using namespace specification for whatever variant it may fit... My main concern is name compatibility to mpl. Regards Hartmut

Maurizio Vitale wrote:
Found some more: bitwise_{and,or,xor} for boost::mpl bit{and,or,xor}_
And then you have these, although here is a tougher call: logical_{and,or,not} for boost::mpl::{and,or,not}_ The problem here is that proto already has and_, or_ and not_ (although not in the tag namespace) and it might be confusing to have the same name denoting different things. (although personally I find having the same name for different things in different namespaces less confusing than having different names for the same thing across proto/mpl).
Ah, I finally remember my rationale for choosing the names logical_and, logical_or and logical_not for representing the operators &&, || and !. Those are the std names of the function objects in <functional> for those operators. And the names bitwise_and, bitwise_or, etc., are chosen by extension. Anyway, that was my reason, and it still seems like a good one. That doesn't mean I can't be convinced to change it, though.
Maybe here it would be better if boost::mpl offered the proto names as well (while preserving the existing ones for backward compatibility).
Eh. Naming is such a contentious issue. I'm not sure I want to wage that battle. -- Eric Niebler Boost Consulting www.boost-consulting.com
participants (7)
-
Eric Niebler
-
Hartmut Kaiser
-
Larry Evans
-
Maurizio Vitale
-
Maurizio Vitale
-
Steven Watanabe
-
Stuart Dootson