{"id":229,"date":"2024-05-21T18:09:00","date_gmt":"2024-05-21T18:09:00","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=229"},"modified":"2024-07-27T08:52:20","modified_gmt":"2024-07-27T08:52:20","slug":"functional-programming-in-c","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/05\/21\/functional-programming-in-c\/","title":{"rendered":"Functional Programming in C++"},"content":{"rendered":"\n<p>I remember <a href=\"https:\/\/en.wikipedia.org\/wiki\/Functional_programming\">functional programming<\/a>\n being a niche aspect of computing science.\nSoftware engineering didn&#8217;t consider it at all.\nNow you can find discussion and books about using it in any major programming language.\nI read <a href=\"https:\/\/www.manning.com\/books\/functional-programming-in-c-sharp\">Functional Programming in C#<\/a> but, to me,\nthis oversold the technique while it lacking practical advice for day to day programming.\nI had a much better time with\n<a href=\"https:\/\/www.manning.com\/books\/functional-programming-in-c-plus-plus\">Functional Programming in C++<\/a>\nwhich concentrates a lot more on how to get things done.\nIt tells you about a new tool and how to add it to your toolbox.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"functional-programming\">Functional programming<\/h2>\n\n\n\n<p>Unsurprisingly this paradigm is all about functions, specifically\n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Pure_function\"><em>pure functions<\/em><\/a>.\nThese are functions where their output is entirely dependant on their input and they have no side-effects.\nThat means they don&#8217;t depend on any global state and they don&#8217;t change any global state.\nThis makes them easier to reason about, less likely to cause or be effected by bugs,\neasier to test and debug, well-suited to parallelisation.\nI tend to think of functional techniques as force multipliers,\nthey let you get more for less.<\/p>\n\n\n\n<p>As well as using functions this paradigm creates and manipulates functions.\nSo you will be passing functions into functions and \/ or  getting functions back as a result.\nIn C++ this means you&#8217;ll be getting into template meta-programming.\nThis is a powerful technique but is also confusing.\nYou have to learn how to use a bunch of build time equivalents to runtime code.\nExpect build time error messages to be less helpful than you&#8217;re use to.\nOn the other hand this book gives some good examples to learn from and reason to do so.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"procedural-to-functional\">Procedural to functional<\/h2>\n\n\n\n<p>The book starts with a good example of taking some simple code using the procedural paradigm and\nconverting it to a functional one.\nLet&#8217;s take a list of filenames and turn it into a list of line counts.\nI&#8217;ll paraphrase it here:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">std::vector&lt;uint32_t&gt; CountLinesInFiles(const std::vector&lt;std::string&gt;&amp; filenames) {\n    std::vector&lt;uint32_t&gt; lineCounts;\n    char character = 0;\n    for (const auto&amp; filename : filenames) {\n        uint32_t lineCount = 0;\n        std::ifstream stream(filename);\n        while (stream.get(character)) {\n            if (character == '\\n') {\n                lineCount++;\n            }\n        }\n        lineCounts.push_back(lineCount);\n    }\n    return lineCounts;\n}<\/pre><\/div>\n\n\n\n<p>This code does the job although I&#8217;d have probably broken it into two functions from the start.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">uint32_t CountLinesInFile(const std::string&amp; filename) {\n    std::ifstream stream(filename);\n    return std::count(std::istreambuf_iterator&lt;char&gt;(stream), std::istreambuf_iterator&lt;char&gt;(), '\\n');\n}\n\nstd::vector&lt;uint32_t&gt; CountLinesInFiles(const std::vector&lt;std::string&gt;&amp; filenames) {\n    std::vector&lt;uint32_t&gt; lineCounts;\n    for (const auto&amp; filename : filenames) {\n        lineCounts.push_back(CountLinesInFile(filename));\n    }\n    return lineCounts;\n}<\/pre><\/div>\n\n\n\n<p>That what the book does next.\nIt&#8217;s also making use standard library to do some of the work.\nDespite the extra function it&#8217;s taking up less space.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">std::vector&lt;uint32_t&gt; CountLinesInFiles(const std::vector&lt;std::string&gt;&amp; filenames) {\n    std::vector&lt;uint32_t&gt; lineCounts(filenames.size());\n    std::transform(filenames.cbegin(), filenames.cend(), lineCounts.begin(), CountLinesInFile);\n    return lineCounts;\n}<\/pre><\/div>\n\n\n\n<p>More standard library work to transform a vector of one things into a vector of another things.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">std::vector&lt;uint32_t&gt; CountLinesInFiles(const std::vector&lt;std::string&gt;&amp; filenames) {\n    return filenames | transform(CountLinesInFile);\n}<\/pre><\/div>\n\n\n\n<p>The book introduces the pipe operator to take a collection and <em>push it through<\/em> a transform.\nThe book came out before C++20 which includes <code>std::ranges<\/code> and\nthe pipe operator so there may be some discrepancies.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">std::vector&lt;uint32_t&gt; CountLinesInFiles(const std::vector&lt;std::string&gt;&amp; filenames) {\n    return filenames | transform(OpenFile) | transform(CountLines);\n}<\/pre><\/div>\n\n\n\n<p>Finally we break up <code>CountLinesInFile<\/code> to two function concepts <code>OpenFile<\/code> and <code>CountLines<\/code>,\nnot included, both of which could be used in other contexts.<\/p>\n\n\n\n<p>All of this sounds good to me and has gone towards my options on\n<a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/03\/12\/how-often\/\">repeating code<\/a>.\nWhether you can take <em>all<\/em> your code and do something like this seems less important to me.\nI think there is definitely <em>some<\/em> code that could be improved like this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"function-in-c\">Functional in C++<\/h2>\n\n\n\n<p>After this the book the books takes you through some functional programming fundamentals:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Fold_(higher-order_function)\">Fold<\/a> &#8211; A way to convert lists into individual values, e.g. sum.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Filter_(higher-order_function)\">Filter<\/a> &#8211; A way to select values from a list.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Map_(higher-order_function)\">Transform<\/a> &#8211; A way to convert values in a list into new values.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Partial_application\">Partial application<\/a> &#8211; Taking a function with some parameters and producing a new function with fewer parameters.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Curry_%28programming_language%29\">Curry<\/a> &#8211; Takes a function with some parameters and creates a series of functions with one parameter. The book isn&#8217;t overly clear as to <em>why<\/em> you&#8217;d do this.<\/li>\n\n\n\n<li><a href=\"https:\/\/wiki.haskell.org\/Lifting\">Lift<\/a> &#8211; Take a function and create a new function applicable in a broader context, e.g. turn <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/string\/byte\/toupper\"><code>to_upper<\/code><\/a> for characters into one for strings.<\/li>\n<\/ul>\n\n\n\n<p>And how to take those fundamentals and make use of them in C++:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/lambda\">Lambdas<\/a> &#8211; An unnamed functions that can be passed into a fold, filter or transform.<\/li>\n\n\n\n<li>Function objects &#8211; Custom classes that reduce boilerplate further.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/functional\/bind\"><code>std::bind<\/code><\/a> or lambdas &#8211; Both can be used for partial application.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Template_metaprogramming\">Template meta-programming<\/a> &#8211; Lets one algorithm work with different types in a controlled way.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"lessons-in-const\">Lessons in const<\/h2>\n\n\n\n<p>Functional programming uses pure functions that don&#8217;t have side effects.\nThat means you can be using <code>const<\/code> all over the place, that guarantees you&#8217;re doing it right.\nHowever the book does point out that const variable cannot undergo <em>named return value optimisation<\/em>\nbecause they cannot use move operations.\nIt&#8217;s a rare case of where <code>const<\/code> might hurt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"building-useful-tools\">Building useful tools<\/h2>\n\n\n\n<p>The book includes a number of classes and ideas you might want to include in your next project:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>LazyValue<\/code> &#8211; Delays the calculation of a value until it is actually needed.<\/li>\n\n\n\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Memoization\">Memoization<\/a> &#8211; Caches function results so they only have to be calculated once.<\/li>\n\n\n\n<li><code>LazyStringConcatination<\/code> &#8211; Lazy string builder implementation.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-are-monads\">What are monads?<\/h2>\n\n\n\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Monad_(functional_programming)\">Monads<\/a> are where things start to get a bit abstract. I think this eventually happens with a lot of functional programming material. Maybe because it&#8217;s been an academic area longer than it&#8217;s been used in more practical fields.<\/p>\n\n\n\n<p>They have multiple uses but one seems to be dealing with errors. Lots of function can only sometimes produce a true result. Other times they produce no value or an error value. This can make chains of function increasingly complicated. Monads can strip these extras off, unwrapping things back to the underlying values.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-the-end\">In the end<\/h2>\n\n\n\n<p>I found this an interesting and fairly clear read, monads aside.\nIn particular it got me to improve my abilities with templates.\nI&#8217;m sure that pieces of a functional approach can improve a C++ codebase and\nthis book give you a clear idea on how you might do that.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I remember functional programming being a niche aspect of computing science. Software engineering didn&#8217;t consider it at all. Now you can find discussion and books about using it in any major programming language. I read Functional Programming in C# but, to me, this oversold the technique while it lacking practical advice for day to day [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[34],"tags":[20,27],"class_list":["post-229","post","type-post","status-publish","format-standard","hentry","category-review","tag-books","tag-paradigm"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/229","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/comments?post=229"}],"version-history":[{"count":1,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/229\/revisions"}],"predecessor-version":[{"id":230,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/229\/revisions\/230"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=229"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=229"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}