This document summarizes the changes since the previous release of the FC++ library. (As always, see the FC++ web site for the latest.)
lambda
, so you can
create anonymous functions on-the-fly. FC++'s lambda has a tiny
functional sublanguage with features like
letrec
, do
-notation for monads,
and comprehensions. See "FC++
Lambda" for more details.f(x,y)
" you can also say "x ^f^
y
". See "New infix
syntax" for details.FullN
wrappers add all the
extra FC++ functoid functionality (currying, lambda-awareness,
smartness, infix syntax) to existing functoids. See "Full
functoids" for details.funify
,
of
, thunkFuncToFunc
, hCurry
,
hUncurry
, delete_
,
outStream
, and inStream
.
(operator.h
and prelude.h
)ptr_to_fun
is now a functoidptr_to_fun
is used on an instance method, the
resulting functoid can now accept a smart pointer (e.g.
Ref
) as the first (receiver) argumentprelude.h
(like
ignore
) now work properly, regardless of the arity of the
functoids passed in as an argument, thanks to "smartness".Ref
and IRef
classes now have
operator==
and operator!=
; this fixes minor
bugs that can arise from implicit conversions to pointers.FCPP_1_3_LIST_IMPL
. The old implementation technically has
order-of-initialization (OOI) bugs which may cause programs to coredump,
but in practice, these are easy to work around. If you are using FC++
in a setting where you need very high performance but are having trouble
getting the old implementation working without crashes, email Brian and
he'll show you how to get your code working fast.)
id
, noOp
, before
,
after
, uncurry
, duplicate
,
ignore
, constructN
and newN
.
Also, the Maybe
type from Haskell has been added.delay
and force
(list.h).dereference
and addressOf
(operator.h).F::result_type
, etc.).Sig
structures in a way that enables a new class of
combinators to be written (compose
, before
,
after
, and uncurry
can
discover whether or not their arguments are zero-arg functoids, and can
act accordingly). Now rather than referring to F::Sig::ResultType
for a
zero-arg functoid of type F
, you should refer to
F::Sig<>::ResultType
or just
RT<F>::ResultType
instead.FCPP_DEFER_DEFINITIONS
will prevent the .h
files from creating definitions of the library functoids; the
declarations remain, but you must separately compile
definitions.cc
and link it in. This is useful for
applications using FC++ in multiple translation units--it prevents each
TU from having its own (redundant) copy of each of the library functoid
objects in favor of a single "master" copy.ptr_to_fun
overloads for const member functions.binder1and2of2
,
stlN
, and cat
.const
data members.Compose0
, as Compose
now
subsumes it.flip
so it returns a curryable result.length
)
so that they don't complain if you pass them an OddList
instead of a List
.const_
, and_
, and
or_
to corresponding functoids.
Whenever a functoid's name clashes with a C++ keyword, we add a trailing
underscore.enumFrom()
FunN
classes (shouldn't be necessary, but without it,
exposes a compiler bug on at least one platform) The run-time performance of the library has been drastically improved. This has all been done "under the hood"; the interface to the library has barely changed. The main sources for the improvements are
List
sThe library now works with both g++2.95.2 and g++3.0. It should also work with any other standard-conforming C++ compiler. See this page for details.
There are now many more example files.
Fun3
class has finally been implemented. Like
Fun2
it supports automatic currying.IRef
(the intrusive version of
Ref
) has been added.ListIterator
now supports
operator->
.FCPP_DEBUG
turns on extra run-time checking
so that if you try to head()
or tail()
an
empty list, an exception (of type fcpp_exception
) is
thrown. Without the flag, there is no run-time check (and the code
fails un-gracefully).FCPP_SAFE_LIST
adds a destructor to the
List
class which ensures that list nodes are destroyed
iteratively. The reference-counting in list nodes
(Cache
s) works recursively, and as a result, can blow the
stack for large lists. In other words,
{ List<int> l = enumFromTo(1,200000); length(l); // force evaluation of the list (actually create nodes) } // Boom! Recursion with a call-depth of 200000.is likely to "blow up" unless the
FCPP_SAFE_LIST
flag is
set. Setting this flag degrades the overall performance of lists,
however. In order to ensure that a specific instance of a
list doesn't blow up, you can always just iteratively destroy that
list, as in
{ List<int> l = enumFromTo(1,200000); length(l); // force evaluation of the list (actually create nodes) while(l) l = tail(l); // iteratively destroys list } // no problem here
using namespace fcpp;at the end of
prelude.h
. As a result, you should add this
yourself to your .cc
files that use the library.
cat
has changed slightly. The first
parameter must be a list, but the second parameter can be either a list
or a function that returns a list. (It used to be that both parameters
could be either lists or functions.)Sig
s of Plus
, Minus
,
etc., now better reflect the true signatures of those functoids.OneElement
(one_element
) has been removed.
You should use cons(x,NIL)
instead.Nil<T>
has been removed. You should just use NIL
instead, unless type inference fails, in which case you can always use
List<T>()
.FCPP_LEAK
turns off the reference counting in
the IRef
class. As a result, the application leaks
away memory (but might run faster).FCPP_TEMPLATE_ENUM
makes enumFrom()
and
enumFromTo()
be template functoids rather than just
functoids that work on int
s. They really probably should be
template functoids, however g++2.95.2 seems to generate slow code for
them when they templated, for no obvious reason. (g++3 generates fast
code regardless of whether the functoids are templated or not.)FCPP_OOI_DEBUG
turns on some debugging output for the
creation of global objects (that may be initialized before
main()
). This helped us debug order-of-initialization
errors.OddList
s, Reuser
s, and iteration. The old
implementations of many of the functions are still there, enclosed in
#ifdef FCPP_SIMPLE_LIST
s. We've kept the old
implementations in the file mostly for instructional value (they
illustrate the simplest ways to create functoids, and also help show
the changes necessary to create optimized versions of functoids).The library now compiles with the "-pedantic -ansi" options for g++, which means it will probably compile with more other compilers now, too. The previous release had a number of "typename" problems; C++ requires the "typename" keyword to appear in lots of places inside templates.
minus(3,2); // yields 1 minus(3); // yields a new function f, where f(x) = 3-x minus(3,_); // same as above minus(_,2); // yields a new function f, where f(x) = x-2This is accomplished by the
CurryableN
classes, which
serve as wrappers around normal functions. The function
makeCurryable()
turns an uncurryable function into an
automatically curryable version. See http://www.cs.umass.edu/~yannis/fc++/currying.html
for more info.fcpp
. However, bugs in the g++2.95.2 compiler force us to keep
part of the library in the global namespace. If you have a working
compiler, use the compiler option -DFCPP_USE_NAMESPACE to have the whole
library be in the namespace. There's a
using namespace fcpp;at the bottom of
prelude.h
, which dumps it all
into the global namespace anyway. We've done that for backwards
compatibility (you can drop in the new library and your old code should
still work without changes), but feel free to remove it (we certainly
will, in a future revision).FunN
s). For example,
Fun1<int,int,int> f = fcpp::plus; Fun1<double,double,double> g = fcpp::plus;both "do the right thing".
ptr_to_fun()
, monomorphizeN()
,
CurryableN
, etc.) work for all sets of functions with 0-3
arguments. (Previous versions of FC++ had spotty support.)List
class has been completely re-implemented.
The old version had a number of problems (the major ones being that (1)
it was too eager (not lazy enough) in a number of cases, and (2) that
functions like cons
had un-intuitive interfaces) that have
now been solved. In our limited tests, the new List
seems
to perform comparably with the old, but let us know if you notice a
speed difference.List::WrappedType
has been renamed to
List::ElementType
. The new name makes more sense,
especially in papers/tutorials.list_until
has been renamed
listUntil
(consistent with
naming convention of other list functions).