Re: [boost] Re: generic uses of optionalT
On Mon, Sep 01, 2003 at 04:05:59PM -0600, Dave Gomboc wrote: [Brian McNamara] do_something( adapt( 3 ) ); do_something( adapt( nilableint(3) ) ); do_something( adapt( foo ) ); // foo has unknown type But I'd like to write do_something(3); do_something(foo); // of type T do_something(bar); // of type nilableT Can I have my cake and eat it too? ;-) Yes: template class T void do_something( T x ) { do_something_helper( adapt(x) ); } template class T void do_something_helper( nilableT x ) { /* actually do it */ } (Shameless plus: Note that with FC++, do_something = compose( do_something_helper, adapt ); or do_something = do_something_helper ^of^ adapt; provided that things are defined as functoids.) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
On Tue, Sep 02, 2003 at 09:05:59AM +0800, Joel de Guzman wrote: My attempt to image optionalT as conceptually a specialized but nevertheless, *IS-A* T, with the added specialization that it can be in a dead-uninitialized state. Is a feeble attempt to re-sell the idea of the concept that will be immediately obvious to the OO programmer. I never really understood why I wasn't able to sell the idea that an optionalT is *REALLY REALLY REALLY* nothing else but a union of T and nil. It's been pointed out before, but to re-emphasize it: from a type-theoretic standpoint, it is not the case that optionalT-isa-T. Rather T-isa-optionalT. (Dog-isa-Animal because Animal has more possible values.) I don't mind the suggestive conceptual analogy/similarity, but when you get down to technicalities, the isa relationship doesn't hold in the same direction you're saying (in your first sentence above). I agree 200%. I think the *only* meaningful argument against this was posed by Brian. That, in C++, you cannot make XT be a drop-in replacement of T because implicit conversion will not allow code such as: struct A { void foo(); } template class T void bar(T t) { t.bar(); } bar(A()); bar(XA()); // HERE Unless: class XT : public T {...}; But then again, that's just a technical impediment. As I just mentioned in a previous mail, if bar() has the foresight to expect this, it can use an adapter in its implementation to smooth out this issue. (E.g. template class T void bar(T t) { adapt(t).bar(); } ) As a final aside, I think much of this thread is degenerating into Parkinson's Bicycle Shed[*], with respect to is it a pointer/container/X? At this point, I think we know what set of methods should be in the interface (indeed, there could be methods both to return pointers and references; both to throw/fail-undefinedly, etc.) and the names/documentation issues will fall out with more experience. Just MO. [*] See bottom of http://www.boost.org/more/discussion_policy.htm -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Re: Re: Optional, tie, and iterator_adaptor
On Mon, Sep 01, 2003 at 09:22:01PM -0600, Dave Gomboc wrote: [Fernando Cacciola] I'm saying that the choice made by variant in this regards is to the code using get as hopeless as undefined behaviour. I don't think that preconditions (and exceptions thereof) should be used to arbitrarily make the illusion of giving meaning to an operation that is undefined at the conceptual level. For myself, and I think also for Joel, nil is a fully legitimate value, not a hopeless, meaningless, conceptually undefined value. It's quite clear that you don't share this view. The conceptual divide here is surprisingly large. I'm surprised to find myself suggesting this, but perhaps instead of debating this issue further I and like-interested people should create and submit a high-quality implementation of nilable.hpp to Boost. If accepted, people could then choose whichever best meets their needs/expectations. I think this is a good idea too. Personally, I side with Fernando's conception of 'optional', but clearly there are two groups which each want a different (though similar) class. My contribution with this message is to mention that, rather than having two completely separate implementations, one could be built atop the other (or both from a common root). My hunch is that your nilable idea could easily be built as a very thin wrapper around optional (provided optional has a wide enough interface, but I think it does). Something along the lines of template class T class nilable { optionalT o; public: T get() { if( o ) return *o; throw oops; } // etc. }; -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
On Mon, Sep 01, 2003 at 09:03:17AM +0800, Joel de Guzman wrote: Do it the ref, tuple and variant way: get(). But get(), as an element-access interface, should return a reference, not a pointer, as it does currently. Clearly I had not been paying enough attention earlier in the thread; I was oblivious to the fact that get() was returning a pointer and not a reference. I think get() (or operator*(), or however it ends up being spelled) should indeed return a reference. (Apologies for the confusion.) As for the use-case with the function returning a pair of iterators that we'd like to assign to optionals via a tie(), I think there should also be a different method in the interface which returns the hole in an empty optional where a new value can be constructed. See, e.g., my earlier message which defined an interface with operator+() and operator~(). -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] generic uses of optionalT
On Sun, Aug 31, 2003 at 09:12:59PM -0600, Dave Gomboc wrote: The point is that optionalT is not a T, and most notably, a template function will never perform the coercion. Replace the lines like B b = get2(args); in your example with real calls to, e.g. do_something( get2(args) ) and do_something() is likely to fail if it's a template function (expecting a T and not an optionalT). Okay, you've demonstrated that it may not be possible to drop-in optionalT for T with zero code changes when T is not a scalar type. (Usually, my Ts are! ;-) Nonetheless, it is at least still possible to write generic code that accepts either T or the wrapped T, which is definitely an improvement over writing a whack of special-casing code. Indeed. [snipped most of code] template typename T class nilable { public: ... operator T(void) const { if (nil_) throw std::bad_cast(); return value_; }; ... I'd add T get() { return T(*this); } // in reality, return T -- using T here just to show the idea ... try { nilable std::vectorint nv(v); //output(nv); // true, this fails output(std::vectorint(nv)); // but this succeeds! As does output( nv.get() ); nilable std::vectorint nv2; output(std::vectorint(nv2)); // and this throws as expected. Again I'd prefer output( nv2.get() ); I was originally arguing with Joel because I thought he wanted to use exactly nv and not anything like nv.get(). I think now that we've cleared up the confusion about get() returning a reference instead of a pointer, we're all back on the same page. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: generic uses of optionalT
On Mon, Sep 01, 2003 at 12:13:11AM -0600, Dave Gomboc wrote: I've been trying to set things up so that code is written for T that can then also use nilableT seamlessly, but doing things the other way around might be an improvement. Agreed. [Brian McNamara] I was originally arguing with Joel because I thought he wanted to use exactly nv and not anything like nv.get(). I think now that we've cleared up the confusion about get() returning a reference instead of a pointer, we're all back on the same page. Well, I guess you're still arguing with me ;-) because I _do_ want to use exactly nv and not anything like nv.get(). I don't like get() because I cannot write x.get() when x is a POD. This would mean I have to support nilableT and T with different code, which is exactly what I'm trying to avoid. This is trivial to fix: // Adapters to uniform-ify the interface template class T nilableT adapt( T x ) { return nilableT(x); } template class T nilableT adapt( nilableT x ) { return x; } // generic function template class T void do_something( nilableT x ) { ... } // examples demonstrating how code looks same regardless of type do_something( adapt( 3 ) ); do_something( adapt( nilableint(3) ) ); do_something( adapt( foo ) ); // foo has unknown type -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Reducing template compile-times
Template libraries, especially those employing expression templates, take a long time to compile. As an example, one of the example files for FC++ (parser.cpp) takes about 10 minutes to compile on a blazingly fast machine with tons of RAM. I would like to reduce the compile-time. I solicit any help/advice on the topic; I am hoping some of the Boost contributors will have run into this same problem with their own libraries, and have found some ways to address it. Here is what I have already figured out. First off, in FC++, there are a number of templates whose sole purpose is to provide better compiler diagnostics (along the same general lines as concept_checks). I rewrote the library code so that these checks are only enabled when a certain preprocessor flag is defined. Turning off these checks reduced the compile-time of parser.cpp from 10 minutes to 8 minutes--a significant speedup. That was the most obvious piece of low-hanging fruit; since the code to produce the compile-time diagnostics doesn't do anything at run-time, it was straightforward to just have a switch to turn it on and off. I imagine there are other things I can do to rewrite some of the library templates that are doing real work so that they compile faster. Specifically, I imagine that some templates can be rewritten so that they cause fewer auxiliary templates to be instantiated each time the main template gets instantiated. However there are two issues that make this hard to do: (1) Knowing which templates to focus on. That is, which templates are effectively the inner loops in the compilation process, and thus deserve the most attention when it comes to optimizing them? (2) Knowing how to rewrite templates to make them faster. I imagine that fewer templates instantiated will mean faster compile times, but I don't actually know this for sure. I have no window into what the compiler is actually doing, to know what takes so long. Maybe it's the template instantiation process; maybe it's all the inlining; maybe it's the code generation for lots of tiny functions. I don't know. I have made some headway with (1): the unix utility nm lists all the symbols compiled into an executable program, and by parsing the output, I am able to determine which templates have been instantiated with the most number of different types. My little script yields output like ... 313 boost::fcpp::lambda_impl::exp::Value 314 boost::fcpp::lambda_impl::BracketCallable 606 boost::fcpp::lambda_impl::exp::CONS 609 boost::fcpp::full1 610 boost::intrusive_ptr 670 boost::fcpp::lambda_impl::exp::Call which tells me that the Call template class has been instantiated 670 different ways in parser.cpp. This at least gives me some idea of which classes to focus my optimizing attention on. However a drawback of using the nm approach is that it only shows templates with run-time storage. There are tons of template classes which contain nothing but typedefs, and I imagine they're being instantiated lots of ways too, and I don't know if this slows stuff down significantly too. As to (2), I know nothing, other than the speculation that fewer instantiations is better. So, that's where I am. Help! :) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
So I completely disagree that optionals should mix the interfaces of optional and the wrapped object into one. I think there should be an explicit unwrapping operation. But this is just my opinion, based on no practical evidence/experience, and I'm sure there are trade-offs either way. I'll explain the crux of my own reasoning below. On Sun, Aug 31, 2003 at 11:59:42PM +0800, Joel de Guzman wrote: It's really strange (and hard to explain) that you have to dereference optionalB. Example: F(tupleA, optionalB, C args) { A a = get1(args); B b = *get2(args); // strange! C c = get3(args); } I don't think it's strange at all; an optionalB is not a B! Not only is it strange, it complexifies the code a lot when the code is automatically generated by some meta-program. Example: template class A, class B, class C F(tupleA, B, C args) { A a = get1(args); B b = get2(args); C c = get3(args); } Whoops, have to do a special case IFF B is an optional! Well, no. B==optionalBprime via template unification, right? If you want to do something with a Bprime, then yes, you have to special-case it, as you should. Here's a (contrived) example of how the implicit conversion breaks generic code: template class Container void contrived( Container c ) { c.begin(); } ... vectorint v; contrived(v); // fine optionalvectorint ov( v ); contrived(ov); // fails The point is that optionalT is not a T, and most notably, a template function will never perform the coercion. Replace the lines like B b = get2(args); in your example with real calls to, e.g. do_something( get2(args) ) and do_something() is likely to fail if it's a template function (expecting a T and not an optionalT). As another example, FC++ lists support conversion-to-bool as a test for NIL: fcpp::listint l = NIL; if( l ) // if l not empty cout head(l); // print first element Clearly if 'l' were an optional, the if test would have a different meaning. I know you've been supporting a separate way to do the test (with ==none), but I think that's completely arbitrary. The two issues are both really the same issue, in my mind. Of all the types involved in the passing of arguments to the semantic actions, the optional doesn't fit nicely because it is the only one that has mixed value/pointer semantics. I am tempted to not use optionalT because of this and instead use variantT, none, but I hate to miss the performance advantage of optional vs. variantT, none. I have not used variant and know little about it, but I imagine you have to explicitly tell a variant which type you expect to get out of it. I think the same is true of optional; the call to operator*() (or whatever) says I want the T type (rather than the 'none'). My two cents. Again let me stress I'm arguing based on no practical experience working with any of these datatypes. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
On Sun, Aug 31, 2003 at 10:41:15AM -0700, Mat Marcus wrote: --On Sunday, August 31, 2003 10:29 AM -0400 Brian McNamara First off, let me say I do think this is a compelling use-case. ... I missed the beginning of this thread, but I imagine the motivation is to avoid having to say std::pairIter,Iter p = out_edges(v,g); Iter begin = p.first; Iter end = p.second; each and every single time you call out_edges(). IIUC, you are saying that you don't find the use of tie with pairs very compelling. Fair enough. Of course tie is more generically useful with arbitrary tuples and multi-value returns. I was just trying to present a small familiar example of such usage. Apologies if I was unclear; I _do_ think it's compelling. The syntactic convenience of being able to bind multiple names in one expression is very nice. (Additionally, if you're doing lots of FP stuff (like me), it's a real pain when you have to introduce those nasty _statements_ into your code, when you'd really like to do things all in one big _expression_. :) ) In general I'm not a fan of implicit conversions or constructors. However one of my goals is to be able to easily/readably move code from using raw variables to use PossiblyUnitinitializedVariables instead. So.. I agree that it would be nice for PossiblyUnitinitializedVariables to be able to be included in existing code with a minimum of fuss. I think, perhaps, that that goal is incompatible with avoiding implicit conversions, though. ... here I like the + or something like it begin.reference_to_uninitialized(). That is I don't mind when users have to be a little more explicit in the dangerous/uncommon case. ~ is Indeed (make the easy/common things easy, and make the hard/uncommon things possible). also interesting, although I think that readability suffers. I'd give up bool conversion and operator! to avoid the need for ~ if that would reasonably solve the muddling issues. But perhaps there would be too many other problems -- I haven't explored this deeply yet. Right; to clarify, I don't think the boolean conversion operator is interfering with the implicit conversion to T. Rather I think each is an instance of implicit conversion, and implicit conversions just don't work well with templates in general, in my experience. I chose '+' and '~' simply because they were the two unary operators that sprang to mind (that aren't named '*'). Personally I have no problem with '*'; C++ has a small finite set of operators, and so you are bound to have to overload the conceptual meanings of some operators if you want to use them for useful syntax sugar. The way I see it, the optional interface using '*' is fine, and I think perhaps what people object to is the conceptual notion of optional being 'pointer-like'. The way I choose to see it, optional is just a special kind of container, which happens to use '*' to get at the value in the container, and the fact that '*' is also used to dereference pointers is a mere coincidence of names. But perhaps other operators (like '+' and '~') or named operations would be more generally acceptable. That's fine. My main point in joining this discussion was to emphasize that I think there ought to be an explicit operation to 'get' the value of an optional (as well as to get the location of raw storage to construct a new value). What those operations are named matters much less than simply their existence. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
On Sun, Aug 31, 2003 at 11:11:10AM -0700, Mat Marcus wrote: --On Sunday, August 31, 2003 1:35 PM -0400 Brian McNamara On Sun, Aug 31, 2003 at 11:59:42PM +0800, Joel de Guzman wrote: It's really strange (and hard to explain) that you have to dereference optionalB. Example: F(tupleA, optionalB, C args) { A a = get1(args); B b = *get2(args); // strange! C c = get3(args); } I don't think it's strange at all; an optionalB is not a B! That doesn't make it a pointer to B! True. See my message of a moment ago, where I adopt the notion that '*' is just an unfortunate coincidence of names, and that any relationship between optional and pointers is mere happenstance. (This all despite the documentation on optional which explicitly describes the relationship; I am merely trying to present another way of looking at it which may be useful.) As another example, FC++ lists support conversion-to-bool There's conversion-to-bool again. I still wonder whether dispensing with this would open the door to implicit conversions. I think no. I should mention in passing that, while in general I think implicit conversions are bad news and should be avoided whenever reasonable, I do think the conversion to bool is an exceptional case, simply because it is already so deeply ingrained in C++ (and C) language/culture. (Fortunately bool has a very narrow interface, so it doesn't get us into too much trouble. Implicit conversions to user-defined types may create arbitrary interface conflicts/conceptual ambiguities, and this is where the real trouble begins.) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: lexicographic: review request?
The point is, that Jan proposed to add something which has a hidden overhead and I'm not sure it's a good idea. Instead of nested if-else-cascades, the user could also write: bool operator( const person lhs, const person rhs ) { return lhs.lastname != rhs.lastname ? lhs.lastname rhs.lastname : lhs.firstname != rhs.firstname ? lhs.firstname rhs.firstname : lhs.age rhs.age; } I am (re)appearing mid-thread, so I may have missed something along the way, but... What's with !=? I think lexicographical orderings are built only on the assumptions of operator, yes? For two objects x and y, if neither x y nor y x is true, then they are in the same equivalence class, but this is not the same thing as equality or inequality. I just want to make sure the template parameter constraints (or macro parameter constraints, as the case may be) are the right ones. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: boost/detail/iterator.hpp update
On Thu, Aug 28, 2003 at 03:05:19PM -0400, David Abrahams wrote: Douglas Gregor [EMAIL PROTECTED] writes: On Thursday 28 August 2003 01:23 pm, David Abrahams wrote: The other possible option would have been to simply not give the user a readable error message. I'm open to opinions that I chose the wrong balance. So we're breaking code in order to produce a better error message? This seems like the wrong trade-off to make, especially because it means it breaks code when users upgrade from VC6 to VC7; but we want them to upgrade! Anyone got a brilliant way to cause vc7 to print the error message? More generally, is there a generally accepted strategy for Boost libraries to attempt to force compilers to emit useful diagnostics? I can imagine there are a number of places where this goes on, and so if anyone has good domain knowledge about coercing compiliers into emitting useful diagnotics, it'd be great to have that written down somewhere (or maybe even turned into some macros possibly). (Kinda a vague idea-specification, I know.) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Do-nothing binary function
On Thu, Aug 28, 2003 at 03:59:19PM +0400, Vladimir Prus wrote: Would it be desirabe to have such class? I'm thinking about struct do_nothing { templateclass T void operator()(const T) const {} templateclass T1, class T2 void operator()(const T1 t1, const T2 t2) const {} // } Someone has already commented WRT bind/lambda. Just FYI (as more support that, yes, it can be generally useful), in FC++ no_op is the (nullary) do-nothing function object, and thus ignore(ignore(no_op)) is the function you've written above. (ignore() is a combinator which takes a function and returns a new function which takes an extra first argument and ignores it.) And another question. Do we have a functional object which always returns true, and can be called with two arguments of any types? Again, some BGL header has such a class in detail namespace. Again, I imagine you do something similar with bind/lambda; in FC++: ignore(ignore(const_(true))) or lambda(X,Y)[ true ] -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: lexicographic: review request?
On Sat, Aug 23, 2003 at 11:21:03AM +0200, Daniel Frey wrote: a) Short-circuiting b) Unnamed functions Jan Langer wrote: bool operator (person const p1, person const p2) { return boost::lexicographic (p1.lastname, p2.lastname, cmp_lower) (p1.firstname, p2.firstname, cmp_lower) (p2.age, p1.age); } The two points listed above are both visible here: Even if there are no persons with the same name, age is accessed. Even worse, it may be a costly method age() and the unaware user creates much worse code than using nested if-else-structures. Also, you might not want to define operator. Sometimes, you just need it in one place, e.g. std::sort( v.begin(), v.end(), /*HERE*/ ); I have imagined another syntax which addresses the issues somewhat: // use boost::lamdba boost::lexicographicperson ( _1.first,cmp_lower )/* see below */ ( _1.last, cmp_lower ) ( bind(T::age,_1) /* use default cmp */ ) ( p1, p2 ) The basic idea is you say lexicographicT to start creating a comparator for T objects, and then use continual argument lists (as in the original example), but where each argument list is either ( lambda(T){ return T.component }, component_comparator ) or ( lambda(T){ return T.component } ) // uses default comparator Finally, when you see an argument list with arguments of type ( T, T ) you know you are done and it is time to compare now. Of course, if you leave off this final argument list, then you get back a function object which can be passed, e.g., to std::sort() as in the example above. The problem (cited see below) is that since operator . isn't overloadable, the boost::lambda expressions like _1.first don't actually exist. Offhand I dunno if C++ in general or Boost in particular offers a nice way to lambda-ify such a member-variable expression. Anyway, just wanted to share some ideas which I think may be a good direction to go to address the issues Daniel raised. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: lexicographic: review request?
On Sat, Aug 23, 2003 at 09:45:42AM -0400, Brian McNamara wrote: // use boost::lamdba boost::lexicographicperson ( _1.first,cmp_lower )/* see below */ ( _1.last, cmp_lower ) ( bind(T::age,_1) /* use default cmp */ ) ( p1, p2 ) ... The problem (cited see below) is that since operator . isn't overloadable, the boost::lambda expressions like _1.first don't actually exist. Offhand I dunno if C++ in general or Boost in particular offers a nice way to lambda-ify such a member-variable expression. I just looked at the boost::lambda documentation and see that they were clever enough to make bind() work on member variables as well as member functions. So the actual syntax would be // Assume p1.first, p1.last, and p1.age() are all legal boost::lexicographicperson ( bind(T::first,_1), cmp_lower ) ( bind(T::last,_1), cmp_lower ) ( bind(T::age,_1) /* use default cmp */ ) // above returns a comparator object; can add ( p1, p2 ) // to call it if desired -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] FC++ integration/future issues (was Some FC++ comments)
On Fri, Aug 15, 2003 at 02:44:20PM -0400, Joel Young wrote: I tried using FC++ a while ago for flexibly expressing and passing around linear algebra pipelines and I found this lack of mutable reference parameters to be highly constraining and insanely frustrating. I wanted to be able to take a reference to a vector as a parameter and return that same vector, mutated, as a return value. I started to hack FC++ to remove the const on the references but after a bit gave up. I should have mentioned as an aside what I did in FC++ for input/output; I made functoids in_stream and out_stream which take pointers to streams as the lhs: cout ^out_stream^ x ^out_stream^ y ^out_stream^ z; // cout x y z; This is one way to functoidize such operations. It's unclear to me if/how useful this is. A question I should I asked before: why were you using FC++ in the first place? (That sounds too accusatory. :) ) What feature(s) motivated its use? Can you give an example of a linear algebra pipeline that you might want to express as a functoid (or something)? I'm afraid I don't have a good enough sense of the domain and what FC++ features you wanted; there may be some useful solution along a completely different path... -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] FC++ integration/future issues (was Some FC++ comments)
On Fri, Aug 15, 2003 at 11:29:49AM +0200, Hartmut Kaiser wrote: You've done a great piece of code! I've tried to understand your articles about the differences between fcpp and boost::lambda/bind/etc. and these (the differences) are now clear to me (to some degree :-). OTOH I know, that there is going on serious work to merge boost::lambda with Phoenix to overcome some well known limitations of both and to avoid having two similar libraries in boost. Wouldn't it be nice, if after this merger we'd get _one_ library lambda + phoenix + fcpp? Or isn't this possible at all? It may well be possible. I have had a little bit of discussions with Jaakko and Joel (off-list) about this. I have not had the opportunity to think deeply about it though; it is unclear to me if the FC++ implicit assumption of 'value semantics' (FC++ doesn't allow (mutable) reference parameters) will throw a wrench in the works. It is also unclear to me how much rework such an integration might necessitate. (I am very pleased to say that integrating/reusing other (small) portions of boost in FC++'s implementation went very smoothly.) This begs another important (at least to me :) ) question about FC++ and Boost. Can FC++ be accepted into Boost prior to any integration with lambda/phoenix/bind? I hope that the answer is yes, for a few reasons: - It will give the boost user/developer community the opportunity to gain some experience with FC++, to see better what its merits and demerits are. - It will provide an opportunity to see how well/badly the various libraries interoperate now (as separate libraries), which may expose more of the important integration issues. - It means less time for FC++ to languish in the current state it's in, where I'm doing work to `boostify' and improve it, but no one is using it. I'm still a newbie to this community, so I have no idea what the opinion of the `ruling committee' is (or will be) on these issues. But it would be helpful to me to know (at least to have a better idea where my immediate future lies). So if anyone has opinions or constructive thoughts on this issue, I'd like to hear them. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] FC++ integration/future issues (was Some FC++ comments)
On Fri, Aug 15, 2003 at 02:44:20PM -0400, Joel Young wrote: From: Brian McNamara [EMAIL PROTECTED] to think deeply about it though; it is unclear to me if the FC++ implicit assumption of 'value semantics' (FC++ doesn't allow (mutable) reference parameters) will throw a wrench in the works. It is also I tried using FC++ a while ago for flexibly expressing and passing around linear algebra pipelines and I found this lack of mutable reference parameters to be highly constraining and insanely frustrating. I wanted to be able to take a reference to a vector as a parameter and return that same vector, mutated, as a return value. I started to hack FC++ to remove the const on the references but after a bit gave up. Yes... square peg, round hole. (You can use pointers, but this sometimes turns existing code into mess of s, *s, and compose(dereference)s.) An open question (which someone on the list suggested) is whether monads will provide a convenient interface to bring mutation cleanly back into the mix. That's what happens, e.g., in Haskell. But the monad stuff in FC++ is really new (and monads are still pretty new to me), so it isn't yet clear if/how this may address the issue. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Some FC++ comments
On Wed, Aug 13, 2003 at 11:27:08PM -0400, Brian McNamara wrote: I've been working on a draft of the documentation for the boostified version of FC++, and it's finally reached a good enough state to be potentially useful to you-all. Check out http://www.cc.gatech.edu/~yannis/fc++/boostpaper.pdf (I'll make it available in a more convenient format when I figure out how to work latex2html.) Got it working: http://www.cc.gatech.edu/~yannis/fc++/boostpaper/ is the HTML version. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Some FC++ comments
On Mon, Jul 28, 2003 at 03:16:52PM -0400, Brian McNamara wrote: functional programming. Over the next couple of weeks I will make documentation of the boostified version of FC++ that's aimed at a C++ audience. Hopefully that will help. I've been working on a draft of the documentation for the boostified version of FC++, and it's finally reached a good enough state to be potentially useful to you-all. Check out http://www.cc.gatech.edu/~yannis/fc++/boostpaper.pdf (I'll make it available in a more convenient format when I figure out how to work latex2html.) I'm also working on improving the example files, and using some of the other constructive comments I've received. Any and all feedback is appreciated. As a reminder, here is where to find the 'boost' version of the library: I have posted the first boostified version of FC++ to the YahooGroups files section; it is called fcpp. http://groups.yahoo.com/group/boost/files/ -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] bind/lambda - unsupported use case?
On Mon, Aug 11, 2003 at 10:54:40PM -0500, Aleksey Gurtovoy wrote: Gary Powell wrote: Consider the following snippet: void show_warning( message_dialog const, user_message ); void post_command( boost::functionvoid() ); int main() { boost::functionvoid( user_message ) f( bind( post_command , ( bind( show_warning, message_dialog(), _1 ) ) // what goes here? ) ); } Could we make it work, somehow? Offers of a hand-written function performing the composition are not accepted :) I'm a bit confused by your request, Do you want both fns to be called? Nope. Please see http://article.gmane.org/gmane.comp.lib.boost.devel/23466 for the semantics clarification. Basically, I want the whole bind expression to return an unary function object which, when invoked, will use the argument to construct a nested nullary function object: bind( show_warning, message_dialog(), arg ) and pass it as an argument to 'post_command'. Does it make more sense now? I can't speak for bind/lambda, although I imagine there must be a way, probably involving delaying the evaluation of _1 for one step. Using FC++, it would be using fcpp::fun1; using fcpp::lambda; using fcpp::ptr_to_fun; fun1user_message,void f = lambda(X)[ ptr_to_fun(post_command)[ lambda()[ ptr_to_fun(show_warning)[ message_dialog(), X ] ] ] ]; The explicit lambda notation makes it easier to (mentally and syntactically) sort out functions like these where the placeholder variables are bound by a lambda (bind expression) other than the innermost one. (The calls to to ptr_to_fun above are necessary only to promote the function pointers into FC++ functoids.) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Some FC++ comments
On Mon, Jul 28, 2003 at 05:38:01PM +0200, Miroslav Silovic wrote: Well, nobody posted anything definite on FC++, which is a pity, since I find this library potentially very useful. Here are some comments. Caveat: I haven't extensively used the library, but I have quite a bit of experience with functional programming. I won't comment on the naming scheme or the docs - that was covered in the original post. I expect the docs are a big issue (as David Abrahams commented); most of the docs on the web site are aimed at an audience of researchers in functional programming. Over the next couple of weeks I will make documentation of the boostified version of FC++ that's aimed at a C++ audience. Hopefully that will help. First, FC++ duplicates Boost::bind with its currying. Are there any plans to reuse the Boost code for this? Boost::bind seems more powerful and general, in that it can take functions with any arity and bind any argument(s). (Perhaps again this is the fault of the documentation being poor.) FC++ full functoids are fully curryable by default. The prefix and underscore styles of currying are the preferred ways to do things. See http://www.cc.gatech.edu/~yannis/fc++/currying.html for some examples. You can do the same things with boost::bind (or boost::lambda, or fcpp::lambda) too. I am talking to Jaakko and Joel (off-list) about the boost infrastructure there to ensure that, at the least, FC++ interoperates with the boost stuff, and at best, that much of the infrastructure can be reused. I think FC++ could profit from pluggable memory management, perhaps as a policy parameter. In particular, zonal allocation could allow one to do away with refcounting for calculate-and-exit trips into FC++ code (where you just carve small chunks from a list of memory pages, then nuke the entire block once you're done with the calculation). This sounds like an interesting extension, though I don't know that I would be the right person to implement it. :) One interesting Haskell feature that FC++ doesn't have are monadic arrays. Are there any plans to communicate with writable STL containers using monads? The monad stuff is very new; this sound like a terrific idea. I'll put it on my to-do list. I also couldn't find any reference to tuples in the docs. Is there any support for them? (This could be a low-hanging fruit, since Boost already has tuples). There is nothing (other than std::pair and fcpp::mk_pair). I don't see any reason boost tuples couldn't be used in fc++ code, though. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Preliminary submission: FC++
Based on David's suggestion, I'll try to briefly define all the terms I've used in my earlier post. Brian McNamara [EMAIL PROTECTED] writes: I have posted the first boostified version of FC++ to the YahooGroups files section; it is called fcpp. http://groups.yahoo.com/group/boost/files/ -- Background -- FC++ is a library for functional programming. In FC++ we program with functoids (classes which define operator() and obey certain other conventions). The library features include: In the latest version of the library, we discriminate among a few kinds of functoids: - A basic functoid is a class which defines a (possibly templated) operator() function, as well as a templated sig member structure. (The sig in FC++ is analogous to the result structure for the proposed result_of construct for computing result types.) - Most functoids are direct functoids, as they call their implementation function directly. In contrast, indirect functoids use dynamic dispatch (virtual function call), in order to create function variables. FC++ indirect functoids are almost completely analogous to boost::function objects: fcpp::fun2int,int,int f = fcpp::plus; // select (int,int)-int f(3,2); // yields 5 f = fcpp::minus; f(3,2); // yields 1 - Indirect functoids must always be monomorphic (non-templated). That is, given an indirect functoid (like f above), it expects a fixed set of arguments types (e.g. ints). - Direct functoids can be polymorphic (templated). For example, fcpp::plus is polymorphic: plus(3,3);// yields int 6 plus(2.2,2.2);// yields double 4.4 plus(s,s);// if s is std::string(foo), yields foofoo Unlike indirect functoids, you can't create variable direct functoids. The type of the object fcpp::plus is fcpp::plus_type. - Full functoids are basic functoids which have been wrapped by the fullN wrapper class. Full functoids add extra FC++ functionality, like currying, lambda awareness, and infix syntax (see below). (Note that the FP community uses polymorphism to mean templates, whereas the OO community uses the term to mean dynamic dispatch. An unfortunate overloading of terms. As you can see, we use the FP definition throughout the FC++ documentation.) - higher order, polymorphic (template) functions (direct functoids) Higher order functions are functions which take other functions as arguments or return functions as results. In FC++, since we represent polymorphic (template) functions as direct functoids (which, unlike C++ function templates, are C++ objects which can be passed around as parameters), we can implement functions which are simultaneously higher-order and polymorphic. An example is compose: // compose(f,g)(args) = f( g(args) ) If add_self is this polymorphic function: // add_self(x) = x + x Then we can write compose( add_self, add_self )( 3 ); // yields 12 compose( add_self, add_self )( s ); // yields foofoofoofoo (s as above) (This feat was a novelty when FC++ was new, but is becoming more mainstream in C++ now, owing to the more general knowledge of techniques along the lines of result_of, which enables the result type of template functions to be named.) - lazy lists More generally, a number of data structures and functions which employ lazy evaluation. As an example, fcpp::listint l = enum_from(1); results in l being the infinite list of integers [1,2,3...]. The elements in the list are not computed until they are demanded (lazy evaluation). - library of useful functions, combinators, and monads (mostly mimicking the Standard Library of the language Haskell) Combinators are higher-order functions. (Definitions of the term combinator seem to vary from community to community.) Monads cannot be defined in a sentence or two, so I won't try. (Much of FC++ was designed to imitate Haskell, which is kinda the cutting edge, mainstream pure functional language.) - currying Given some 3-argument function f: f(x,y,z) // normal call f(x,y)// new function g, where g(z)=f(x,y,z) f(x) // new function g, where g(y,z)=f(x,y,z) f(x,_,z) // new function g, where g(y)=f(x,y,z) etc. FC++ full functoids exhibit built-in currying. This is basically a terser syntax for what boost::bind does. - infix function syntax Given a two-argument function f: x ^f^ y // same as f(x,y) This is syntax sugar. Often things like x ^plus^ 3 are easier to read than plus(3,x) because it seems more natural. (Haskell uses ` instead of ^) Of course, if f is a 3-arg full functoid, then x ^f^ y// new function g, where g(z)=f(x,y,z) - dynamically bound functions (indirect functoids) Described above. - effect combinators Suppose write_log is a function which takes a string and writes it to a log file, and do_foo is a function that does something
[boost] Preliminary submission: FC++
I have posted the first boostified version of FC++ to the YahooGroups files section; it is called fcpp. http://groups.yahoo.com/group/boost/files/ -- Background -- FC++ is a library for functional programming. In FC++ we program with functoids (classes which define operator() and obey certain other conventions). The library features include: - higher order, polymorphic (template) functions (direct functoids) - lazy lists - library of useful functions, combinators, and monads (mostly mimicking the Standard Library of the language Haskell) - currying - infix function syntax - dynamically bound functions (indirect functoids) - effect combinators - interfaces to STL via iterators - ways to transform normal C++ functions/methods into functoids - a lambda sublanguage, with syntax for lambda, let, letrec, do-notation, and monad comprehensions Much of the documentation for FC++ can be found at http://www.cc.gatech.edu/~yannis/fc++/ and the rest appears linked from http://www.cc.gatech.edu/~yannis/fc++/New1.5/ (which has a pre-release of the upcoming version (v1.5), currently out for beta-testing). The upcoming release comprises about 9000 lines of code and compiles on a number of different compilers (g++, Comeau, Intel, MSVC++). Note that all the documentation on our web site uses FC++ identifiers rather than Boost FC++ identifiers. (See below.) --- Boostifying --- I have asked a few questions on the boost mailing list about what would need to be done to FC++ to boostify it. I received a number of useful comments. Here are the things that have changed from FC++ to the submission I just posted to the YahooGroups page (I shall henceforth refer to that submission as Boost FC++): - Changed naming convention of all types/objects/functions in the public interface to conform with Boost naming conventions. (e.g. enumFrom is now enum_from; EnumFrom is enum_from_type.) - Reused boost libraries as appropriate. Specifically, I have reused these items from boost: - shared_ptr - addressof - intrusive_ptr- noncopyable - is_base_and_derived - type_with_alignment - is_convertible - alignment_of (I compiled against boost_1_30_0.) I should probably also reuse some of mpl, but I have not yet studied that library enough to use it. - Changed file names so that headers have .hpp file extensions, and clients have .cpp extensions. - Moved library into namespace boost (::boost::fcpp). - Boost FC++ full functoids meet the demands of the proposed result_of template, for forward compatibility with boost/std library template adaptables. - The code posted to YahooGroups has been tested on g++-3.1.1 for Solaris and on icc7 for linux. Prior versions of FC++ have also been tested on Comeau and VC++7.1. I expect that this code should be reasonably portable. - Known future work - There are still a few issues which need tending to which I am aware of. They are: - Documentation. There are a number of research papers and tutorials about FC++ on our web site (mentioned in the Background section, above). However there is not yet good documentation for Boost FC++. I need to create a document which (1) describes everything in one place, (2) is aimed at a C++ audience, and (3) uses the new Boost FC++ identifiers. Additionally there will need to be a bit of documentation describing how Boost FC++ relates to the rest of Boost (especially lambda, bind, and function). - The header files define objects (in an unnamed namespace) by default. (Read about FCPP_DEFER_DEFINITIONS at http://www.cc.gatech.edu/~yannis/fc++/FC++.1.4/changes.html for a short description.) I am not sure if this behavior is objectionable or not. Ask me more if you're confused. - There is probably a way to adapt some functoids which work on boost::fcpp::list objects so that they can read arbitrary containers (really, iterator ranges). I should add a little more support for using Boost FC++ functoids on std:: data structures. - Copyright notices. The header files contain the FC++ copyright notice; the clients (.cpp) contain none. I've heard a bit about a standard Boost license being developed; perhaps by the time (if/when) FC++ gets added, that will be complete. In any case, the boost copyright/licensing issues as I understand them are all acceptable to Yannis and me (the FC++ authors). -- Refinement -- FC++ is a big library and I expect there will be a number of things needing refinement to make FC++ acceptable to Boost. I hope this message will start that discussion. Thanks, Brian -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: functors for taking apart std::pair?
On Sat, Jul 12, 2003 at 01:21:49PM +0100, Andy Sawyer wrote: There's a third form I've also found useful on occasion: struct selector1st { templatetypename Pair const typename Pair::first_type operator()( const Pair a ) const { return a.first; } }; Which has the advantage of not needing to specify _any_ type at the call site: for_each( map.begin(), map.end(), selector1st() ); And again, is not limited to use with std::pair. However, it's utility is limited by not inheriting from std::unary_function. If and when I get FC++ ( http://www.cc.gatech.edu/~yannis/fc++/ ) into Boost, FC++ has the same kind of selectors you've shown above (named fst and snd, as in Haskell). Whereas these function objects also cannot be used with STL algorithms requiring adaptables (for the reason you mention above), it can be used with the analogous algorithms in FC++, since the FC++ infrastructure enables return-type-deduction for template function objects. I've been working on boostifying FC++ this past week (adopting naming conventions, reusing Boost code, etc.) and will hopefully get a Boost-ful FC++ version up for review in the next two weeks or so. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Interest in FC++?
On Thu, Jun 26, 2003 at 01:36:58PM +0200, Dirk Gerrits wrote: Brian McNamara wrote: - Reuse: FC++ reinvents a number of Boost's libraries in its implementation, such as smart pointers and metaprogramming tricks. A Boost version of FC++ should reuse Boost libraries for this. I agree. While FC++ probably would bring in a lot of new stuff, there is *considerable* overlap with Boost's current libraries. On the function side there's: bind, mem_fn, compose, function, functional, and of course lambda. And then there are smart_ptr, mpl, and preprocessor. Reusing will probably make the implementation a lot cleaner, potentially more robust, and ... I have taken a closer look at what is and is not reusable. Here's what I've come up with: Reusable: smart_ptr: boost::shared_ptr and boost::intrusive_ptr seem to do exactly the same thing as fcpp::Ref and fcpp::IRef mpl: it looks like some things here, like if_ and find can be reused. There may be more, too. type_traits: boost::is_base_and_derived replaces fcpp::Inherits concept_check: it may be possible to re-use some of the machinery here for reporting custom error messages. Non-reusable: bind, mem_fn, compose, function, functional, lambda: (It looks like much of compose and functional is subsumed by bind/lambda anyway.) FC++ indirect functoids are similar to boost::function objects. fcpp::ptr_to_fun is similar to bind and mem_fn. fcpp::lambda is somewhat similar to boost::lambda. In each of these cases, however, none of the boost stuff can be reused in FC++, as FC++ uses/requires so-called full functoids to work. FC++ must necessarily duplicate these, owing to the fundamental differences in the library architecture. - Naming conventions: FC++ uses a naming convention other than Boost's (including systematically using capital letters in identifiers). From what I have been able to tell in such a short time, the 'camel hump notation' is mostly used in the implementation and only slightely so in the interface. For example, things like Fun0, Fun0Impl, ... are no problem because you want to reuse Boost's facilities for these anyway. And the functiods are already 'properly' named in lowercase. Of course, there is some work to be done here, but I don't think it would be a big problem, do you? It's much more insidious than this. There are a number of types of names which use captial letters visible in the client interface to the FC++ library. Here are the major categories of examples that spring to mind: Functoids. Every functoid (like id, map, enumFrom, compose) is an instance of a corresponding data type which begins with a capital letter (Id, Map, EnumFrom, Compose). Being able to name the type of any functoid is important. Data types. Classes like List and Maybe have names starting with capital letters. Signature information. We use names like Arg1Type, Arg2Type, and ResultType as typedefs for functoid signatures. LEType computer. Lambda expressions' types are named by the LEType computer, which uses some all-caps names like LAM, LV, CALL, etc. While some of these names are ones that I have made up, and thus can be changed on a whim to lowercase versions, there are still two classes of naming issues which I hesitate to change: Haskell names. Many functoids (like enumFromTo, takeWhile, zipWith, etc.) and datatypes (like Maybe) have the exact same names and behavior as their counterparts in the Haskell programming language. I've named them this way to cater to programmers coming from a Haskell background, and am hesitant to change them. Functoid types. The obvious alternative to naming the type of a functoid with a leading capital letter (e.g. compose has type Compose) is to add a suffix (e.g. make it so compose has type compose_type). Functoid type names are used a lot, though, and I am not fond of the idea of making the type names longer than the names of the instances. I dunno if either of the examples above constitutes reason enough to bend the rules with regards to naming conventions, but I want to ask. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Interest in FC++?
I would like to see if there is interest in incorporating the FC++ library into Boost. FC++ is a library for functional programming. In FC++ we program with functoids (classes which define operator() and obey certain other conventions). The library features include: - higher order, polymorphic (template) functions (direct functoids) - lazy lists - library of useful functions, combinators, and monads (mostly mimicking the Standard Library of the language Haskell) - currying - infix function syntax - dynamically bound functions (indirect functoids) - effect combinators - interfaces to STL via iterators - ways to transform normal C++ functions/methods into functoids - reference-counted pointers - a lambda sublanguage, with syntax for lambda, let, letrec, do-notation, and monad comprehensions Much of the documentation for FC++ can be found at http://www.cc.gatech.edu/~yannis/fc++/ and the rest appears linked from http://www.cc.gatech.edu/~yannis/fc++/New1.5/ (which has a pre-release of the upcoming version (v1.5), currently out for beta-testing). The upcoming release comprises about 9000 lines of code and compiles on a number of different compilers (g++, Comeau, Intel, MSVC++). I have received mail a couple times in the past few years expressing interest in adding FC++ to Boost. However until now, I have been unwilling (1) to do the work to Boostify the library, and (2) to lose any creative control to tinker with things on my own whims. I think now the library has finally settled down, and all the major features I have wanted to add are included in the upcoming release (v1.5) of FC++. And I have some free time this summer to do the work. Which is why I'm now finally talking to you-all. So I am sending this mail to see: (1) If there is still interest in adding FC++ to Boost, and (2) If there is interest, what-all needs to be changed with the FC++ library to make it meet the standards of Boost. With regards to (1), I hope yes, but the Boost Lambda Library has a bit of conceptual overlap with FC++, so I can imagine this issue being potentially contentious. (FC++ and Lambda ostensibly provide much of the same kinds of functionality, but while there is overlap, each library does a lot of its own thing too. I (and Jaakko too, probably) can say more about this if necessary.) With regards to (2), I have been reading all the stuff on the Boost web site regarding submissions, and so I am aware of a number of issues, including: - Reuse: FC++ reinvents a number of Boost's libraries in its implementation, such as smart pointers and metaprogramming tricks. A Boost version of FC++ should reuse Boost libraries for this. - Documentation: as of yet, there is no good singular users guide for FC++ aimed at the audience of C++ programmers; I'd need to write one. - Naming conventions: FC++ uses a naming convention other than Boost's (including systematically using capital letters in identifiers). But at this point I'm probably already getting ahead of myself. So I'll stop talking and ask people to comment with regards to interest in FC++. Thanks, Brian -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost