Boost logo

Boost :

From: Vesa Karvonen (vesa_karvonen_at_[hidden])
Date: 2003-01-15 04:30:29


Hi,

The sequence data structure is very nice. One of the advantages is that it
makes it possible to reduce syntactic clutter considerably compared to
lists.

Unfortunately, due to preprocessor limitations, one is limited to
parenthesized expressions that do not contain top-level commas. For example,
the following is not considered a sequence:

  (a,b)(c,d)(e,f)

But the following is a sequence:

  ((a,b))((c,d))((e,f))

In order to reduce syntactic clutter, it would be nice to have a macro that
converts an arbitrary "relation"/"table" or "n-sequence" into a sequence. In
other words:

  RELATION_TO_SEQ(2,(a,b)(c,d)(e,f)) ==> ((a,b))((c,d))((e,f))
  RELATION_TO_SEQ(3,(a,b,c)(d,e,f)) ==> ((a,b,c))((d,e,f))

I think that such a macro would be more than just a small convenience. The
above examples do not do justice to the reduction in syntactic clutter. The
most promising use for this construct would be as a building block for
macros that essentially take relations as arguments. For example, the state
machine example I presented previously, would essentially take a relation
(actually nested relations) as an argument.

The implementation of RELATION_TO_SEQ() should not be very difficult, but
there is a quick incomplete implementation in this post, that can give some
ideas. A more generic "token sequence" to sequence conversion macro could
also be very useful. Consider the following token sequences:

  1 0 2 3
  B o o s t SPACE 1 3 1

Neither of the above are sequences, but it would be possible to turn them
into sequences using suitable macros (pseudo-code):

  TOKEN_SEQ_TO_SEQ(FIRST, REST, IS_LAST, 1 0 2 3)
     ==> (1)(0)(2)(3)

  TOKEN_SEQ_TO_SEQ(FIRST, REST, IS_LAST, B o o s t SPACE 1 3 1)
     ==> (B)(o)(o)(s)(t)(SPACE)(1)(3)(1)

The macros FIRST, REST and IS_LAST would be used by the TOKEN_SEQ_TO_SEQ
conversion macro to extract tokens from the token sequence. The
RELATION_TO_SEQ macro could easily be implemented in terms of the
TOKEN_SEQ_TO_SEQ macro.

The intention behind these conversion macros is to allow making
more-convenient-to-use code generating macros using the preprocessor
library. They essentially help to reduce the amount of unnecessary
punctuation for the user of such code generating macros.

None of these macros would be strictly necessary, as similar things can be
achieved using lists and sequences.

...

BTW, the naming of SEQ_HEAD and SEQ_TAIL is, IMO, unfortunate, as they do
not match the precedent made by LIST_FIRST and LIST_REST. IIRC, I polled the
group when I designed the initial list support for naming suggestions and
FIRST/REST was the preferred choice. Even if HEAD and TAIL would, in some
sense, be slightly better, I think that it is more important to try to be
consistent. This is not a big issue, but it could, for instance, be useful
for designing generic sequence manipulation macros. Actually, perhaps there
is a good reason to use the name SEQ_TAIL as a sequence can not be empty.

- Vesa Karvonen

#include "boost/preprocessor/tuple/eat.hpp"
#include "boost/preprocessor/tuple/elem.hpp"
#include "boost/preprocessor/control/while.hpp"
#include "boost/preprocessor/control/if.hpp"
#include "boost/preprocessor/cat.hpp"

#define MAKE_SEQ(n,seq)
BOOST_PP_IF(MORE(n,seq),MAKE_SEQ_N,MAKE_SEQ_1)(n,seq)
#define MAKE_SEQ_1(n,seq) (FIRST(n,seq))
#define MAKE_SEQ_N(n,seq)
BOOST_PP_TUPLE_ELEM(3,0,BOOST_PP_WHILE(MAKE_SEQ_P,MAKE_SEQ_O,((FIRST(n,seq)),n,REST(n,seq)
FIRST(n,seq))))
#define MAKE_SEQ_P(d,rns)
MORE(BOOST_PP_TUPLE_ELEM(3,1,rns),BOOST_PP_TUPLE_ELEM(3,2,rns))
#define MAKE_SEQ_O(d,rns)\
  
(BOOST_PP_TUPLE_ELEM(3,0,rns)(FIRST(BOOST_PP_TUPLE_ELEM(3,1,rns),BOOST_PP_TUPLE_ELEM(3,2,rns)))\
  ,BOOST_PP_TUPLE_ELEM(3,1,rns)\
  ,REST(BOOST_PP_TUPLE_ELEM(3,1,rns),BOOST_PP_TUPLE_ELEM(3,2,rns))\
  )

#define FIRST(n,seq) BOOST_PP_TUPLE_ELEM(n,0,(BOOST_PP_CAT(FIRST_H,n) seq))
#define FIRST_H2(x,y) (x,y), BOOST_PP_NIL
#define REST(n,seq) BOOST_PP_TUPLE_EAT(n) seq
#define MORE(n,seq)
BOOST_PP_TUPLE_ELEM(2,0,(BOOST_PP_CAT(MORE_,BOOST_PP_CAT(MORE_H,n) seq)))
#define MORE_H2(x,y) ONE2
#define ONE2(x,y) TWO
#define MORE_ONE2 0, BOOST_PP_NIL
#define MORE_TWO 1, BOOST_PP_NIL

// test

#define SEQ2 (a,b)(c,d)(e,f)
MAKE_SEQ(2,SEQ2)

_________________________________________________________________
STOP MORE SPAM with the new MSN 8 and get 2 months FREE*
http://join.msn.com/?page=features/junkmail


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