[preprocessor] Lists vs. nil-sequences?

Hello all, I have a curiosity about Boost.Preprocessor: What is the difference between pp-lists and pp-sequences starting with a NIL element? PP-Lists can be empty or nil (e.g., have 0 size, etc) while pp-sequences cannot. However, I could use sequences that always start with a nil element `(NIL) ...` and write macros that ignore this 1st element so to handle empty pp-sequences: #define NILSEQ_SIZE(nilseq) BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(nilseq)) NILSEQ_SIZE( (NIL) ) // 0 NILSEQ_SIZE( (NIL)(a) ) // 1 NILSEQ_SIZE( (NIL)(a)(b) ) // 2 BOOST_PP_LIST_SIZE( BOOST_PP_NIL ) // 0 BOOST_PP_LIST_SIZE( (a, BOOST_PP_NIL) ) // 1 BOOST_PP_LIST_SIZE( (a, (b, BOOST_PP_NIL)) ) // 1 Similarly, I could program NILSEQ_FOR_EACH, NILSEQ_ENUM, etc. What are the pros and cons of using pp-nil-sequences vs pp-lists given that both allow for emptiness? Thank you very much. -- Lorenzo

On 3/2/2011 9:32 AM, Lorenzo Caminiti wrote:
Hello all,
I have a curiosity about Boost.Preprocessor: What is the difference between pp-lists and pp-sequences starting with a NIL element?
PP-Lists can be empty or nil (e.g., have 0 size, etc) while pp-sequences cannot. However, I could use sequences that always start with a nil element `(NIL) ...` and write macros that ignore this 1st element so to handle empty pp-sequences:
#define NILSEQ_SIZE(nilseq) BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(nilseq))
NILSEQ_SIZE( (NIL) ) // 0 NILSEQ_SIZE( (NIL)(a) ) // 1 NILSEQ_SIZE( (NIL)(a)(b) ) // 2
BOOST_PP_LIST_SIZE( BOOST_PP_NIL ) // 0 BOOST_PP_LIST_SIZE( (a, BOOST_PP_NIL) ) // 1 BOOST_PP_LIST_SIZE( (a, (b, BOOST_PP_NIL)) ) // 1
Similarly, I could program NILSEQ_FOR_EACH, NILSEQ_ENUM, etc.
What are the pros and cons of using pp-nil-sequences vs pp-lists given that both allow for emptiness?
I believe tuples and arrays can be empty also, but the first does not give length so I would choose a list or an array if you must deal with emptiness internally. Externally for the end-user I would always create two slightly different macros, one for emptiness and one without, if I want the end-user to pass variable amounts of elements. I do not believe requiring an end-user to pass some emptiness notation is a friendly thing. You can then direct either of these macros internally to a macro which takes a list or an array and the data may be empty, for common processing.

On 3/2/2011 6:32 AM, Lorenzo Caminiti wrote:
Hello all,
I have a curiosity about Boost.Preprocessor: What is the difference between pp-lists and pp-sequences starting with a NIL element?
PP-Lists can be empty or nil (e.g., have 0 size, etc) while pp-sequences cannot. However, I could use sequences that always start with a nil element `(NIL) ...` and write macros that ignore this 1st element so to handle empty pp-sequences:
#define NILSEQ_SIZE(nilseq) BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(nilseq))
NILSEQ_SIZE( (NIL) ) // 0 NILSEQ_SIZE( (NIL)(a) ) // 1 NILSEQ_SIZE( (NIL)(a)(b) ) // 2
BOOST_PP_LIST_SIZE( BOOST_PP_NIL ) // 0 BOOST_PP_LIST_SIZE( (a, BOOST_PP_NIL) ) // 1 BOOST_PP_LIST_SIZE( (a, (b, BOOST_PP_NIL)) ) // 1
Similarly, I could program NILSEQ_FOR_EACH, NILSEQ_ENUM, etc.
What are the pros and cons of using pp-nil-sequences vs pp-lists given that both allow for emptiness?
Thank you very much.
I don't know whether this is necessarily good practice or not, but I've created macros that allow BOOST_PP_SEQ_NIL to be passed as a parameter where a Boost.PP seq is intended, and within the macro implementation I dispatch appropriately. From an interface-design point-of-view, that would seem to be preferable to prepending all non-empty Boost.PP seq's with "(NIL)". However, I would believe it's easy to sacrifice efficiency depending on how you do the dispatch... - Jeff
participants (3)
-
Edward Diener
-
Jeffrey Lee Hellrung, Jr.
-
Lorenzo Caminiti