Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map/fold operators (in c++)

I am writing library which can do map/fold operations on ranges. I need to do these with operators. I am not very familiar with functional programming and I've tentatively selected * for map and || for fold. So to find (brute force algorithm) maximum of cos(x) in interval: 8 < x < 9:

double maximum = ro::range(8, 9, 0.01) * std::cos  || std::max;

In above, ro::range can be replaced with any STL container.

I don't want to be different if there is any convention for map/fold operators. My question is: is there a math notation or does any language uses operators for map/fold?

** EDIT **

For those who asked, below is small demo of what RO currently can do. scc is small utility which can evaluate C++ snippets.

// Can print ranges, container, tuples, etc directly (vint is vector<int>) :
scc 'vint V{1,2,3};  V'
{1,2,3}

// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}

// Assign 42 to [2..5)
scc 'vint V=range(0,9);   range(V/2, V/5) = 42;  V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}


// concatenate vector of strings ('add' is shotcut for std::plus<T>()):
scc 'vstr V{"aaa", "bb", "cccc"};  V || add'
aaabbcccc

// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"};  V * size ||  (_1+_2)'
9

// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99];  range(s) = "abc";  (range(s) << "XYZ") - "bc"'
aXYZ


// Remove non alpha-num characters and convert to upper case
scc '(range("abc-123, xyz/") | isalnum) * toupper'
ABC123XYZ


// Hide phone number:
scc "str S=\"John Q Public  (650)1234567\";  S|isdigit='X';  S"
John Q Public  (XXX)XXXXXXX
like image 917
Leonid Volnitsky Avatar asked Dec 10 '12 05:12

Leonid Volnitsky


1 Answers

This is really more a comment than a true answer, but it's too long to fit in a comment.

At least if my memory for the terminology serves correctly, map is essentially std::transform, and fold is std::accumulate. Assuming that's correct, I think trying to write your own would be ill-advised at best.

If you want to use map/fold style semantics, you could do something like this:

std::transform(std::begin(sto), std::end(sto), ::cos);
double maximum = *std::max_element(std::begin(sto), std::end(sto));

Although std::accumulate is more like a general-purpose fold, std::max_element is basically a fold(..., max); If you prefer a single operation, you could do something like:

double maximum = *(std::max_element(std::begin(sto), std::end(sto),
    [](double a, double b) { return cos(a) < cos(b); });

I urge you to reconsider overloading operators for this purpose. Either example I've given above should be clear to almost any reasonable C++ programmer. The example you've given will be utterly opaque to most.

On a more general level, I'd urge extreme caution when overloading operators. Operator overloading is great when used correctly -- being able to overload operators for things like arbitrary precision integers, matrices, complex numbers, etc., renders code using those types much more readable and understandable than code without overloaded operators.

Unfortunately, when you use operators in unexpected ways, precisely the opposite is true -- and these uses are certainly extremely unexpected -- in fact, well into the range of "quite surprising". There might be question (but at least a little justification) if these operators were well understood in specific areas, but contrary to other uses in C++. In this case, however, you seem to be inventing a notation "out of whole cloth" -- I'm not aware of anybody using any operator C++ supports overloading to mean either fold or map (nor anything visually similar or analogous in any other way). In short, using overloading this way is a poor and unjustified idea.

like image 71
Jerry Coffin Avatar answered Sep 21 '22 03:09

Jerry Coffin