A Read-Eval-Print-Loop makes functional programing very proficient. This notebook demonstrates it. If you are new to functional programming, it is recommended to view it as a slideshow.
FunctionalPlus is a Functional Programming Library for C++. Some docs:
First, include fplus, which is a header only library.
#pragma cling add_include_path("../external/FunctionalPlus/include")
#include <fplus/fplus.hpp>
Let's try to read some text.
Note: If you do not end your line with a ";", cling will output the result of the last computation
using namespace std;
fplus::read_text_file("data/if.txt") // no ";"
Wow, where is our text ? fplus::read_text_file did not return a string!
The reason for this is that fplus is a functional library, so that fplus::read_text_file(filename) does not perform the side effect : instead it returns a function which you need to invoke in order to perform the side effect.
Let's try again, and invoke the function : see the () at the end below
auto poem = fplus::read_text_file("data/if.txt")();
poem
// Let's try to split some lines
const auto lines = fplus::split_lines(poem, false);
Wow, I must have typed something wrong. Let's lookup split_lines
in the API (search for "split_lines"), or on sourcegraph
// Ha, the order of the params was wrong. Let's try again
const auto lines = fplus::split_lines(false, poem);
lines
Much better!
Let's try to modify this poem, by applying a function that changes all letter of each word to lowercase, except the first letter of each word.
// This is the function we want to apply to each word
std::string capitalize_first_letter(const std::string & word) {
auto result = fplus::to_lower_case(word);
result[0] = toupper(result[0]);
return result;
}
capitalize_first_letter("hello")
const std::string first_line = lines[0];
const auto words = fplus::split<std::string>(' ', false, first_line);
words
How to transform all these words using capitalize_first_letter
?
We will be using fplus::transform
: it applies a given transformation to all the elements of a container.
See it's documentation at http://www.editgym.com/fplus-api-search/
auto words_transformed = fplus::transform(capitalize_first_letter, words);
words_transformed
Then, we need to join our transformed words:
auto first_line_transformed = fplus::join(std::string(" "), words_transformed);
first_line_transformed
So, the final result for the first line could be written:
fplus::join( std::string(" "),
fplus::transform(capitalize_first_letter,
fplus::split<std::string>(' ', false, first_line)
)
)
// See how our lines are going towards the right of the screen: this is because
// we are composing three functions calls: efficient, but not very readable
apply_by_words
is a higher order function that will transform a function f into another function
that will apply f word by word.
// Here we are composing three functions in a much more readable way
// We can even transform with any other function (to_upper, etc)!
auto apply_by_words = [](auto f) {
return fplus::fwd::compose(
fplus::fwd::split(' ', false),
fplus::fwd::transform(f),
fplus::fwd::join(std::string(" "))
);
};;
fplus::fwd
namespace contains partially curried version of the functions. This is useful for composition. See doc here// Now let's instantiate apply_by_words with capitalize_first_letter
// cap_words will be a lambda function of type : string -> string
auto cap_words = apply_by_words(capitalize_first_letter);
// And let's try it
cap_words(lines[0])
apply_by_lines
is another higher order function that will transform a function f into another function
that will apply f line by line.
// Let's continue
auto apply_by_lines = [](auto f) {
return fplus::fwd::compose(
fplus::fwd::split_lines(false),
fplus::fwd::transform(f),
fplus::fwd::join(std::string("\n"))
);
};; // the double ;; is voluntary here (bug in cling !)
auto cap_text = apply_by_lines(cap_words);;
// And now let's apply this to the complete poem
cap_text(poem)
fplus::interact
is a higher order function that transforms a function of type string -> string
into a program that read it's output from stdin and writes it output to stdout.
auto prog = fplus::interact(cap_text);
Let's examine prog:
prog
So, prog
is itself a lambda. In order to construct a program, we need to call it inside main, like so:
int main() {
prog();
}
So, a full program that would apply our transformation to stdin and write to stdout could be written as below. (beware, this code can not be used inside this page, you need to copy / paste it into a cpp file).
#include <fplus/fplus.hpp>
std::string capitalize_first_letter(const std::string & word) {
auto result = fplus::to_lower_case(word);
result[0] = toupper(result[0]);
return result;
}
int main()
{
auto apply_by_words = [](auto f) {
return fplus::fwd::compose(
fplus::fwd::split(' ', false),
fplus::fwd::transform(f),
fplus::fwd::join(std::string(" "))
);
};
auto apply_by_lines = [](auto f) {
return fplus::fwd::compose(
fplus::fwd::split_lines(false),
fplus::fwd::transform(f),
fplus::fwd::join(std::string("\n"))
);
};
auto cap_words = apply_by_words(capitalize_first_letter);
auto cap_text = apply_by_lines(cap_words);
auto prog = fplus::interact(cap_text);
prog();
}