Boost logo

Boost :

Subject: Re: [boost] [contract] syntax redesign
From: Dave Abrahams (dave_at_[hidden])
Date: 2011-10-24 18:13:54


on Mon Oct 24 2011, lcaminiti <lorcaminiti-AT-gmail.com> wrote:

> Dave Abrahams wrote:
>>
>
>> on Sat Oct 22 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
>>
>>> On Fri, Sep 2, 2011 at 3:14 PM, Dave Abrahams &lt;dave@&gt; wrote:
>>>> on Fri Sep 02 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
>>>
>>>>> (I still have to implement named parameter support (using
>>>>> Boost.Parameter behind the scene) but that shouldn't be too hard. The
>>>>> macros already parse the named parameter syntax using in/out/inout
>>>>> "keywords".)
>>>>
>>>> I can't wait.
>>>
>>> Hello all,
>>>
>>> Here's how I am thinking to support named parameters within
>>> Boost.Contract's syntax.
>>
>> Cool! Don't forget deduced parameters, though ;-)
>>
>
> Deduced params will be prefixed by the pp-keyword deduce. For example:
>
> CONTRACT_FUNCTION(
> void (def) (
> // skip optional keyword tag namespace
> in (char const*) name, // input required name with exact type
> in auto func, // input required function of any type
> // deduced optional params with exact and predicate type requirement
> deduce in (char const*) docstring, default "",
> deduce in requires(is_keyword_expression<_>) keywords,
> default no_keywords,
> deduce in requires(not_< or_<is_convertible&lt;_, char const*>,
> is_keyword_expression<_> > >) policies,
> default default_call_policies
> )
> precondition( ... )
> postcondition( ... )
> ) ;

Nicely done.

>>> namespace tag, // optional namespace (tag assumed by default)
>>
>> I'd really like to eliminate that if possible; it's quite off-putting.
>> I guess if you can make it optional, that handles the problem.
>
> Yes, the keyword tag namespace is always optional and tag is used by default
> (e.g., the python::def above did not specify the namespace).
>
>>> in requires( // requires for type requirements
>>
>> Why are we using "in" before "requires?" Requirements are not "in
>> parameters."
>>
>
> This might be tricky... I need to prefix all named parameters with special
> "keywords" so the pp can distinguish them from positional parameters. In
> this case, I could just use requires and say that a parameter is named if
> prefixed by in, out, in out, or requires.

Yeah, that's what I was thinking.

> However, I need to keep in, out, or in out for exact type requirements
> (not predicate) because they don't use requires. For example, this is
> a named parameter:
>
> void (f) (
> in (typename graph_traits<graph_type>::vertex_descriptor)
> root_vertex, default *vertices(graph).first,
> )
>
> But this is a positional parameter (no in prefix):
>
> void (f) (
> (typename graph_traits<graph_type>::vertex_descriptor)
> root_vertex, default *vertices(graph).first,
> )
>
> Can you please explain better why it might be a problem if I always use the
> in, out, in out specifiers even with predicate type requirements?

I'm sorry, maybe I misunderstood. I thought the requires( ... ) clause
was not part of a parameter declaration. Ultimately it would probably be
syntactically superior if requirements were separated, but if that's not
the case I can certainly live with it.

> I'd think ultimately, any parameter must have in, out, or in out
> semantic even if its type is specified using a metafunction
> predicate... isn't that ture? For example, depth_first_search
> documents /all/ its parameters as in, out, or in out:
> http://www.boost.org/doc/libs/1_47_0/libs/graph/doc/depth_first_search.html

Yeah... I think we said at one point that "in" was the default, but that
feature may have fallen by the wayside.

>> I guess, to sum up, to evaluate the syntax I'd need to see the most
>> beautiful possible realization of this algorithm as opposed to the most
>> horrendous ;-).
>>
>
> I understand. Is this version more usable to judge the syntax?

No, it's still too dense because of the comments (and the redundant
optional "namespace tag"). Try again, please :-)

> #include <contract.hpp>
>
> using namespace boost;
> using namespace boost::mpl::placeholders;
> using namespace boost::python;
>
> namespace graphs {
>
> BOOST_PARAMETER_NAME(graph)
> BOOST_PARAMETER_NAME(visitor)
> BOOST_PARAMETER_NAME(root_vertex)
> BOOST_PARAMETER_NAME(index_map)
> BOOST_PARAMETER_NAME(color_map)
>
> // For simplicity, leaving out the use of BOOST_IDENTITY_TYPE for now.
> CONTRACT_FUNCTION(
> void (depth_first_search) (
> // param keyword tag namespace (always optional, default to `tag`)
> namespace tag,
> // input required param with predicate type requirement (requires)
> in requires(is_incidence_and_vertex_list_graph<_>) graph,
> // input optional (default) param of any type (auto)
> in auto visitor, default dfs_visitor<>(),
> // input optional param with exact type requirement (parenthesized
> type)
> in (typename graph_traits<graph_type>::vertex_descriptor)
> root_vertex, default *vertices(graph).first,
> // input optional param with predicate type requirement (requires)
> in requires(is_integral_property_map_of_key<_, typename
> graph_traits<
> graph_type>::vertex_descriptor>) index_map,
> default get(vertex_index, graph),
> // input-output optional param with predicate type requirement
> in out requires(is_property_map_of_key<_, typename graph_traits<
> graph_type>::vertex_descriptor>) color_map,
> default default_color_map(num_vertices(graph), index_map)
> )
> precondition( ... )
> postcondition( ... )
> ) ;
>
> } // namespace graphs
>
> I really appreciate your help on this, I only marginally understand
> Boost.Parameter.
> --Lorenzo

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk