Boost logo

Boost Users :

From: Joel de Guzman (joel_at_[hidden])
Date: 2008-01-10 18:52:40


Tobias Schwinger wrote:
>
> Then 'switch_<void>(n)' is a fused function and 'cases' a sequence of
> cases (whether implemented with Fusion or not)...
>
> > The number of cases *can* vary at compile time. I have a guess that
> > we're talking past each other.
>
> Yes, obviously -- I think because of a pair of parentheses. This code
>
> switch_<result>(n)
> ((
> // ... hand-written cases, note (( ))
> ));
>
> would've told me more easily what you're up to :-).

I often add the double parens. Someone asked why at BoostCon'07.
I answered "because I like it" :-) Now, I have a more valid reason.
Yeah... sorry about the confusion.

> >>> For the purpose of clarification, let me call the original
> >>> interface A and my proposal B.
> >>>
> >>> Again:
> >>>
> >>> * Transforming A to B requires minimal amount of coding. The smarts
> >>> is already in the PP code. The cost is cheap.
> >> The cost is cheap and the effect is destructive :-).
> >
> > Why is it destructive?
>
> We lose the index and the chance to easily use a single function for all
> cases.

Index:

* I also recall sometime ago when attributes for Spirit2 was being
   discussed. For alternates:

      (a | b | c)[f]

   the question was: do f receive the index or not. Many times it
   is useful.

* With for_each (and many of the algorithms), one disadvantage
   over the lowly for or while is the access to the index of the
   iterator. Many times those are usefule too.

My answer to these kind of concerns now is: bind it when you
need it.

Single function:

I'm a strong advocate of smaller is better. Modularity matters.
Big classes (or in this case function objects), metaprogram blobs
(i.e. traits), humongous enums, and all such sort of dinosours :-)
are best avoided. They are convenient up to a certain extent and
becomes unmanageable beyond a certain limit.

In all of my use cases, I have N functions that are provided
elsewhere and I have no control over (e.g. parser functions).
I insist that this is the more common use case. Grouping
them into a single big struct is an unnecessary and cumbersome
step.

Still, if people insist, I outlined a way to convert the big
function object to smaller 'bound' objects, in another post.
Just bind 'em into smaller function chunks.

> > You must be seeing a use-case that I don't.
>
> Yes, see below.
>
> [...]
>
> >
> > To be honest, I really don't see your point. I still don't see why
> > you'd want to build A on top of B.
> >
>
> 1. As a thought experiment to figure out which of the two variants is
> the more basic one, and
>
> 2. for parameterizing a single function with compile time information
> looked up by index (it's quite common and -as you can probably guess-
> the index can be very handy inside the metaprogram).
>
> Now that I have figured out that your interface accepts sequences, we
> can actually express the transforms between the two:
>
> A ---> B: function := L(I): functions[I]()
> B ---> A: transform(cases, L(I): make_pair<I>(bind(function,I())))
>
> // Notation:
> // =========
> // uppercase - types
> // lowercase - objects
> // L(args): - lambda composition
>
> I don't expect us to a reach consensus, but hopefully we do understand
> each other's points now.

That's a relief ;-)

Now that that's cleared, let me /push/ now the other benefits
of my proposed interface:

* Ability to allow fall-through and break:

       case_<1>(f1, break_), // no fall-through
       case_<2>(f2), // fall-through (by default)

* Allow multiple case handling:

       case_<'x', 'y'>(f2), // handle 'x' and 'y'

Regards,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net