Boost logo

Boost :

Subject: Re: [boost] [contract] syntax redesign
From: lcaminiti (lorcaminiti_at_[hidden])
Date: 2011-10-24 15:33:01


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( ... )
) ;

>> 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. 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'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

> I realize this is a direct translation of what's in the Boost.Parameter
> docs, but it would be instructive to see the example without all the
> mess, using something like concepts for the "requires" clause. In fact,
> I believe much of what you have below could also be consolidated into
> something more semantically meaningful. Would
> something like that be possible? Also, the use of graphs::graph::_ and
> boost::mpl::_ below is confusing me. I've never heard of the former.
>
> 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?

#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

--
View this message in context: http://boost.2283326.n4.nabble.com/contract-syntax-redesign-tp3563993p3934283.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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