Full Code of getify/Functional-Light-JS for AI

master 40a68612275b cached
35 files
22.4 MB
127.7k tokens
38 symbols
1 requests
Download .txt
Showing preview only (552K chars total). Download the full file or copy to clipboard to get everything.
Repository: getify/Functional-Light-JS
Branch: master
Commit: 40a68612275b
Files: 35
Total size: 22.4 MB

Directory structure:
gitextract_xx3xfcwu/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── content-question.md
│       ├── foreign-translation-request.md
│       ├── report-technical-mistake.md
│       └── textual-grammar-typo.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── LICENSE.txt
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── ch11-code/
│   ├── fp-helpers.js
│   ├── index.html
│   ├── mock-server.js
│   ├── stock-ticker-events.js
│   ├── stock-ticker.css
│   └── stock-ticker.js
└── manuscript/
    ├── README.md
    ├── apA.md
    ├── apB.md
    ├── apC.md
    ├── ch1.md
    ├── ch10.md
    ├── ch11.md
    ├── ch2.md
    ├── ch3.md
    ├── ch4.md
    ├── ch5.md
    ├── ch6.md
    ├── ch7.md
    ├── ch8.md
    ├── ch9.md
    ├── foreword.md
    ├── images/
    │   └── marketing/
    │       └── front-cover-hd.tiff
    └── preface.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4

[*.md]
indent_style = space
indent_size = 4


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [getify]
patreon: getify
custom: ['https://www.paypal.com/paypalme2/getify','https://www.blockchain.com/btc/address/32R5dVrqirdcbiyvUw85y7YbPFZTd7YpnH']


================================================
FILE: .github/ISSUE_TEMPLATE/content-question.md
================================================
---
name: Content Question
about: Ask a question about something you read in the books?
labels: 

---

**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONTRIBUTING.md)** (please feel free to remove this line -- if you leave this line here, I'm going to assume you didn't actually read it).


================================================
FILE: .github/ISSUE_TEMPLATE/foreign-translation-request.md
================================================
---
name: Foreign Translation Request
about: Want to request a translation into a foreign language?
labels: 

---

Please check these issues first:

* https://github.com/getify/Functional-Light-JS/issues?utf8=%E2%9C%93&q=label%3A%22foreign+language+translations%22+
* https://github.com/getify/Functional-Light-JS/issues/106
* https://github.com/getify/Functional-Light-JS/issues/115

To summarize, the steps for a foreign language translation are:

1. Fork this repo
2. Make your own translation entirely in your fork, preferably of all six books, but at a minimum of one whole book
3. File an issue asking for a branch to be made on our main repo, named for that [language's ISO code](http://www.lingoes.net/en/translator/langcode.htm)
4. Once the branch is created, you can PR to merge your translated work in
5. Once the merge is complete, I will promote you to a repository maintainer so you can manage any further translation maintenance work on your own branch of this repo


================================================
FILE: .github/ISSUE_TEMPLATE/report-technical-mistake.md
================================================
---
name: Report Technical Mistake
about: Help us fix a mistake in the code.
labels: 

---

**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONTRIBUTING.md)** (please feel free to remove this line -- if you leave this line here, I'm going to assume you didn't actually read it).


================================================
FILE: .github/ISSUE_TEMPLATE/textual-grammar-typo.md
================================================
---
name: Textual/Grammar Typo
about: Help us correct a spelling or grammar error in the text.
labels: 

---

**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONTRIBUTING.md)** (please feel free to remove this line -- if you leave this line here, I'm going to assume you didn't actually read it).


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Please feel free to contribute to the quality of this content by submitting PR's for improvements to code snippets, explanations, etc. If there's any doubt or if you think that a word/phrase is used confusingly, **before submitting a PR, open an issue to ask about it.**

However, if you choose to contribute content (not just typo corrections) to this repo, you agree that you're giving me a non-exclusive license to use that content for the book, as I (and any future publisher) deem appropriate. You probably guessed that already, but I just have to make sure the lawyers are happy by explicitly stating it.

## Search First!

If you have any questions or concerns, please make sure to search the issues (both open and closed!) first, to keep the churn of issues to a minimum. I want to keep my focus on improving the content as much as possible.

## Typos?

This book has already been edited. Most typos have already been caught and fixed, but there might still be some mistakes here and there.

If you're going to submit a PR for typo fixes, please be measured in doing so, perhaps by collecting several small changes into a single PR (in separate commits).

## Reading Experience (Chapter/Section links, etc)

This repo **is not optimized for your reading experience.** It's optimized for the publishing process.

The primary intended reading experience -- likely the most pleasant one for many of you! -- is the ebook, [which is now on sale](https://leanpub.com/fljs). The balance I'm striking here is releasing the content for free, but selling the reading experience. Other authors make different decisions on that balance, but that's what I've come to for now.

I hope you continue to enjoy and benefit from the content, and I also hope you value it enough to purchase the best reading experience in the ebook/print form.


================================================
FILE: ISSUE_TEMPLATE.md
================================================
**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONTRIBUTING.md)** (please feel free to remove this line -- if you leave this line here, I'm going to assume you didn't actually read it).


================================================
FILE: LICENSE.txt
================================================
Attribution-NonCommercial-NoDerivatives 4.0 International

=======================================================================

Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.

Using Creative Commons Public Licenses

Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.

     Considerations for licensors: Our public licenses are
     intended for use by those authorized to give the public
     permission to use material in ways otherwise restricted by
     copyright and certain other rights. Our licenses are
     irrevocable. Licensors should read and understand the terms
     and conditions of the license they choose before applying it.
     Licensors should also secure all rights necessary before
     applying our licenses so that the public can reuse the
     material as expected. Licensors should clearly mark any
     material not subject to the license. This includes other CC-
     licensed material, or material used under an exception or
     limitation to copyright. More considerations for licensors:
	wiki.creativecommons.org/Considerations_for_licensors

     Considerations for the public: By using one of our public
     licenses, a licensor grants the public permission to use the
     licensed material under specified terms and conditions. If
     the licensor's permission is not necessary for any reason--for
     example, because of any applicable exception or limitation to
     copyright--then that use is not regulated by the license. Our
     licenses grant only permissions under copyright and certain
     other rights that a licensor has authority to grant. Use of
     the licensed material may still be restricted for other
     reasons, including because others have copyright or other
     rights in the material. A licensor may make special requests,
     such as asking that all changes be marked or described.
     Although not required by our licenses, you are encouraged to
     respect those requests where reasonable. More_considerations
     for the public:
	wiki.creativecommons.org/Considerations_for_licensees

=======================================================================

Creative Commons Attribution-NonCommercial-NoDerivatives 4.0
International Public License

By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-NoDerivatives 4.0 International Public
License ("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.


Section 1 -- Definitions.

  a. Adapted Material means material subject to Copyright and Similar
     Rights that is derived from or based upon the Licensed Material
     and in which the Licensed Material is translated, altered,
     arranged, transformed, or otherwise modified in a manner requiring
     permission under the Copyright and Similar Rights held by the
     Licensor. For purposes of this Public License, where the Licensed
     Material is a musical work, performance, or sound recording,
     Adapted Material is always produced where the Licensed Material is
     synched in timed relation with a moving image.

  b. Copyright and Similar Rights means copyright and/or similar rights
     closely related to copyright including, without limitation,
     performance, broadcast, sound recording, and Sui Generis Database
     Rights, without regard to how the rights are labeled or
     categorized. For purposes of this Public License, the rights
     specified in Section 2(b)(1)-(2) are not Copyright and Similar
     Rights.

  c. Effective Technological Measures means those measures that, in the
     absence of proper authority, may not be circumvented under laws
     fulfilling obligations under Article 11 of the WIPO Copyright
     Treaty adopted on December 20, 1996, and/or similar international
     agreements.

  d. Exceptions and Limitations means fair use, fair dealing, and/or
     any other exception or limitation to Copyright and Similar Rights
     that applies to Your use of the Licensed Material.

  e. Licensed Material means the artistic or literary work, database,
     or other material to which the Licensor applied this Public
     License.

  f. Licensed Rights means the rights granted to You subject to the
     terms and conditions of this Public License, which are limited to
     all Copyright and Similar Rights that apply to Your use of the
     Licensed Material and that the Licensor has authority to license.

  g. Licensor means the individual(s) or entity(ies) granting rights
     under this Public License.

  h. NonCommercial means not primarily intended for or directed towards
     commercial advantage or monetary compensation. For purposes of
     this Public License, the exchange of the Licensed Material for
     other material subject to Copyright and Similar Rights by digital
     file-sharing or similar means is NonCommercial provided there is
     no payment of monetary compensation in connection with the
     exchange.

  i. Share means to provide material to the public by any means or
     process that requires permission under the Licensed Rights, such
     as reproduction, public display, public performance, distribution,
     dissemination, communication, or importation, and to make material
     available to the public including in ways that members of the
     public may access the material from a place and at a time
     individually chosen by them.

  j. Sui Generis Database Rights means rights other than copyright
     resulting from Directive 96/9/EC of the European Parliament and of
     the Council of 11 March 1996 on the legal protection of databases,
     as amended and/or succeeded, as well as other essentially
     equivalent rights anywhere in the world.

  k. You means the individual or entity exercising the Licensed Rights
     under this Public License. Your has a corresponding meaning.


Section 2 -- Scope.

  a. License grant.

       1. Subject to the terms and conditions of this Public License,
          the Licensor hereby grants You a worldwide, royalty-free,
          non-sublicensable, non-exclusive, irrevocable license to
          exercise the Licensed Rights in the Licensed Material to:

            a. reproduce and Share the Licensed Material, in whole or
               in part, for NonCommercial purposes only; and

            b. produce and reproduce, but not Share, Adapted Material
               for NonCommercial purposes only.

       2. Exceptions and Limitations. For the avoidance of doubt, where
          Exceptions and Limitations apply to Your use, this Public
          License does not apply, and You do not need to comply with
          its terms and conditions.

       3. Term. The term of this Public License is specified in Section
          6(a).

       4. Media and formats; technical modifications allowed. The
          Licensor authorizes You to exercise the Licensed Rights in
          all media and formats whether now known or hereafter created,
          and to make technical modifications necessary to do so. The
          Licensor waives and/or agrees not to assert any right or
          authority to forbid You from making technical modifications
          necessary to exercise the Licensed Rights, including
          technical modifications necessary to circumvent Effective
          Technological Measures. For purposes of this Public License,
          simply making modifications authorized by this Section 2(a)
          (4) never produces Adapted Material.

       5. Downstream recipients.

            a. Offer from the Licensor -- Licensed Material. Every
               recipient of the Licensed Material automatically
               receives an offer from the Licensor to exercise the
               Licensed Rights under the terms and conditions of this
               Public License.

            b. No downstream restrictions. You may not offer or impose
               any additional or different terms or conditions on, or
               apply any Effective Technological Measures to, the
               Licensed Material if doing so restricts exercise of the
               Licensed Rights by any recipient of the Licensed
               Material.

       6. No endorsement. Nothing in this Public License constitutes or
          may be construed as permission to assert or imply that You
          are, or that Your use of the Licensed Material is, connected
          with, or sponsored, endorsed, or granted official status by,
          the Licensor or others designated to receive attribution as
          provided in Section 3(a)(1)(A)(i).

  b. Other rights.

       1. Moral rights, such as the right of integrity, are not
          licensed under this Public License, nor are publicity,
          privacy, and/or other similar personality rights; however, to
          the extent possible, the Licensor waives and/or agrees not to
          assert any such rights held by the Licensor to the limited
          extent necessary to allow You to exercise the Licensed
          Rights, but not otherwise.

       2. Patent and trademark rights are not licensed under this
          Public License.

       3. To the extent possible, the Licensor waives any right to
          collect royalties from You for the exercise of the Licensed
          Rights, whether directly or through a collecting society
          under any voluntary or waivable statutory or compulsory
          licensing scheme. In all other cases the Licensor expressly
          reserves any right to collect such royalties, including when
          the Licensed Material is used other than for NonCommercial
          purposes.


Section 3 -- License Conditions.

Your exercise of the Licensed Rights is expressly made subject to the
following conditions.

  a. Attribution.

       1. If You Share the Licensed Material, You must:

            a. retain the following if it is supplied by the Licensor
               with the Licensed Material:

                 i. identification of the creator(s) of the Licensed
                    Material and any others designated to receive
                    attribution, in any reasonable manner requested by
                    the Licensor (including by pseudonym if
                    designated);

                ii. a copyright notice;

               iii. a notice that refers to this Public License;

                iv. a notice that refers to the disclaimer of
                    warranties;

                 v. a URI or hyperlink to the Licensed Material to the
                    extent reasonably practicable;

            b. indicate if You modified the Licensed Material and
               retain an indication of any previous modifications; and

            c. indicate the Licensed Material is licensed under this
               Public License, and include the text of, or the URI or
               hyperlink to, this Public License.

          For the avoidance of doubt, You do not have permission under
          this Public License to Share Adapted Material.

       2. You may satisfy the conditions in Section 3(a)(1) in any
          reasonable manner based on the medium, means, and context in
          which You Share the Licensed Material. For example, it may be
          reasonable to satisfy the conditions by providing a URI or
          hyperlink to a resource that includes the required
          information.

       3. If requested by the Licensor, You must remove any of the
          information required by Section 3(a)(1)(A) to the extent
          reasonably practicable.


Section 4 -- Sui Generis Database Rights.

Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:

  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
     to extract, reuse, reproduce, and Share all or a substantial
     portion of the contents of the database for NonCommercial purposes
     only and provided You do not Share Adapted Material;

  b. if You include all or a substantial portion of the database
     contents in a database in which You have Sui Generis Database
     Rights, then the database in which You have Sui Generis Database
     Rights (but not its individual contents) is Adapted Material; and

  c. You must comply with the conditions in Section 3(a) if You Share
     all or a substantial portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.


Section 5 -- Disclaimer of Warranties and Limitation of Liability.

  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.

  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.

  c. The disclaimer of warranties and limitation of liability provided
     above shall be interpreted in a manner that, to the extent
     possible, most closely approximates an absolute disclaimer and
     waiver of all liability.


Section 6 -- Term and Termination.

  a. This Public License applies for the term of the Copyright and
     Similar Rights licensed here. However, if You fail to comply with
     this Public License, then Your rights under this Public License
     terminate automatically.

  b. Where Your right to use the Licensed Material has terminated under
     Section 6(a), it reinstates:

       1. automatically as of the date the violation is cured, provided
          it is cured within 30 days of Your discovery of the
          violation; or

       2. upon express reinstatement by the Licensor.

     For the avoidance of doubt, this Section 6(b) does not affect any
     right the Licensor may have to seek remedies for Your violations
     of this Public License.

  c. For the avoidance of doubt, the Licensor may also offer the
     Licensed Material under separate terms or conditions or stop
     distributing the Licensed Material at any time; however, doing so
     will not terminate this Public License.

  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
     License.


Section 7 -- Other Terms and Conditions.

  a. The Licensor shall not be bound by any additional or different
     terms or conditions communicated by You unless expressly agreed.

  b. Any arrangements, understandings, or agreements regarding the
     Licensed Material not stated herein are separate from and
     independent of the terms and conditions of this Public License.


Section 8 -- Interpretation.

  a. For the avoidance of doubt, this Public License does not, and
     shall not be interpreted to, reduce, limit, restrict, or impose
     conditions on any use of the Licensed Material that could lawfully
     be made without permission under this Public License.

  b. To the extent possible, if any provision of this Public License is
     deemed unenforceable, it shall be automatically reformed to the
     minimum extent necessary to make it enforceable. If the provision
     cannot be reformed, it shall be severed from this Public License
     without affecting the enforceability of the remaining terms and
     conditions.

  c. No term or condition of this Public License will be waived and no
     failure to comply consented to unless expressly agreed to by the
     Licensor.

  d. Nothing in this Public License constitutes or may be interpreted
     as a limitation upon, or waiver of, any privileges and immunities
     that apply to the Licensor or You, including from the legal
     processes of any jurisdiction or authority.

=======================================================================

Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.

Creative Commons may be contacted at creativecommons.org.


================================================
FILE: PULL_REQUEST_TEMPLATE.md
================================================
**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONTRIBUTING.md)** (please feel free to remove this line -- if you leave this line here, I'm going to assume you didn't actually read it).


================================================
FILE: README.md
================================================
# Functional-Light JavaScript

[![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC%20BY--NC--ND%204.0-blue.svg)](http://creativecommons.org/licenses/by-nc-nd/4.0/)

<a href="http://fljsbook.com"><img src="manuscript/images/marketing/front-cover-small.png" width="25%" align="right" hspace="20" vspace="20" title="Functional-Light JavaScript" alt="Book Cover"></a>

This book is a balanced, pragmatic look at FP in JavaScript. The first edition is now complete. Read here online **for free**, or:

<p align="center">
    <a href="http://fljsbook.com"><img src="https://img.shields.io/badge/Buy-Leanpub-yellow.svg" title="Buy on Leanpub" alt="Buy on Leanpub"></a> <a href="http://manning.fljsbook.com"><img src="https://img.shields.io/badge/Buy-Manning-yellow.svg" title="Buy on Manning" alt="Buy on Manning"></a> <a href="http://amazon.fljsbook.com"><img src="https://img.shields.io/badge/Buy-Amazon-yellow.svg" title="Buy on Amazon" alt="Buy on Amazon"></a>
</p>

"Functional-Light JavaScript" explores the core principles of functional programming (FP) as they are applied to JavaScript. But what makes this book different is that we approach these principles without drowning in all the heavy terminology. We look at a subset of FP foundational concepts that I call "Functional-Light Programming" (FLP) and apply it to JavaScript.

**Note:** Despite the word "Light" in the title, I do not consider or recommend this book as a "beginner", "easy", or "intro" book on the topic. This book is rigorous and full of gritty detail; it expects a solid foundation of JS knowledge before diving in. "Light" means limited in scope; instead of being more broad, this book goes much deeper into each topic than you typically find in other FP-JavaScript books.

Let's face it: unless you're already a member of the FP cool kids club (I'm not!), a statement like, "a monad is just a monoid in the category of endofunctors", just doesn't mean anything useful to us.

That's not to say the terms are meaning*less* or that FPrs are bad for using them. Once you graduate from Functional-Light, you'll maybe/hopefully want to study FP more formally, and you'll certainly have plenty of exposure to what they mean and why.

But I want you to be able to apply some of the fundamentals of FP to your JavaScript *now*, because I believe it will help you write better, more *reason*able code.

**To read more about the motivations and perspective behind this book, check out the [Preface](manuscript/preface.md).**

## Book

[Table of Contents](manuscript/README.md/#table-of-contents)

* [Foreword](manuscript/foreword.md/#foreword) (by [Brian Lonsdorf, aka "Prof Frisby"](https://twitter.com/DrBoolean))
* [Preface](manuscript/preface.md/#preface)
* [Chapter 1: Why Functional Programming?](manuscript/ch1.md/#chapter-1-why-functional-programming)
* [Chapter 2: The Nature Of Functions](manuscript/ch2.md/#chapter-2-the-nature-of-functions)
* [Chapter 3: Managing Function Inputs](manuscript/ch3.md/#chapter-3-managing-function-inputs)
* [Chapter 4: Composing Functions](manuscript/ch4.md/#chapter-4-composing-functions)
* [Chapter 5: Reducing Side Effects](manuscript/ch5.md/#chapter-5-reducing-side-effects)
* [Chapter 6: Value Immutability](manuscript/ch6.md/#chapter-6-value-immutability)
* [Chapter 7: Closure vs Object](manuscript/ch7.md/#chapter-7-closure-vs-object)
* [Chapter 8: Recursion](manuscript/ch8.md/#chapter-8-recursion)
* [Chapter 9: List Operations](manuscript/ch9.md/#chapter-9-list-operations)
* [Chapter 10: Functional Async](manuscript/ch10.md/#chapter-10-functional-async)
* [Chapter 11: Putting It All Together](manuscript/ch11.md/#chapter-11-putting-it-all-together)
* [Appendix A: Transducing](manuscript/apA.md/#appendix-a-transducing)
* [Appendix B: The Humble Monad](manuscript/apB.md/#appendix-b-the-humble-monad)
* [Appendix C: FP Libraries](manuscript/apC.md/#appendix-c-fp-libraries)

## Publishing

This book has been published and is now available for purchase (in both ebook and print formats) from these sources:

<p align="center">
    <a href="http://fljsbook.com"><img src="https://img.shields.io/badge/Buy-Leanpub-yellow.svg" title="Buy on Leanpub" alt="Buy on Leanpub"></a> <a href="http://manning.fljsbook.com"><img src="https://img.shields.io/badge/Buy-Manning-yellow.svg" title="Buy on Manning" alt="Buy on Manning"></a> <a href="http://amazon.fljsbook.com"><img src="https://img.shields.io/badge/Buy-Amazon-yellow.svg" title="Buy on Amazon" alt="Buy on Amazon"></a>
</p>

If you'd like additionally to contribute financially towards the effort (or any of my other OSS work) aside from purchasing the book, I do have a [patreon](https://www.patreon.com/getify) that I would always appreciate your generosity towards.

<a href="https://www.patreon.com/getify">[![patreon.png](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/getify)</a>

## In-person Training

The content for this book derives heavily from a training workshop I teach professionally (in both public and private-corporate workshop format) of the same name.

If you like this content and would like to contact me regarding conducting training on this, or other various JS/HTML5/Node.js topics, please reach out to me through email: getify @ gmail

## Online Video Training

I also have several JS training courses available in on-demand video format. I [teach courses](https://FrontendMasters.com/teachers/kyle-simpson) through [Frontend Masters](https://FrontendMasters.com), like my [Functional-Light JavaScript v2](https://frontendmasters.com/courses/functional-javascript-v2/) workshop. Some of my courses are also available on [PluralSight](https://www.pluralsight.com/search?q=kyle%20simpson&categories=all).

## Contributions

Any contributions you make to this effort **are of course greatly appreciated**.

But **PLEASE** read the [Contributions Guidelines](CONTRIBUTING.md) carefully before submitting a PR.

## License & Copyright

The materials herein are all (c) 2016-2018 Kyle Simpson.

<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivs 4.0 Unported License</a>.


================================================
FILE: ch11-code/fp-helpers.js
================================================
"use strict";

var pipe = reverseArgs(compose);

// curried list operators
var map = unboundMethod( "map", 2 );
var filter = unboundMethod( "filter", 2 );
var filterIn = filter;
var reduce = unboundMethod( "reduce", 3 );
var each = unboundMethod( "forEach", 2 );
var flatMap = curry( function flatMap(mapperFn,arr) {
	return arr.reduce( function reducer(list,v) {
		return list.concat( mapperFn( v ) );
	}, [] );
} );


// ************************************

function filterOut(predicateFn,arr) {
	return filterIn( not( predicateFn ), arr );
}

function unary(fn) {
	return function onlyOneArg(arg){
		return fn( arg );
	};
}

function not(predicate) {
	return function negated(...args){
		return !predicate( ...args );
	};
}

function reverseArgs(fn) {
	return function argsReversed(...args){
		return fn( ...args.reverse() );
	};
}

function spreadArgs(fn) {
	return function spreadFn(argsArr){
		return fn( ...argsArr );
	};
}

function partial(fn,...presetArgs) {
	return function partiallyApplied(...laterArgs){
		return fn( ...presetArgs, ...laterArgs );
	};
}

function partialRight(fn,...presetArgs) {
	return function partiallyApplied(...laterArgs){
		return fn( ...laterArgs, ...presetArgs );
	};
}

function curry(fn,arity = fn.length) {
	return (function nextCurried(prevArgs){
		return function curried(nextArg){
			var args = [ ...prevArgs, nextArg ];

			if (args.length >= arity) {
				return fn( ...args );
			}
			else {
				return nextCurried( args );
			}
		};
	})( [] );
}

function uncurry(fn) {
	return function uncurried(...args){
		var ret = fn;

		for (let i = 0; i < args.length; i++) {
			ret = ret( args[i] );
		}

		return ret;
	};
}

function zip(arr1,arr2) {
	var zipped = [];
	arr1 = [...arr1];
	arr2 = [...arr2];

	while (arr1.length > 0 && arr2.length > 0) {
		zipped.push( [ arr1.shift(), arr2.shift() ] );
	}

	return zipped;
}

function compose(...fns) {
    return fns.reduceRight( function reducer(fn1,fn2){
        return function composed(...args){
            return fn2( fn1( ...args ) );
        };
    } );
}

function prop(name,obj) {
	return obj[name];
}

function setProp(name,obj,val) {
	var o = Object.assign( {}, obj );
	o[name] = val;
	return o;
}

function unboundMethod(methodName,argCount = 2) {
	return curry(
		(...args) => {
			var obj = args.pop();
			return obj[methodName]( ...args );
		},
		argCount
	);
}


================================================
FILE: ch11-code/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Functional-Light JavaScript, Ch11: Stock Ticker</title>
<link rel="stylesheet" href="stock-ticker.css">
</head>
<body>
<h1>Functional-Light JavaScript, Ch11: Stock Ticker</h1>

<ul id="stock-ticker"></ul>

<!-- faking a server sending up stock updates -->
<script src="mock-server.js"></script>
<!-- **************************************** -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.min.js"></script>
<script src="fp-helpers.js"></script>
<script src="stock-ticker-events.js"></script>
<script src="stock-ticker.js"></script>

</body>
</html>


================================================
FILE: ch11-code/mock-server.js
================================================
function connectToServer() {
	// faking an event emitter attached to a server-event stream
	return evtEmitter;
}


// ***********************************
// MOCK SERVER
// ***********************************

// simple/mock event emitter
var evtEmitter = {
	handlers: {},
	on(evtName,cb) {
		this.handlers[evtName] = this.handlers[evtName] || [];
		this.handlers[evtName][this.handlers[evtName].length] = cb;
	},
	addEventListener(...args) {
		return this.on( ...args );
	},
	removeEventListener(){},
	emit(evtName,...args) {
		for (let handler of (this.handlers[evtName] || [])) {
			handler(...args);
		}
	}
};

var stocks = {
	"AAPL": { price: 121.95, change: 0.01 },
	"MSFT": { price: 65.78, change: 1.51 },
	"GOOG": { price: 821.31, change: -8.84 },
};

setTimeout( function initialStocks(){
	for (let id in stocks) {
		// !!SIDE EFFECTS!!
		evtEmitter.emit( "stock", Object.assign( { id }, stocks[id] ) );
	}
}, 100 );

setTimeout( function randomStockUpdate(){
	var stockIds = Object.keys( stocks );
	var stockIdx = randInRange( 0, stockIds.length - 1 );
	var change = (randInRange( 1, 10 ) > 7 ? -1 : 1) *
		(randInRange( 1, 10 ) / 1E2);

	var newStock = Object.assign( stocks[stockIds[stockIdx]] );
	newStock.price += change;
	newStock.change += change;

	// !!SIDE EFFECTS!!
	stocks[stockIdx[stockIdx]] = newStock;
	evtEmitter.emit( "stock-update", Object.assign( { id: stockIds[stockIdx] }, newStock ) );

	setTimeout( randomStockUpdate, randInRange( 300, 1500 ) );
}, 1000 );


// !!SIDE EFFECTS!!
function randInRange(min = 0,max = 1E9) {
	return (Math.round(Math.random() * 1E4) % (max - min)) + min;
}


================================================
FILE: ch11-code/stock-ticker-events.js
================================================
var server = connectToServer();

var formatDecimal = unboundMethod( "toFixed" )( 2 );
var formatPrice = pipe( formatDecimal, formatCurrency );
var formatChange = pipe( formatDecimal, formatSign );
var processNewStock = pipe( addStockName, formatStockNumbers );
var observableMapperFns = [ processNewStock, formatStockNumbers ];
var makeObservableFromEvent = curry( Rx.Observable.fromEvent, 2 )( server );
var mapObservable = uncurry( map );

var stockEventNames = [ "stock", "stock-update" ];

var [ newStocks, stockUpdates ] = pipe(
	map( makeObservableFromEvent ),
	curry( zip )( observableMapperFns ),
	map( spreadArgs( mapObservable ) )
)
( stockEventNames );


// *********************

function addStockName(stock) {
	return setProp( "name", stock, stock.id );
}

function formatStockNumbers(stock) {
	var stockDataUpdates = [
		[ "price", formatPrice( stock.price ) ],
		[ "change", formatChange( stock.change ) ]
	];

	return reduce( function formatter(stock,[propName,val]){
		return setProp( propName, stock, val );
	} )
	( stock )
	( stockDataUpdates );
}

function formatSign(val) {
	if (Number(val) > 0) {
		return `+${val}`;
	}
	return val;
}

function formatCurrency(val) {
	return `$${val}`;
}


================================================
FILE: ch11-code/stock-ticker.css
================================================
*, *:before, *:after {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

#stock-ticker {
	background-color: #efefef;
	padding: 1em;
	margin: 0;
	width: 14em;
}

.stock {
	list-style-type: none;
	padding: 0;
	margin: 0 0 1em 0;
}

.stock:last-child {
	margin-bottom: 0;
}

.stock > span {
	display: inline-block;
	width: 4em;
	text-align: right;
	overflow: hidden;
}

.stock-name {
	font-weight: bold;
	text-align: center;
}



================================================
FILE: ch11-code/stock-ticker.js
================================================
"use strict";

var stockTickerUI = {

	updateStockElems(stockInfoChildElemList,data) {
		var getDataVal = curry( reverseArgs( prop ), 2 )( data );
		var extractInfoChildElemVal = pipe(
			getClassName,
			curry( stripPrefix )( /\bstock-/i ),
			getDataVal
		);
		var orderedDataVals =
			map( extractInfoChildElemVal )( stockInfoChildElemList );
		var elemsValsTuples =
			filterOut( function updateValueMissing([infoChildElem,val]){
				return val === undefined;
			} )
			( zip( stockInfoChildElemList, orderedDataVals ) );

		// !!SIDE EFFECTS!!
		compose( each, spreadArgs )( setDOMContent )
		( elemsValsTuples );
	},

	updateStock(tickerElem,data) {
		var getStockElemFromId = curry( getStockElem )( tickerElem );
		var stockInfoChildElemList = pipe(
			getStockElemFromId,
			getStockInfoChildElems
		)
		( data.id );

		return stockTickerUI.updateStockElems(
			stockInfoChildElemList,
			data
		);
	},

	addStock(tickerElem,data) {
		var [stockElem, ...infoChildElems] = map(
			createElement
		)
		( [ "li", "span", "span", "span" ] );
		var attrValTuples = [
			[ ["class","stock"], ["data-stock-id",data.id] ],
			[ ["class","stock-name"] ],
			[ ["class","stock-price"] ],
			[ ["class","stock-change"] ]
		];
		var elemsAttrsTuples =
			zip( [stockElem, ...infoChildElems], attrValTuples );

		// !!SIDE EFFECTS!!
		each( function setElemAttrs([elem,attrValTupleList]){
			each(
				spreadArgs( partial( setElemAttr, elem ) )
			)
			( attrValTupleList );
		} )
		( elemsAttrsTuples );

		// !!SIDE EFFECTS!!
		stockTickerUI.updateStockElems( infoChildElems, data );
		reduce( appendDOMChild )( stockElem )( infoChildElems );
		appendDOMChild( tickerElem, stockElem );
	}

};

var getDOMChildren = pipe(
	listify,
	flatMap(
		pipe(
			curry( prop )( "childNodes" ),
			Array.from
		)
	)
);
var createElement = document.createElement.bind( document );
var getElemAttrByName = curry( getElemAttr, 2 );
var getStockId = getElemAttrByName( "data-stock-id" );
var getClassName = getElemAttrByName( "class" );
var isMatchingStock = curry( matchingStockId, 2 );
var ticker = document.getElementById( "stock-ticker" );
var stockTickerUIMethodsWithDOMContext = map(
	pipe( partialRight, unary )( partial, ticker )
)
( [ stockTickerUI.addStock, stockTickerUI.updateStock ] );
var subscribeToObservable =
	pipe( unboundMethod, uncurry )( "subscribe" );
var stockTickerObservables = [ newStocks, stockUpdates ];

// !!SIDE EFFECTS!!
each( spreadArgs( subscribeToObservable ) )
( zip( stockTickerUIMethodsWithDOMContext, stockTickerObservables ) );


// *********************

function stripPrefix(prefixRegex,val) {
	return val.replace( prefixRegex, "" );
}

function listify(listOrItem) {
	if (!Array.isArray( listOrItem )) {
		return [ listOrItem ];
	}
	return listOrItem;
}

function isTextNode(node) {
	return node && node.nodeType == 3;
}

function getElemAttr(prop,elem) {
	return elem.getAttribute( prop );
}

function setElemAttr(elem,prop,val) {
	// !!SIDE EFFECTS!!
	return elem.setAttribute( prop, val );
}

function matchingStockId(id,node) {
	return getStockId( node ) == id;
}

function isStockInfoChildElem(elem) {
	return /\bstock-/i.test( getClassName( elem ) );
}

function getStockElem(tickerElem,stockId) {
	return pipe(
		getDOMChildren,
		filterOut( isTextNode ),
		filterIn( isMatchingStock( stockId ) )
	)
	( tickerElem );
}

function getStockInfoChildElems(stockElem) {
	return pipe(
		getDOMChildren,
		filterOut( isTextNode ),
		filterIn( isStockInfoChildElem )
	)
	( stockElem );
}

function appendDOMChild(parentNode,childNode) {
	// !!SIDE EFFECTS!!
	parentNode.appendChild( childNode );
	return parentNode;
}

function setDOMContent(elem,html) {
	// !!SIDE EFFECTS!!
	elem.innerHTML = html;
	return elem;
}


================================================
FILE: manuscript/README.md
================================================
# Functional-Light JavaScript

<a href="https://leanpub.com/fljs"><img src="images/marketing/front-cover-small.png" width="20%"></a>

[![Buy on Leanpub](https://img.shields.io/badge/Buy-Leanpub-yellow.svg)](https://leanpub.com/fljs) [![Buy on Amazon](https://img.shields.io/badge/Buy-Amazon-yellow.svg)](http://amazon.fljsbook.com)

## Table of Contents

* [Foreword](foreword.md/#foreword)
* [Preface](preface.md/#preface)
* [Chapter 1: Why Functional Programming?](ch1.md/#chapter-1-why-functional-programming)
    * [At a Glance](ch1.md/#at-a-glance)
    * [Confidence](ch1.md/#confidence)
    * [Communication](ch1.md/#communication)
    * [Readability](ch1.md/#readability)
    * [Perspective](ch1.md/#perspective)
    * [How to Find Balance](ch1.md/#how-to-find-balance)
    * [Resources](ch1.md/#resources)
* [Chapter 2: The Nature Of Functions](ch2.md/#chapter-2-the-nature-of-functions)
    * [What Is A Function?](ch2.md/#what-is-a-function)
    * [Function Input](ch2.md/#function-input)
    * [Named Arguments](ch2.md/#named-arguments)
    * [Function Output](ch2.md/#function-output)
    * [Functions Of Functions](ch2.md/#functions-of-functions)
    * [Syntax](ch2.md/#syntax)
    * [What's This?](ch2.md/#whats-this)
* [Chapter 3: Managing Function Inputs](ch3.md/#chapter-3-managing-function-inputs)
    * [All For One](ch3.md/#all-for-one)
    * [Adapting Arguments to Parameters](ch3.md/#adapting-arguments-to-parameters)
    * [Some Now, Some Later](ch3.md/#some-now-some-later)
    * [One At A Time](ch3.md/#one-at-a-time)
    * [Order Matters](ch3.md/#order-matters)
    * [No Points](ch3.md/#no-points)
* [Chapter 4: Composing Functions](ch4.md/#chapter-4-composing-functions)
    * [Output To Input](ch4.md/#output-to-input)
    * [General Composition](ch4.md/#general-composition)
    * [Reordered Composition](ch4.md/#reordered-composition)
    * [Abstraction](ch4.md/#abstraction)
    * [Revisiting Points](ch4.md/#revisiting-points)
* [Chapter 5: Reducing Side Effects](ch5.md/#chapter-5-reducing-side-effects)
    * [Effects On The Side, Please](ch5.md/#effects-on-the-side-please)
    * [Once Is Enough, Thanks](ch5.md/#once-is-enough-thanks)
    * [Pure Bliss](ch5.md/#pure-bliss)
    * [There Or Not](ch5.md/#there-or-not)
    * [Purifying](ch5.md/#purifying)
* [Chapter 6: Value Immutability](ch6.md/#chapter-6-value-immutability)
    * [Primitive Immutability](ch6.md/#primitive-immutability)
    * [Value To Value](ch6.md/#value-to-value)
    * [Reassignment](ch6.md/#reassignment)
    * [Performance](ch6.md/#performance)
    * [Treatment](ch6.md/#treatment)
* [Chapter 7: Closure vs Object](ch7.md/#chapter-7-closure-vs-object)
    * [The Same Page](ch7.md/#the-same-page)
    * [Look Alike](ch7.md/#look-alike)
    * [Two Roads Diverged In A Wood...](ch7.md/#two-roads-diverged-in-a-wood)
* [Chapter 8: Recursion](ch8.md/#chapter-8-recursion)
    * [Definition](ch8.md/#definition)
    * [Declarative Recursion](ch8.md/#declarative-recursion)
    * [Stack](ch8.md/#stack)
    * [Rearranging Recursion](ch8.md/#rearranging-recursion)
* [Chapter 9: List Operations](ch9.md/#chapter-9-list-operations)
    * [Non-FP List Processing](ch9.md/#non-fp-list-processing)
    * [Map](ch9.md/#map)
    * [Filter](ch9.md/#filter)
    * [Reduce](ch9.md/#reduce)
    * [Advanced List Operations](ch9.md/#advanced-list-operations)
    * [Method vs. Standalone](ch9.md/#method-vs-standalone)
    * [Looking For Lists](ch9.md/#looking-for-lists)
    * [Fusion](ch9.md/#fusion)
    * [Beyond Lists](ch9.md/#beyond-lists)
* [Chapter 10: Functional Async](ch10.md/#chapter-10-functional-async)
    * [Time As State](ch10.md/#time-as-state)
    * [Eager vs Lazy](ch10.md/#eager-vs-lazy)
    * [Reactive FP](ch10.md/#reactive-fp)
* [Chapter 11: Putting It All Together](ch11.md/#chapter-11-putting-it-all-together)
    * [Setup](ch11.md/#setup)
    * [Stock Events](ch11.md/#stock-events)
    * [Stock Ticker UI](ch11.md/#stock-ticker-ui)
* [Appendix A: Transducing](apA.md/#appendix-a-transducing)
    * [Why, First](apA.md/#why-first)
    * [How, Next](apA.md/#how-next)
    * [What, Finally](apA.md/#what-finally)
* [Appendix B: The Humble Monad](apB.md/#appendix-b-the-humble-monad)
    * [Type](apB.md/#type)
    * [Loose Interface](apB.md/#loose-interface)
    * [Just a Monad](apB.md/#just-a-monad)
    * [Maybe](apB.md/#maybe)
    * [Humble](apB.md/#humble)
* [Appendix C: FP Libraries](apC.md/#appendix-c-fp-libraries)
    * [Stuff to Investigate](apC.md/#stuff-to-investigate)
    * [Ramda](apC.md/#ramda-0230)
    * [Lodash/fp](apC.md/#lodashfp-4174)
    * [Mori](apC.md/#mori-032)
    * [Bonus: FPO](apC.md/#bonus-fpo)
    * [Bonus #2: fasy](apC.md/#bonus-2-fasy)


================================================
FILE: manuscript/apA.md
================================================
# Functional-Light JavaScript
# Appendix A: Transducing

Transducing is a more advanced technique than we've covered in this book. It extends many of the concepts from [Chapter 9](ch9.md) on list operations.

I wouldn't necessarily call this topic strictly "Functional-Light", but more like a bonus on top. I've presented this as an appendix because you might very well need to skip the discussion for now and come back to it once you feel fairly comfortable with -- and make sure you've practiced! -- the main book concepts.

To be honest, even after teaching transducing many times, and writing this chapter, I am still trying to fully wrap my brain around this technique. So don't feel bad if it twists you up. Bookmark this appendix and come back when you're ready.

Transducing means transforming with reduction.

I know that may sound like a jumble of words that confuses more than it clarifies. But let's take a look at how powerful it can be. I actually think it's one of the best illustrations of what you can do once you grasp the principles of Functional-Light Programming.

As with the rest of this book, my approach is to first explain *why*, then *how*, then finally boil it down to a simplified, repeatable *what*. That's often the reverse of how many teach, but I think you'll learn the topic more deeply this way.

## Why, First

Let's start by extending a [scenario we covered back in Chapter 3](ch3.md/#user-content-shortlongenough), testing words to see if they're short enough and/or long enough:

```js
function isLongEnough(str) {
    return str.length >= 5;
}

function isShortEnough(str) {
    return str.length <= 10;
}
```

In [Chapter 3, we used these predicate functions](ch3.md/#user-content-shortlongenough) to test a single word. Then in Chapter 9, we learned how to repeat such tests [using list operations like `filter(..)`](ch9.md/#filter). For example:

```js
var words = [ "You", "have", "written", "something", "very",
    "interesting" ];

words
.filter( isLongEnough )
.filter( isShortEnough );
// ["written","something"]
```

It may not be obvious, but this pattern of separate adjacent list operations has some non-ideal characteristics. When we're dealing with only a single array of a small number of values, everything is fine. But if there were lots of values in the array, each `filter(..)` processing the list separately can slow down a bit more than we'd like.

A similar performance problem arises when our arrays are async/lazy (aka Observables), processing values over time in response to events (see [Chapter 10](ch10.md)). In this scenario, only a single value comes down the event stream at a time, so processing that discrete value with two separate `filter(..)`s function calls isn't really such a big deal.

But what's not obvious is that each `filter(..)` method produces a separate observable. The overhead of pumping a value out of one observable into another can really add up. That's especially true since in these cases, it's not uncommon for thousands or millions of values to be processed; even such small overhead costs add up quickly.

The other downside is readability, especially when we need to repeat the same series of operations against multiple lists (or Observables). For example:

```js
zip(
    list1.filter( isLongEnough ).filter( isShortEnough ),
    list2.filter( isLongEnough ).filter( isShortEnough ),
    list3.filter( isLongEnough ).filter( isShortEnough )
)
```

Repetitive, right?

Wouldn't it be better (both for readability and performance) if we could combine the `isLongEnough(..)` predicate with the `isShortEnough(..)` predicate? You could do so manually:

```js
function isCorrectLength(str) {
    return isLongEnough( str ) && isShortEnough( str );
}
```

But that's not the FP way!

In [Chapter 9, we talked about fusion](ch9.md/#fusion) -- composing adjacent mapping functions. Recall:

```js
words
.map(
    pipe( removeInvalidChars, upper, elide )
);
```

Unfortunately, combining adjacent predicate functions doesn't work as easily as combining adjacent mapping functions. To understand why, think about the "shape" of the predicate function -- a sort of academic way of describing the signature of inputs and output. It takes a single value in, and it returns a `true` or a `false`.

If you tried `isShortEnough(isLongEnough(str))`, it wouldn't work properly. `isLongEnough(..)` will return `true`/`false`, not the string value that `isShortEnough(..)` is expecting. Bummer.

A similar frustration exists trying to compose two adjacent reducer functions. The "shape" of a reducer is a function that receives two values as input, and returns a single combined value. The output of a reducer as a single value is not suitable for input to another reducer expecting two inputs.

Moreover, the `reduce(..)` helper takes an optional `initialValue` input. Sometimes this can be omitted, but sometimes it has to be passed in. That even further complicates composition, since one reduction might need one `initialValue` and the other reduction might seem like it needs a different `initialValue`. How can we possibly do that if we only make one `reduce(..)` call with some sort of composed reducer?

Consider a chain like this:

```js
words
.map( strUppercase )
.filter( isLongEnough )
.filter( isShortEnough )
.reduce( strConcat, "" );
// "WRITTENSOMETHING"
```

Can you envision a composition that includes all of these steps: `map(strUppercase)`, `filter(isLongEnough)`, `filter(isShortEnough)`, `reduce(strConcat)`? The shape of each operator is different, so they won't directly compose together. We need to bend their shapes a little bit to fit them together.

Hopefully these observations have illustrated why simple fusion-style composition isn't up to the task. We need a more powerful technique, and transducing is that tool.

## How, Next

Let's talk about how we might derive a composition of mappers, predicates, and/or reducers.

Don't get too overwhelmed: you won't have to go through all these mental steps we're about to explore in your own programming. Once you understand and can recognize the problem transducing solves, you'll be able to just jump straight to using a `transduce(..)` utility from a FP library and move on with the rest of your application!

Let's jump in.

### Expressing Map/Filter as Reduce

The first trick we need to perform is expressing our `filter(..)` and `map(..)` calls as `reduce(..)` calls. Recall [how we did that in Chapter 9](ch9.md/#map-as-reduce):

```js
function strUppercase(str) { return str.toUpperCase(); }
function strConcat(str1,str2) { return str1 + str2; }

function strUppercaseReducer(list,str) {
    list.push( strUppercase( str ) );
    return list;
}

function isLongEnoughReducer(list,str) {
    if (isLongEnough( str )) list.push( str );
    return list;
}

function isShortEnoughReducer(list,str) {
    if (isShortEnough( str )) list.push( str );
    return list;
}

words
.reduce( strUppercaseReducer, [] )
.reduce( isLongEnoughReducer, [] )
.reduce( isShortEnoughReducer, [] )
.reduce( strConcat, "" );
// "WRITTENSOMETHING"
```

That's a decent improvement. We now have four adjacent `reduce(..)` calls instead of a mixture of three different methods all with different shapes. We still can't just `compose(..)` those four reducers, however, because they accept two arguments instead of one.

<a name="cheating"></a>

In [Chapter 9, we sort of cheated](ch9.md/#user-content-reducecheating) and used `list.push(..)` to mutate as a side effect rather than creating a whole new array to concatenate onto. Let's step back and be a bit more formal for now:

```js
function strUppercaseReducer(list,str) {
    return [ ...list, strUppercase( str ) ];
}

function isLongEnoughReducer(list,str) {
    if (isLongEnough( str )) return [ ...list, str ];
    return list;
}

function isShortEnoughReducer(list,str) {
    if (isShortEnough( str )) return [ ...list, str ];
    return list;
}
```

Later, we'll revisit whether creating a new array (e.g., `[...list,str]`) to concatenate onto is necessary here or not.

### Parameterizing the Reducers

Both filter reducers are almost identical, except they use a different predicate function. Let's parameterize that so we get one utility that can define any filter-reducer:

```js
function filterReducer(predicateFn) {
    return function reducer(list,val){
        if (predicateFn( val )) return [ ...list, val ];
        return list;
    };
}

var isLongEnoughReducer = filterReducer( isLongEnough );
var isShortEnoughReducer = filterReducer( isShortEnough );
```

Let's do the same parameterization of the `mapperFn(..)` for a utility to produce any map-reducer:

```js
function mapReducer(mapperFn) {
    return function reducer(list,val){
        return [ ...list, mapperFn( val ) ];
    };
}

var strUppercaseReducer = mapReducer( strUppercase );
```

Our chain still looks the same:

```js
words
.reduce( strUppercaseReducer, [] )
.reduce( isLongEnoughReducer, [] )
.reduce( isShortEnoughReducer, [] )
.reduce( strConcat, "" );
```

### Extracting Common Combination Logic

Look very closely at the preceding `mapReducer(..)` and `filterReducer(..)` functions. Do you spot the common functionality shared in each?

This part:

```js
return [ ...list, .. ];

// or
return list;
```

Let's define a helper for that common logic. But what shall we call it?

```js
function WHATSITCALLED(list,val) {
    return [ ...list, val ];
}
```

If you examine what that `WHATSITCALLED(..)` function does, it takes two values (an array and another value) and it "combines" them by creating a new array and concatenating the value onto the end of it. Very uncreatively, we could name this `listCombine(..)`:

```js
function listCombine(list,val) {
    return [ ...list, val ];
}
```

Let's now re-define our reducer helpers to use `listCombine(..)`:

```js
function mapReducer(mapperFn) {
    return function reducer(list,val){
        return listCombine( list, mapperFn( val ) );
    };
}

function filterReducer(predicateFn) {
    return function reducer(list,val){
        if (predicateFn( val )) return listCombine( list, val );
        return list;
    };
}
```

Our chain still looks the same (so we won't repeat it).

### Parameterizing the Combination

Our simple `listCombine(..)` utility is only one possible way that we might combine two values. Let's parameterize the use of it to make our reducers more generalized:

```js
function mapReducer(mapperFn,combinerFn) {
    return function reducer(list,val){
        return combinerFn( list, mapperFn( val ) );
    };
}

function filterReducer(predicateFn,combinerFn) {
    return function reducer(list,val){
        if (predicateFn( val )) return combinerFn( list, val );
        return list;
    };
}
```

To use this form of our helpers:

```js
var strUppercaseReducer = mapReducer( strUppercase, listCombine );
var isLongEnoughReducer = filterReducer( isLongEnough, listCombine );
var isShortEnoughReducer = filterReducer( isShortEnough, listCombine );
```

Defining these utilities to take two arguments instead of one is less convenient for composition, so let's use our `curry(..)` approach:

```js
var curriedMapReducer =
    curry( function mapReducer(mapperFn,combinerFn){
        return function reducer(list,val){
            return combinerFn( list, mapperFn( val ) );
        };
    } );

var curriedFilterReducer =
    curry( function filterReducer(predicateFn,combinerFn){
        return function reducer(list,val){
            if (predicateFn( val )) return combinerFn( list, val );
            return list;
        };
    } );

var strUppercaseReducer =
    curriedMapReducer( strUppercase )( listCombine );
var isLongEnoughReducer =
    curriedFilterReducer( isLongEnough )( listCombine );
var isShortEnoughReducer =
    curriedFilterReducer( isShortEnough )( listCombine );
```

That looks a bit more verbose, and probably doesn't seem very useful.

But this is actually necessary to get to the next step of our derivation. Remember, our ultimate goal here is to be able to `compose(..)` these reducers. We're almost there.

### Composing Curried

This step is the trickiest of all to visualize. So read slowly and pay close attention here.

Let's consider the curried functions from earlier, but without the `listCombine(..)` function having been passed in to each:

```js
var x = curriedMapReducer( strUppercase );
var y = curriedFilterReducer( isLongEnough );
var z = curriedFilterReducer( isShortEnough );
```

Think about the shape of all three of these intermediate functions, `x(..)`, `y(..)`, and `z(..)`. Each one expects a single combination function, and produces a reducer function with it.

Remember, if we wanted the independent reducers from all these, we could do:

```js
var upperReducer = x( listCombine );
var longEnoughReducer = y( listCombine );
var shortEnoughReducer = z( listCombine );
```

But what would you get back if you called `y(z)`, instead of `y(listCombine)`? Basically, what happens when passing `z` in as the `combinerFn(..)` for the `y(..)` call? That returned reducer function internally looks kinda like this:

```js
function reducer(list,val) {
    if (isLongEnough( val )) return z( list, val );
    return list;
}
```

See the `z(..)` call inside? That should look wrong to you, because the `z(..)` function is supposed to receive only a single argument (a `combinerFn(..)`), not two arguments (`list` and `val`). The shapes don't match. That won't work.

Let's instead look at the composition `y(z(listCombine))`. We'll break that down into two separate steps:

```js
var shortEnoughReducer = z( listCombine );
var longAndShortEnoughReducer = y( shortEnoughReducer );
```

We create `shortEnoughReducer(..)`, then we pass *it* in as the `combinerFn(..)` to `y(..)` instead of calling `y(listCombine)`; this new call produces `longAndShortEnoughReducer(..)`. Re-read that a few times until it clicks.

Now consider: what do `shortEnoughReducer(..)` and `longAndShortEnoughReducer(..)` look like internally? Can you see them in your mind?

```js
// shortEnoughReducer, from calling z(..):
function reducer(list,val) {
    if (isShortEnough( val )) return listCombine( list, val );
    return list;
}

// longAndShortEnoughReducer, from calling y(..):
function reducer(list,val) {
    if (isLongEnough( val )) return shortEnoughReducer( list, val );
    return list;
}
```

Do you see how `shortEnoughReducer(..)` has taken the place of `listCombine(..)` inside `longAndShortEnoughReducer(..)`? Why does that work?

Because **the shape of a `reducer(..)` and the shape of `listCombine(..)` are the same.** In other words, a reducer can be used as a combination function for another reducer; that's how they compose! The `listCombine(..)` function makes the first reducer, then *that reducer* can be used as the combination function to make the next reducer, and so on.

Let's test out our `longAndShortEnoughReducer(..)` with a few different values:

```js
longAndShortEnoughReducer( [], "nope" );
// []

longAndShortEnoughReducer( [], "hello" );
// ["hello"]

longAndShortEnoughReducer( [], "hello world" );
// []
```

The `longAndShortEnoughReducer(..)` utility is filtering out both values that are not long enough and values that are not short enough, and it's doing both these filterings in the same step. It's a composed reducer!

Take another moment to let that sink in. It still kinda blows my mind.

Now, to bring `x(..)` (the uppercase reducer producer) into the composition:

```js
var longAndShortEnoughReducer = y( z( listCombine) );
var upperLongAndShortEnoughReducer = x( longAndShortEnoughReducer );
```

As the name `upperLongAndShortEnoughReducer(..)` implies, it does all three steps at once -- a mapping and two filters! What it kinda look likes internally:

```js
// upperLongAndShortEnoughReducer:
function reducer(list,val) {
    return longAndShortEnoughReducer( list, strUppercase( val ) );
}
```

A string `val` is passed in, uppercased by `strUppercase(..)` and then passed along to `longAndShortEnoughReducer(..)`. *That* function only conditionally adds this uppercased string to the `list` if it's both long enough and short enough. Otherwise, `list` will remain unchanged.

It took my brain weeks to fully understand the implications of that juggling. So don't worry if you need to stop here and re-read a few (dozen!) times to get it. Take your time.

Now let's verify:

```js
upperLongAndShortEnoughReducer( [], "nope" );
// []

upperLongAndShortEnoughReducer( [], "hello" );
// ["HELLO"]

upperLongAndShortEnoughReducer( [], "hello world" );
// []
```

This reducer is the composition of the map and both filters! That's amazing!

Let's recap where we're at so far:

```js
var x = curriedMapReducer( strUppercase );
var y = curriedFilterReducer( isLongEnough );
var z = curriedFilterReducer( isShortEnough );

var upperLongAndShortEnoughReducer = x( y( z( listCombine ) ) );

words.reduce( upperLongAndShortEnoughReducer, [] );
// ["WRITTEN","SOMETHING"]
```

That's pretty cool. But let's make it even better.

`x(y(z( .. )))` is a composition. Let's skip the intermediate `x` / `y` / `z` variable names, and just express that composition directly:

```js
var composition = compose(
    curriedMapReducer( strUppercase ),
    curriedFilterReducer( isLongEnough ),
    curriedFilterReducer( isShortEnough )
);

var upperLongAndShortEnoughReducer = composition( listCombine );

words.reduce( upperLongAndShortEnoughReducer, [] );
// ["WRITTEN","SOMETHING"]
```

Think about the flow of "data" in that composed function:

1. `listCombine(..)` flows in as the combination function to make the filter-reducer for `isShortEnough(..)`.
2. *That* resulting reducer function then flows in as the combination function to make the filter-reducer for `isLongEnough(..)`.
3. Finally, *that* resulting reducer function flows in as the combination function to make the map-reducer for `strUppercase(..)`.

In the previous snippet, `composition(..)` is a composed function expecting a combination function to make a reducer; `composition(..)` here has a special name: transducer. Providing the combination function to a transducer produces the composed reducer:

```js
var transducer = compose(
    curriedMapReducer( strUppercase ),
    curriedFilterReducer( isLongEnough ),
    curriedFilterReducer( isShortEnough )
);

words
.reduce( transducer( listCombine ), [] );
// ["WRITTEN","SOMETHING"]
```

**Note:** We should make an observation about the `compose(..)` order in the previous two snippets, which may be confusing. Recall that in our original example chain, we `map(strUppercase)` and then `filter(isLongEnough)` and finally `filter(isShortEnough)`; those operations indeed happen in that order. But in [Chapter 4](ch4.md/#user-content-generalcompose), we learned that `compose(..)` typically has the effect of running its functions in reverse order of listing. So why don't we need to reverse the order *here* to get the same desired outcome? The abstraction of the `combinerFn(..)` from each reducer reverses the effective applied order of operations under the hood. So counter-intuitively, when composing a transducer, you actually want to list them in desired order of execution!

#### List Combination: Pure vs. Impure

As a quick aside, let's revisit our `listCombine(..)` combination function implementation:

```js
function listCombine(list,val) {
    return [ ...list, val ];
}
```

While this approach is pure, it has negative consequences for performance: for each step in the reduction, we're creating a whole new array to append the value onto, effectively throwing away the previous array. That's a lot of arrays being created and thrown away, which is not only bad for CPU but also GC memory churn.

By contrast, look again at the better-performing but impure version:

```js
function listCombine(list,val) {
    list.push( val );
    return list;
}
```

Thinking about `listCombine(..)` in isolation, there's no question it's impure and that's usually something we'd want to avoid. However, there's a bigger context we should consider.

`listCombine(..)` is not a function we interact with at all. We don't directly use it anywhere in the program; instead, we let the transducing process use it.

Back in [Chapter 5](ch5.md), we asserted that our goal with reducing side effects and defining pure functions was only that we expose pure functions to the API level of functions we'll use throughout our program. We observed that under the covers, inside a pure function, it can cheat for performance sake all it wants, as long as it doesn't violate the external contract of purity.

`listCombine(..)` is more an internal implementation detail of the transducing -- in fact, it'll often be provided by the transducing library for you! -- rather than a top-level method you'd interact with on a normal basis throughout your program.

Bottom line: I think it's perfectly acceptable, and advisable even, to use the performance-optimal impure version of `listCombine(..)`. Just make sure you document that it's impure with a code comment!

### Alternative Combination

So far, this is what we've derived with transducing:

```js
words
.reduce( transducer( listCombine ), [] )
.reduce( strConcat, "" );
// WRITTENSOMETHING
```

That's pretty good, but we have one final trick up our sleeve with transducing. And frankly, I think this part is what makes all this mental effort you've expended thus far, actually worth it.

Can we somehow "compose" these two `reduce(..)` calls to get it down to just one `reduce(..)`? Unfortunately, we can't just add `strConcat(..)` into the `compose(..)` call; because it's a reducer and not a combination-expecting function, its shape is not correct for the composition.

But let's look at these two functions side by side:

```js
function strConcat(str1,str2) { return str1 + str2; }

function listCombine(list,val) { list.push( val ); return list; }
```

If you squint your eyes, you can almost see how these two functions are interchangeable. They operate with different data types, but conceptually they do the same thing: combine two values into one.

In other words, `strConcat(..)` is a combination function!

That means we can use *it* instead of `listCombine(..)` if our end goal is to get a string concatenation rather than a list:

```js
words.reduce( transducer( strConcat ), "" );
// WRITTENSOMETHING
```

Boom! That's transducing for you. I won't actually drop the mic here, but just gently set it down...

## What, Finally

Take a deep breath. That was a lot to digest.

Clearing our brains for a minute, let's turn our attention back to just using transducing in our applications without jumping through all those mental hoops to derive how it works.

Recall the helpers we defined earlier; let's rename them for clarity:

```js
var transduceMap =
    curry( function mapReducer(mapperFn,combinerFn){
        return function reducer(list,v){
            return combinerFn( list, mapperFn( v ) );
        };
    } );

var transduceFilter =
    curry( function filterReducer(predicateFn,combinerFn){
        return function reducer(list,v){
            if (predicateFn( v )) return combinerFn( list, v );
            return list;
        };
    } );
```

Also recall that we use them like this:

```js
var transducer = compose(
    transduceMap( strUppercase ),
    transduceFilter( isLongEnough ),
    transduceFilter( isShortEnough )
);
```

`transducer(..)` still needs a combination function (like `listCombine(..)` or `strConcat(..)`) passed to it to produce a transduce-reducer function, which can then be used (along with an initial value) in `reduce(..)`.

But to express all these transducing steps more declaratively, let's make a `transduce(..)` utility that does these steps for us:

```js
function transduce(transducer,combinerFn,initialValue,list) {
    var reducer = transducer( combinerFn );
    return list.reduce( reducer, initialValue );
}
```

Here's our running example, cleaned up:

```js
var transducer = compose(
    transduceMap( strUppercase ),
    transduceFilter( isLongEnough ),
    transduceFilter( isShortEnough )
);

transduce( transducer, listCombine, [], words );
// ["WRITTEN","SOMETHING"]

transduce( transducer, strConcat, "", words );
// WRITTENSOMETHING
```

Not bad, huh!? See the `listCombine(..)` and `strConcat(..)` functions used interchangeably as combination functions?

### Transducers.js

Finally, let's illustrate our running example using the [`transducers-js` library](https://github.com/cognitect-labs/transducers-js):

```js
var transformer = transducers.comp(
    transducers.map( strUppercase ),
    transducers.filter( isLongEnough ),
    transducers.filter( isShortEnough )
);

transducers.transduce( transformer, listCombine, [], words );
// ["WRITTEN","SOMETHING"]

transducers.transduce( transformer, strConcat, "", words );
// WRITTENSOMETHING
```

Looks almost identical to above.

**Note:** The preceding snippet uses `transformers.comp(..)` because the library provides it, but in this case our [`compose(..)` from Chapter 4](ch4.md/#user-content-generalcompose) would produce the same outcome. In other words, composition itself isn't a transducing-sensitive operation.

The composed function in this snippet is named `transformer` instead of `transducer`. That's because if we call `transformer( listCombine )` (or `transformer( strConcat )`), we won't get a straight-up transduce-reducer function as earlier.

`transducers.map(..)` and `transducers.filter(..)` are special helpers that adapt regular predicate or mapper functions into functions that produce a special transform object (with the transducer function wrapped underneath); the library uses these transform objects for transducing. The extra capabilities of this transform object abstraction are beyond what we'll explore, so consult the library's documentation for more information.

Because calling `transformer(..)` produces a transform object and not a typical binary transduce-reducer function, the library also provides `toFn(..)` to adapt the transform object to be useable by native array `reduce(..)`:

```js
words.reduce(
    transducers.toFn( transformer, strConcat ),
    ""
);
// WRITTENSOMETHING
```

`into(..)` is another provided helper that automatically selects a default combination function based on the type of empty/initial value specified:

```js
transducers.into( [], transformer, words );
// ["WRITTEN","SOMETHING"]

transducers.into( "", transformer, words );
// WRITTENSOMETHING
```

When specifying an empty `[]` array, the `transduce(..)` called under the covers uses a default implementation of a function like our `listCombine(..)` helper. But when specifying an empty `""` string, something like our `strConcat(..)` is used. Cool!

As you can see, the `transducers-js` library makes transducing pretty straightforward. We can very effectively leverage the power of this technique without getting into the weeds of defining all those intermediate transducer-producing utilities ourselves.

## Summary

To transduce means to transform with a reduce. More specifically, a transducer is a composable reducer.

We use transducing to compose adjacent `map(..)`, `filter(..)`, and `reduce(..)` operations together. We accomplish this by first expressing `map(..)`s and `filter(..)`s as `reduce(..)`s, and then abstracting out the common combination operation to create unary reducer-producing functions that are easily composed.

Transducing primarily improves performance, which is especially obvious if used on an observable.

But more broadly, transducing is how we express a more declarative composition of functions that would otherwise not be directly composable. The result, if used appropriately as with all other techniques in this book, is clearer, more readable code! A single `reduce(..)` call with a transducer is easier to reason about than tracing through multiple `reduce(..)` calls.



================================================
FILE: manuscript/apB.md
================================================
# Functional-Light JavaScript
# Appendix B: The Humble Monad

Let me just start off this appendix by admitting: I did not know much about what a monad was before starting to write this appendix. And it took a lot of mistakes to get something sensible. If you don't believe me, go look at the commit history of this appendix in the [Github repository for this book](https://github.com/getify/Functional-Light-JS)!

I am including the topic of monads in the book because it's part of the journey that every developer will encounter while learning FP, just as I have in this book writing.

We're basically ending this book with a brief glimpse at monads, whereas most other FP literature kinda almost starts with monads! I do not encounter in my "Functional-Light" programming much of a need to think explicitly in terms of monads, so that's why this material is more bonus than main core. But that's not to say monads aren't useful or prevalent -- they very much are.

There's a bit of a joke around the JavaScript FP world that pretty much everybody has to write their own tutorial or blog post on what a monad is, like the writing of it alone is some rite of passage. Over the years, monads have variously been depicted as burritos, onions, and all sorts of other wacky conceptual abstractions. I hope there's none of that silly business going on here!

> A monad is just a monoid in the category of endofunctors.

We started the preface with this quote, so it seems fitting we come back to it here. But no, we won't be talking about monoids, endofunctors, or category theory. That quote is not only condescending, but totally unhelpful.

My only hope for what you get out of this discussion is to not be scared of the term monad or the concept anymore -- I have been, for years! -- and to be able to recognize them when you see them. You might, just maybe, even use them on occasion.

## Type

There's a huge area of interest in FP that we've basically stayed entirely away from throughout this book: type theory. I'm not going to get very deep into type theory, because quite frankly I'm not qualified to do so. And you wouldn't appreciate it even if I did.

But what I will say is that a monad is basically a value type.

The number `42` has a value type (number!) that brings with it certain characteristics and capabilities that we rely on. The string `"42"` may look very similar, but it has a different purpose in our program.

In object-oriented programming, when you have a set of data (even a single discrete value) and you have some behavior you want to bundle with it, you create an object/class to represent that "type". Instances are then members of that type. This practice generally goes by the name "data structures".

I'm going to use the notion of data structures very loosely here, and assert that we may find it useful in a program to define a set of behaviors and constraints for a certain value, and bundle them together with that value into a single abstraction. That way, as we work with one or more of those kinds of values in our program, their behaviors come along for free and will make working with them more convenient. And by convenient, I mean more declarative and approachable for the reader of your code!

A monad is a data structure. It's a type. It's a set of behaviors that are specifically designed to make working with a value predictable.

Recall in [Chapter 9 that we talked about functors](ch9.md/#a-word-functors): a value along with a map-like utility to perform an operation on all its constitute data members. A monad is a functor that includes some additional behavior.

## Loose Interface

Actually, a monad isn't a single data type, it's really more like a related collection of data types. It's kind of an interface that's implemented differently depending on the needs of different values. Each implementation is a different type of monad.

For example, you may read about the "Identity Monad", the "IO Monad", the "Maybe Monad", the "Either Monad", or a variety of others. Each of these has the basic monad behavior defined, but it extends or overrides the interactions according to the use cases for each different type of monad.

It's a little more than an interface though, because it's not just the presence of certain API methods that makes an object a monad. There's a certain set of guarantees about the interactions of these methods that is necessary, to be monadic. These well-known invariants are critical to usage of monads improving readability by familiarity; otherwise, it's just an ad hoc data structure that must be fully read to be understood by the reader.

As a matter of fact, there's not even just one single unified agreement on the names of these monadic methods, the way a true interface would mandate; a monad is more like a loose interface. Some people call a certain method `bind(..)`, some call it `chain(..)`, some call it `flatMap(..)`, and so on.

So a monad is an object data structure with sufficient methods (of practically any name or sort) that at a minimum satisfy the main behavioral requirements of the monad definition. Each kind of monad has a different kind of extension above the minimum. But, because they all have an overlap in behavior, using two different kinds of monads together is still straightforward and predictable.

It's in that sense that monads are sort of like an interface.

## Just a Monad

A basic primitive monad underlying many other monads you will run across is called Just. It's *just* a simple monadic wrapper for any regular (aka, non-empty) value.

Since a monad is a type, you might think we'd define `Just` as a class to be instantiated. That's a valid way of doing it, but it introduces `this`-binding issues in the methods that I don't want to juggle; instead, I'm going to stick with just a simple function approach.

Here's a basic implementation:

```js
function Just(val) {
    return { map, chain, ap, inspect };

    // *********************

    function map(fn) { return Just( fn( val ) ); }

    // aka: bind, flatMap
    function chain(fn) { return fn( val ); }

    function ap(anotherMonad) { return anotherMonad.map( val ); }

    function inspect() {
        return `Just(${ val })`;
    }
}
```

**Note:** The `inspect(..)` method is included here only for our demonstration purposes. It serves no direct role in the monadic sense.

You'll notice that whatever `val` value a `Just(..)` instance holds, it's never changed. All monad methods create new monad instances instead of mutating the monad's value itself.

Don't worry if most of this doesn't make sense right now. We're not gonna obsess too much over the details or the math/theory behind the design of the monad. Instead, we'll focus more on illustrating what we can do with them.

### Working with Monad Methods

All monad instances will have `map(..)`, `chain(..)` (also called `bind(..)` or `flatMap(..)`), and `ap(..)` methods. The purpose of these methods and their behavior is to provide a standardized way of multiple monad instances interacting with each other.

Let's look first at the monadic `map(..)` function. Like `map(..)` on an array (see [Chapter 9](ch9.md/#map)) that calls a mapper function with its value(s) and produces a new array, a monad's `map(..)` calls a mapper function with the monad's value, and whatever is returned is wrapped in a new Just monad instance:

```js
var A = Just( 10 );
var B = A.map( v => v * 2 );

B.inspect();                // Just(20)
```

Monadic `chain(..)` kinda does the same thing as `map(..)`, but then it sort of unwraps the resulting value from its new monad. However, instead of thinking informally about "unwrapping" a monad, the more formal explanation would be that `chain(..)` flattens the monad. Consider:

```js
var A = Just( 10 );
var eleven = A.chain( v => v + 1 );

eleven;                     // 11
typeof eleven;              // "number"
```

`eleven` is the actual primitive number `11`, not a monad holding that value.

To connect this `chain(..)` method conceptually to stuff we've already learned, we'll point out that many monad implementations name this method `flatMap(..)`. Now, recall from [Chapter 9 what `flatMap(..)`](ch9.md/#user-content-flatmap) does (as compared to `map(..)`) with an array:

```js
var x = [3];

map( v => [v,v+1], x );         // [[3,4]]
flatMap( v => [v,v+1], x );     // [3,4]
```

See the difference? The mapper function `v => [v,v+1]` results in a `[3,4]` array, which ends up in the single first position of the outer array, so we get `[[3,4]]`. But `flatMap(..)` flattens out the inner array into the outer array, so we get just `[3,4]` instead.

That's the same kind of thing going on with a monad's `chain(..)` (often referred to as `flatMap(..)`). Instead of getting a monad holding the value as `map(..)` does, `chain(..)` additionally flattens the monad into the underlying value. Actually, instead of creating that intermediate monad only to immediately flatten it, `chain(..)` is generally implemented more performantly to just take a shortcut and not create the monad in the first place. Either way, the end result is the same.

One way to illustrate `chain(..)` in this manner is in combination with the `identity(..)` utility (see [Chapter 3](ch3.md/#one-on-one)), to effectively extract a value from a monad:

```js
var identity = v => v;

A.chain( identity );        // 10
```

`A.chain(..)` calls `identity(..)` with the value in `A`, and whatever value `identity(..)` returns (`10` in this case) just comes right out without any intervening monad. In other words, from that earlier `Just(..)` code listing, we wouldn't actually need to include that optional `inspect(..)` helper, as `chain(identity)` accomplishes the same goal; it's purely for ease of debugging as we learn monads.

At this point, hopefully both `map(..)` and `chain(..)` feel fairly reasonable to you.

By contrast, a monad's `ap(..)` method will likely be much less intuitive at first glance. It will seem like a strange contortion of interaction, but there's deep and important reasoning behind the design. Let's take a moment to break it down.

`ap(..)` takes the value wrapped in a monad and "applies" it to another monad using that other monad's `map(..)`. OK, fine so far.

However, `map(..)` always expects a function. So that means the monad you call `ap(..)` on has to actually contain a function as its value, to pass to that other monad's `map(..)`.

Confused? Yeah, not what you might have expected. We'll try to briefly illuminate, but just expect that these things will be fuzzy for a while until you've had a lot more exposure and practice with monads.

We'll define `A` as a monad that contains a value `10`, and `B` as a monad that contains the value `3`:

```js
var A = Just( 10 );
var B = Just( 3 );

A.inspect();                // Just(10)
B.inspect();                // Just(3)
```

Now, how could we make a new monad where the values `10` and `3` had been added together, say via a `sum(..)` function? Turns out `ap(..)` can help.

To use `ap(..)`, we said we first need to construct a monad that holds a function. Specifically, we need one that holds a function that itself holds (remembers via closure) the value in `A`. Let that sink in for a moment.

To make a monad from `A` that holds a value-containing function, we call `A.map(..)`, giving it a curried function that "remembers" that extracted value (see [Chapter 3](ch3.md/#one-at-a-time)) as its first argument. We'll call this new function-containing monad `C`:

```js
function sum(x,y) { return x + y; }

var C = A.map( curry( sum ) );

C.inspect();
// Just(function curried...)
```

Think about how that works. The curried `sum(..)` function is expecting two values to do its work, and we give it the first of those values by having `A.map(..)` extract `10` and pass it in. `C` now holds the function that remembers `10` via closure.

Now, to get the second value (`3` inside `B`) passed to the waiting curried function in `C`:

```js
var D = C.ap( B );

D.inspect();                // Just(13)
```

The value `10` came out of `C`, and `3` came out of `B`, and `sum(..)` added them together to `13` and wrapped that in the monad `D`. Let's put the two steps together so you can see their connection more clearly:

```js
var D = A.map( curry( sum ) ).ap( B );

D.inspect();                // Just(13)
```

To illustrate what `ap(..)` is helping us with, we could have achieved the same result this way:

```js
var D = B.map( A.chain( curry( sum ) ) );

D.inspect();                // Just(13);
```

And that of course is just a composition (see [Chapter 4](ch4.md)):

```js
var D = compose( B.map, A.chain, curry )( sum );

D.inspect();                // Just(13)
```

Cool, huh!?

If the *how* of this discussion on monad methods is unclear so far, go back and re-read. If the *why* is elusive, just hang in there. Monads so easily confound developers, that's *just* how it is!

## Maybe

It's very common in FP material to cover well-known monads like Maybe. Actually, the Maybe monad is a particular pairing of two other simpler monads: Just and Nothing.

We've already seen Just; Nothing is a monad that holds an empty value. Maybe is a monad that either holds a Just or a Nothing.

Here's a minimal implementation of Maybe:

```js
var Maybe = { Just, Nothing, of/* aka: unit, pure */: Just };

function Just(val) { /* .. */ }

function Nothing() {
    return { map: Nothing, chain: Nothing, ap: Nothing, inspect };

    // *********************

    function inspect() {
        return "Nothing";
    }
}
```

**Note:** `Maybe.of(..)` (sometimes referred to as `unit(..)` or `pure(..)`) is a convenience alias for `Just(..)`.

In contrast to `Just()` instances, `Nothing()` instances have no-op definitions for all monadic methods. So if such a monad instance shows up in any monadic operations, it has the effect of basically short-circuiting to have no behavior happen. Notice there's no imposition here of what "empty" means -- your code gets to decide that. More on that later.

In Maybe, if a value is non-empty, it's represented by an instance of `Just(..)`; if it's empty, it's represented by an instance of `Nothing()`.

But the importance of this kind of monad representation is that whether we have a `Just(..)` instance or a `Nothing()` instance, we'll use the API methods the same.

The power of the Maybe abstraction is to encapsulate that behavior/no-op duality implicitly.

### Different Maybes

Many implementations of a JavaScript Maybe monad include a check (usually in `map(..)`) to see if the value is `null`/`undefined`, and skipping the behavior if so. In fact, Maybe is trumpeted as being valuable precisely because it sort of automatically short-circuits its behavior with the encapsulated empty-value check.

Here's how Maybe is usually illustrated:

```js
// instead of unsafe `console.log( someObj.something.else.entirely )`:

Maybe.of( someObj )
.map( prop( "something" ) )
.map( prop( "else" ) )
.map( prop( "entirely" ) )
.map( console.log );
```

In other words, if at any point in the chain we get a `null`/`undefined` value, the Maybe magically switches into no-op mode -- it's now a `Nothing()` monad instance! -- and stops doing anything for the rest of the chain. That makes the nested-property access safe against throwing JS exceptions if some property is missing/empty. That's cool, and a nice helpful abstraction for sure!

But... ***that approach to Maybe is not a pure monad.***

The core spirit of a Monad says that it must be valid for all values and cannot do any inspection of the value, at all -- not even a null check. So those other implementations are cutting corners for the sake of convenience. It's not a huge deal, but when it comes to learning something, you should probably learn it in its purest form first before you go bending the rules.

The earlier implementation of the Maybe monad I provided differs from other Maybes primarily in that it does not have the empty-check in it. Also, we present `Maybe` merely as a loose pairing of `Just(..)`/`Nothing()`.

So wait. If we don't get the automatic short-circuiting, why is Maybe useful at all?!? That seems like its whole point.

Never fear! We can simply provide the empty-check externally, and the rest of the short-circuiting behavior of the Maybe monad will work just fine. Here's how you could do the nested-property access (`someObj.something.else.entirely`) from before, but more "correctly":

```js
function isEmpty(val) {
    return val === null || val === undefined;
}

var safeProp = curry( function safeProp(prop,obj){
    if (isEmpty( obj[prop] )) return Maybe.Nothing();
    return Maybe.of( obj[prop] );
} );

Maybe.of( someObj )
.chain( safeProp( "something" ) )
.chain( safeProp( "else" ) )
.chain( safeProp( "entirely" ) )
.map( console.log );
```

We made a `safeProp(..)` that does the empty-check, and selects either a `Nothing()` monad instance if so, or wraps the value in a `Just(..)` instance (via `Maybe.of(..)`). Then instead of `map(..)`, we use `chain(..)` which knows how to "unwrap" the monad that `safeProp(..)` returns.

We get the same chain short-circuiting upon encountering an empty value. We just don't embed that logic into the Maybe.

The benefit of the monad, and Maybe specifically, is that our `map(..)` and `chain(..)` methods have a consistent and predictable interaction regardless of which kind of monad comes back. That's pretty cool!

## Humble

Now that we have a little more understanding of Maybe and what it does, I'm going to put a little twist on it -- and add some self-deferential humor to our discussion -- by inventing the Maybe+Humble monad. Technically, `MaybeHumble(..)` is not a monad itself, but a factory function that produces a Maybe monad instance.

Humble is an admittedly contrived data structure wrapper that uses Maybe to track the status of an `egoLevel` number. Specifically, `MaybeHumble(..)`-produced monad instances only operate affirmatively if their ego-level value is low enough (less than `42`!) to be considered humble; otherwise it's a `Nothing()` no-op. That should sound a lot like Maybe; it's pretty similar!

Here's the factory function for our Maybe+Humble monad:

```js
function MaybeHumble(egoLevel) {
    // accept anything other than a number that's 42 or higher
    return !(Number( egoLevel ) >= 42) ?
        Maybe.of( egoLevel ) :
        Maybe.Nothing();
}
```

You'll notice that this factory function is kinda like `safeProp(..)`, in that it uses a condition to decide if it should pick the `Just(..)` or the `Nothing()` part of the Maybe.

Let's illustrate some basic usage:

```js
var bob = MaybeHumble( 45 );
var alice = MaybeHumble( 39 );

bob.inspect();              // Nothing
alice.inspect();            // Just(39)
```

What if Alice wins a big award and is now a bit more proud of herself?

```js
function winAward(ego) {
    return MaybeHumble( ego + 3 );
}

alice = alice.chain( winAward );
alice.inspect();            // Nothing
```

The `MaybeHumble( 39 + 3 )` call creates a `Nothing()` monad instance to return back from the `chain(..)` call, so now Alice doesn't qualify as humble anymore.

Now, let's use a few monads together:

```js
var bob = MaybeHumble( 41 );
var alice = MaybeHumble( 39 );

var teamMembers = curry( function teamMembers(ego1,ego2){
    console.log( `Our humble team's egos: ${ego1} ${ego2}` );
} );

bob.map( teamMembers ).ap( alice );
// Our humble team's egos: 41 39
```

Recalling the usage of `ap(..)` from earlier, we can now explain how this code works.

Because `teamMembers(..)` is curried, the `bob.map(..)` call passes in the `bob` ego level (`41`), and creates a monad instance with the remaining function wrapped up. Calling `ap(alice)` on *that* monad calls `alice.map(..)` and passes to it the function from the monad. The effect is that both the `bob` and `alice` monad's numeric values have been provided to `teamMembers(..)` function, printing out the message as shown.

However, if either or both monads are actually `Nothing()` instances (because their ego level was too high):

```js
var frank = MaybeHumble( 45 );

bob.map( teamMembers ).ap( frank );
// ..no output..

frank.map( teamMembers ).ap( bob );
// ..no output..
```

`teamMembers(..)` never gets called (and no message is printed), because `frank` is a `Nothing()` instance. That's the power of the Maybe monad, and our `MaybeHumble(..)` factory allows us to select based on the ego level. Cool!

### Humility

One more example to illustrate the behaviors of our Maybe+Humble data structure:

```js
function introduction() {
    console.log( "I'm just a learner like you! :)" );
}

var egoChange = curry( function egoChange(amount,concept,egoLevel) {
    console.log( `${amount > 0 ? "Learned" : "Shared"} ${concept}.` );
    return MaybeHumble( egoLevel + amount );
} );

var learn = egoChange( 3 );

var learner = MaybeHumble( 35 );

learner
.chain( learn( "closures" ) )
.chain( learn( "side effects" ) )
.chain( learn( "recursion" ) )
.chain( learn( "map/reduce" ) )
.map( introduction );
// Learned closures.
// Learned side effects.
// Learned recursion.
// ..nothing else..
```

Unfortunately, the learning process seems to have been cut short. You see, I've found that learning a bunch of stuff without sharing with others inflates your ego too much and is not good for your skills.

Let's try a better approach to learning:

```js
var share = egoChange( -2 );

learner
.chain( learn( "closures" ) )
.chain( share( "closures" ) )
.chain( learn( "side effects" ) )
.chain( share( "side effects" ) )
.chain( learn( "recursion" ) )
.chain( share( "recursion" ) )
.chain( learn( "map/reduce" ) )
.chain( share( "map/reduce" ) )
.map( introduction );
// Learned closures.
// Shared closures.
// Learned side effects.
// Shared side effects.
// Learned recursion.
// Shared recursion.
// Learned map/reduce.
// Shared map/reduce.
// I'm just a learner like you! :)
```

Sharing while you learn. That's the best way to learn more and learn better.

## Summary

What is a monad, anyway? A monad is a value type, an interface, an object data structure with encapsulated behaviors.

But none of those definitions are particularly useful. Here's an attempt at something better: **a monad is how you organize behavior around a value in a more declarative way.**

As with everything else in this book, use monads where they are helpful but don't use them just because everyone else talks about them in FP. Monads aren't a universal silver bullet, but they do offer some utility when used conservatively.


================================================
FILE: manuscript/apC.md
================================================
# Functional-Light JavaScript
# Appendix C: FP Libraries

If you've been reading this book from start to finish, take a minute to stop and look back how far you've come since [Chapter 1](ch1.md). It's been quite a journey. I hope you've learned a lot and gained insight into thinking functionally for your own programs.

I want to close this book leaving you with some quick pointers of working with common/popular FP libraries. This is not an exhaustive documentation on each, but a quick glance at the things you should be aware of as you venture beyond "Functional-Light" into broader FP.

Wherever possible, I recommend you *not* reinvent any wheels. If you find an FP library that suits your needs, use it. Only use the ad hoc helper utilities from this book -- or invent ones of your own! -- if you can't find a suitable library method for your circumstance.

## Stuff to Investigate

Let's expand the [list of FP libraries to be aware of, from Chapter 1](ch1.md/#libraries). We won't cover all of these (as there's a lot of overlap), but here are the ones that should probably be on your radar screen:

* [Ramda](http://ramdajs.com): General FP Utilities
* [Sanctuary](https://github.com/sanctuary-js/sanctuary): Ramda Companion for FP Types
* [lodash/fp](https://github.com/lodash/lodash/wiki/FP-Guide): General FP Utilities
* [functional.js](http://functionaljs.com/): General FP Utilities
* [Immutable](https://github.com/facebook/immutable-js): Immutable Data Structures
* [Mori](https://github.com/swannodette/mori): (ClojureScript Inspired) Immutable Data Structures
* [Seamless-Immutable](https://github.com/rtfeldman/seamless-immutable): Immutable Data Helpers
* [transducers-js](https://github.com/cognitect-labs/transducers-js): Transducers
* [monet.js](https://github.com/monet/monet.js): Monadic Types

There are dozens of other fine libraries not on this list. Just because it's not on my list here doesn't mean it's not good, nor is this list a particular endorsement. It's just a quick glance at the landscape of FP-in-JavaScript. A much longer list of FP resources can be [found here](https://github.com/stoeffel/awesome-fp-js).

One resource that's extremely important to the FP world -- it's not a library but more an encyclopedia! -- is [Fantasy Land](https://github.com/fantasyland/fantasy-land) (aka FL).

This is definitely not light reading for the faint of heart. It's a complete detailed roadmap of all of FP as it's interpreted in JavaScript. FL has become a de facto standard for JavaScript FP libraries to adhere to, to ensure maximum interoperability.

Fantasy Land is pretty much the exact opposite of "Functional-Light". It's the full-on no-holds-barred approach to FP in JavaScript. That said, as you venture beyond this book, it's likely that FL will be on that road for you. I'd recommend you bookmark it, and go back to it after you've had at least six months of real-world practice with this book's concepts.

## Ramda (0.23.0)

From the [Ramda documentation](http://ramdajs.com/):

> Ramda functions are automatically curried.
>
> The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.

I find that design decision to be one of Ramda's strengths. It's also important to note that Ramda's form of currying (as with most libraries, it seems) is the ["loose currying" we talked about in Chapter 3](ch3.md/#user-content-loosecurry).

The [final example of Chapter 3](ch3.md/#user-content-finalshortlong) -- recall defining a point-free `printIf(..)` utility -- can be done with Ramda like this:

```js
function output(msg) {
    console.log( msg );
}

function isShortEnough(str) {
    return str.length <= 5;
}

var isLongEnough = R.complement( isShortEnough );

var printIf = R.partial( R.flip( R.when ), [output] );

var msg1 = "Hello";
var msg2 = msg1 + " World";

printIf( isShortEnough, msg1 );            // Hello
printIf( isShortEnough, msg2 );

printIf( isLongEnough, msg1 );
printIf( isLongEnough, msg2 );            // Hello World
```

A few differences to point out compared to [Chapter 3's approach](ch3.md/#user-content-finalshortlong):

* We use `R.complement(..)` instead of `not(..)` to create a negating function `isLongEnough(..)` around `isShortEnough(..)`.

* We use `R.flip(..)` instead of `reverseArgs(..)`. It's important to note that `R.flip(..)` only swaps the first two arguments, whereas `reverseArgs(..)` reverses all of them. In this case, `flip(..)` is more convenient for us, so we don't need to do `partialRight(..)` or any of that kind of juggling.

* `R.partial(..)` takes all of its subsequent arguments (beyond the function) as a single array.

* Because Ramda is using loose currying, we don't need to use `R.uncurryN(..)` to get a `printIf(..)` that takes both its arguments. If we did, it would look like `R.uncurryN( 2, .. )` wrapped around the `R.partial(..)` call; but that's not necessary.

Ramda is a very popular and powerful library. It's a really good place to start if you're practicing adding FP to your code base.

## Lodash/fp (4.17.4)

Lodash is one of the most popular libraries in the entire JS ecosystem. They publish an "FP-friendly" version of their API as ["lodash/fp"](https://github.com/lodash/lodash/wiki/FP-Guide).

In [Chapter 9, we looked at composing standalone list operations](ch9.md/#composing-standalone-utilities) (`map(..)`, `filter(..)`, and `reduce(..)`). Here's how we could do it with "lodash/fp":

```js
var sum = (x,y) => x + y;
var double = x => x * 2;
var isOdd = x => x % 2 == 1;

fp.compose( [
    fp.reduce( sum )( 0 ),
    fp.map( double ),
    fp.filter( isOdd )
] )
( [1,2,3,4,5] );                    // 18
```

Instead of the more familiar `_.` namespace prefix, "lodash/fp" defines its methods with `fp.` as the namespace prefix. I find that a helpful distinguisher, and also generally more easy on my eyes than `_.` anyway!

Notice that `fp.compose(..)` (also known as `_.flowRight(..)` in lodash proper) takes an array of functions instead of individual arguments.

You cannot beat the stability, widespread community support, and performance of lodash. It's a solid bet for your FP explorations.

## Mori (0.3.2)

In [Chapter 6](ch6.md), we already briefly glanced at the Immutable.js library, probably the most well-known for immutable data structures.

Let's instead look at another popular library: [Mori](https://github.com/swannodette/mori). Mori is designed with a different (ostensibly more FP-like) take on API: it uses standalone functions instead of methods directly on the values.

```js
var state = mori.vector( 1, 2, 3, 4 );

var newState = mori.assoc(
    mori.into( state, Array.from( {length: 39} ) ),
    42,
    "meaning of life"
);

state === newState;                        // false

mori.get( state, 2 );                    // 3
mori.get( state, 42 );                    // undefined

mori.get( newState, 2 );                // 3
mori.get( newState, 42 );                // "meaning of life"

mori.toJs( newState ).slice( 1, 3 );    // [2,3]
```

Some interesting things to point out about Mori for this example:

* We're using a `vector` instead of a `list` (as one might assume), mostly because the documentation says it behaves more like we expect JS arrays to be.

* We cannot just randomly set a position past the end of the vector like we can with JS arrays; that throws an exception. So we have to first "grow" the vector using `mori.into(..)` with an array of the appropriate size of extra slots we want. Once we have a vector with 43 slots (4 + 39), we can set the final slot (position `42`) to the `"meaning of life"` value using the `mori.assoc(..)` method.

* The intermediate step of creating a larger vector with `mori.into(..)` and then creating another from it with `mori.assoc(..)` might sound inefficient. But the beauty of immutable data structures is that no cloning is going on here. Each time a "change" is made, the new data structure is just tracking the difference from the previous state.

Mori is heavily inspired by ClojureScript. Its API will be very familiar if you have experience (or currently work in!) that language. Since I don't have that experience, I find the method names a little strange to get used to.

But I really like the standalone function design instead of methods on values. Mori also has some functions that automatically return regular JS arrays, which is a nice convenience.

## Bonus: FPO

In [Chapter 2, we introduced a pattern](ch2.md/#named-arguments) for dealing with arguments called "named arguments", which in JS means using an object at the call-site to map properties to destructured function parameters:

```js
function foo( {x,y} = {} ) {
    console.log( x, y );
}

foo( {
    y: 3
} );                    // undefined 3
```

Then in [Chapter 3, we talked about extending](ch3.md/#order-matters) our ideas of currying and partial application to work with named arguments, like this:

```js
function foo({ x, y, z } = {}) {
    console.log( `x:${x} y:${y} z:${z}` );
}

var f1 = curryProps( foo, 3 );

f1( {y: 2} )( {x: 1} )( {z: 3} );
```

One major benefit of this style is being able to pass arguments (even with currying or partial application!) in any order without needing to do `reverseArgs(..)`-style juggling of parameters. Another is being able to omit an optional argument by simply not specifying it, instead of passing an ugly placeholder.

In my journey learning FP, I've regularly been frustrated by both of those irritations of functions with traditional positional arguments; thus I've really appreciated the named arguments style for addressing those concerns.

One day, I was musing about with this style of FP coding, and wondered what it would be like if a whole FP library had all its API methods exposed in this style. I started experimenting, showed those experiments to a few FP folks, and got some positive feedback.

From those experiments, eventually the [FPO](https://github.com/getify/fpo) (pronounced "eff-poh") library was born; FPO stands for FP-with-Objects, in case you were wondering.

From the documentation:

```js
// Ramda's `reduce(..)`
R.reduce(
    (acc,v) => acc + v,
    0,
    [3,7,9]
);  // 19

// FPO named-argument method style
FPO.reduce({
    arr: [3,7,9],
    fn: ({acc,v}) => acc + v
}); // 19
```

With traditional library implementations of `reduce(..)` (like Ramda), the initial value parameter is in the middle, and not optional. FPO's `reduce(..)` method can take the arguments in any order, and you can omit the optional initial value if desired.

As with most other FP libraries, FPO's API methods are automatically loose-curried, so you can not only provide arguments in any order, but specialize the function by providing its arguments over multiple calls:

```js
var f = FPO.reduce({ arr: [3,7,9] });

// later

f({ fn: ({acc,v}) => acc + v });    // 19
```

Lastly, all of FPO's API methods are also exposed using the traditional positional arguments style -- you'll find they're all very similar to Ramda and other libraries -- under the `FPO.std.*` namespace:

```js
FPO.std.reduce(
    (acc,v) => acc + v,
    undefined,
    [3,7,9]
);  // 19
```

If FPO's named argument form of FP appeals to you, perhaps check out the library and see what you think. It has a full test suite and most of the major FP functionality you'd expect, including everything we covered in this text to get you up and going with Functional-Light JavaScript!

## Bonus #2: fasy

FP iterations (`map(..)`, `filter(..)`, etc.) are almost always modeled as synchronous operations, meaning we eagerly run through all the steps of the iteration immediately. As a matter of fact, other FP patterns like composition and even transducing are also iterations, and are also modeled exactly this way.

But what happens if one or more of the steps in an iteration needs to complete asynchronously? You might jump to thinking that Observables (see [Chapter 10](ch10.md/#observables)) is the natural answer, but they're not what we need.

Let me quickly illustrate.

Imagine you have a list of URLs that represent images you want to load into a web page. The fetching of the images is asynchronous, obviously. So, this isn't going to work quite like you'd hope:

```js
var imageURLs = [
    "https://some.tld/image1.png",
    "https://other.tld/image2.png",
    "https://various.tld/image3.png"
];

var images = imageURLs.map( fetchImage );
```

The `images` array won't contain the images. Depending on the behavior of `fetchImage(..)`, it probably returns a promise for the image object once it finishes downloading. So `images` would now be a list of promises.

Of course, you could then use `Promise.all(..)` to wait for all those promises to resolve, and then unwrap an array of the image object results at its completion:

```js
Promise.all( images )
.then(function allImages(imgObjs){
    // ..
});
```

Unfortunately, this "trick" only works if you're going to do all the asynchronous steps concurrently (rather than serially, one after the other), and only if the operation is a `map(..)` call as shown. If you want serial asynchrony, or you want to, for example, do a `filter(..)` concurrently, this won't quite work; it's possible, but it's messier.

And some operations naturally require serial asynchrony, like for example an asynchronous `reduce(..)`, which clearly needs to work left-to-right one at a time; those steps can't be run concurrently and have that operation make any sense.

As I said, Observables (see [Chapter 10](ch10.md/#observables)) aren't the answer to these kinds of tasks. The reason is, an Observable's coordination of asynchrony is between separate operations, not between steps/iterations at a single level of operation.

Another way to visualize this distinction is that Observables support "vertical asynchrony", whereas what I'm talking about would be "horizontal asynchrony".

Consider:

```js
var obsv = Rx.Observable.from( [1,2,3,4,5] );

obsv
.map( x => x * 2 )
.delay( 100 )        // <-- vertical asynchrony
.map( x => x + 1 )
.subscribe( v => console.log );
// {after 100 ms}
// 3
// 5
// 7
// 9
// 11
```

If for some reason I wanted to ensure that there was a delay of 100 ms between when `1` was processed by the first `map(..)` and when `2` was processed, that would be the "horizontal asynchrony" I'm referring to. There's not really a clean way to model that.

And of course, I'm using an arbitrary delay in that description, but in practice that would more likely be serial-asynchrony like an asynchronous reduce, where each step in that reduction iteration could take some time before it completes and lets the next step be processed.

So, how do we support both serial and concurrent iteration across asynchronous operations?

**fasy** (pronounced like "Tracy" but with an "f") is a little utility library I built for supporting exactly those kinds of tasks. You can find more information about it [here](https://github.com/getify/fasy).

To illustrate **fasy**, let's consider a concurrent `map(..)` versus a serial `map(..)`:

```js
FA.concurrent.map( fetchImage, imageURLs )
.then( function allImages(imgObjs){
    // ..
} );

FA.serial.map( fetchImage, imageURLs )
.then( function allImages(imgObjs){
    // ..
} );
```

In both cases, the `then(..)` handler will only be invoked once all the fetches have fully completed. The difference is whether the fetches will all initiate concurrently (aka, "in parallel") or go out one at a time.

Your instinct might be that concurrent would always be preferable, and while that may be common, it's not always the case.

For example, what if `fetchImage(..)` maintains a cache of fetched images, and it checks the cache before making the actual network request? What if, in addition to that, the list of `imageURLs` could have duplicates in it? You'd certainly want the first fetch of an image URL to complete (and populate the cache) before doing the check on the duplicate image URL later in the list.

Again, there will inevitably be cases where concurrent or serial asynchrony will be called for. Asynchronous reductions will always be serial, whereas asynchronous mappings may likely tend to be more concurrent but can also need to be serial in some cases. That's why **fasy** supports all these options.

Along with Observables, **fasy** will help you extend more FP patterns and principles to your asynchronous operations.

## Summary

JavaScript is not particularly designed as an FP language. However, it does have enough of the basics (like function values, closures, etc.) for us to make it FP-friendly. And the libraries we've examined here will help you do that.

Armed with the concepts from this book, you're ready to start tackling real-world code. Find a good, comfortable FP library and jump in. Practice, practice, practice!

So... that's it. I've shared what I have for you, for now. I hereby officially certify you as a "Functional-Light JavaScript" programmer! It's time to close out this "chapter" of our story of learning FP together. But my learning journey still continues; I hope yours does, too!


================================================
FILE: manuscript/ch1.md
================================================
# Functional-Light JavaScript
# Chapter 1: Why Functional Programming?

> Functional programmer: (noun) One who names variables "x", names functions "f", and names code patterns "zygohistomorphic prepromorphism"
>
> James Iry @jamesiry 5/13/15
>
> https://twitter.com/jamesiry/status/598547781515485184

Functional Programming (FP) is not a new concept by any means. It's been around almost the entire history of programming. However, and I'm not sure it's fair to say, but... it sure hasn't seemed like as mainstream of a concept in the overall developer world until perhaps the last few years. I think FP has more been the realm of academics.

That's all changing, though. A groundswell of interest is growing around FP, not just at the languages level but even in libraries and frameworks. You very well might be reading this text because you've finally realized FP is something you can't ignore any longer. Or maybe you're like me and you've tried to learn FP many times before but struggled to wade through all the terms or mathematical notation.

This first chapter's purpose is to answer questions like "Why should I use FP style with my code?" and "How does Functional-Light JavaScript compare to what others say about FP?" After we've laid that groundwork, throughout the rest of the book we'll uncover, piece by piece, the techniques and patterns for writing JS in Functional-Light style.

## At a Glance

Let's briefly illustrate the notion of "Functional-Light JavaScript" with a before-and-after snapshot of code. Consider:

```js
var numbers = [4,10,0,27,42,17,15,-6,58];
var faves = [];
var magicNumber = 0;

pickFavoriteNumbers();
calculateMagicNumber();
outputMsg();                // The magic number is: 42

// ***************

function calculateMagicNumber() {
    for (let fave of faves) {
        magicNumber = magicNumber + fave;
    }
}

function pickFavoriteNumbers() {
    for (let num of numbers) {
        if (num >= 10 && num <= 20) {
            faves.push( num );
        }
    }
}

function outputMsg() {
    var msg = `The magic number is: ${magicNumber}`;
    console.log( msg );
}
```

Now consider a very different style that accomplishes exactly the same outcome:

```js
var sumOnlyFavorites = FP.compose( [
    FP.filterReducer( FP.gte( 10 ) ),
    FP.filterReducer( FP.lte( 20 ) )
] )( sum );

var printMagicNumber = FP.pipe( [
    FP.reduce( sumOnlyFavorites, 0 ),
    constructMsg,
    console.log
] );

var numbers = [4,10,0,27,42,17,15,-6,58];

printMagicNumber( numbers );        // The magic number is: 42

// ***************

function sum(x,y) { return x + y; }
function constructMsg(v) { return `The magic number is: ${v}`; }
```

Once you understand FP and Functional-Light, this is likely how you'd *read* and mentally process that second snippet:

> We're first creating a function called `sumOnlyFavorites(..)` that's a combination of three other functions. We combine two filters, one checking if a value is greater-than-or-equal to 10 and one for less-than-or-equal to 20. Then we include the `sum(..)` reducer in the transducer composition. The resulting `sumOnlyFavorites(..)` function is a reducer that checks if a value passes both filters, and if so, adds the value to an accumulator value.
>
> Then we make another function called `printMagicNumber(..)` which first reduces a list of numbers using that `sumOnlyFavorites(..)` reducer we just defined, resulting in a sum of only numbers that passed the *favorite* checks. Then `printMagicNumber(..)` pipes that final sum into `constructMsg(..)`, which creates a string value that finally goes into `console.log(..)`.

All those moving pieces *speak* to an FP developer in ways that likely seem highly unfamiliar to you right now. This book will help you *speak* that same kind of reasoning so that it's as readable to you as any other code, if not more so!

A few other quick remarks about this code comparison:

* It's likely that for many readers, the former snippet feels closer to comfortable/readable/maintainable than the latter snippet. It's entirely OK if that's the case. You're in exactly the right spot. I'm confident that if you stick it out through the whole book, and practice everything we talk about, that second snippet will eventually become a lot more natural, maybe even preferable!

* You might have done the task significantly or entirely different from either snippet presented. That's OK, too. This book won't be prescriptive in dictating that you should do something a specific way. The goal is to illustrate the pros/cons of various patterns and enable you to make those decisions. By the end of this book, how you would approach the task may fall a little closer to the second snippet than it does right now.

* It's also possible that you're already a seasoned FP developer who's scanning through the start of this book to see if it has anything useful for you to read. That second snippet certainly has some bits that are quite familiar. But I'm also betting that you thought, "Hmmm, I wouldn't have done it *that* way..." a couple of times. That's OK, and entirely reasonable.

    This is not a traditional, canonical FP book. We'll at times seem quite heretical in our approaches. We're seeking to strike a pragmatic balance between the clear undeniable benefits of FP, and the need to ship workable, maintainable JS without having to tackle a daunting mountain of math/notation/terminology. This is not *your* FP, it's "Functional-Light JavaScript".

Whatever your reasons for reading this book, welcome!

## Confidence

I have a very simple premise that sort of underlies everything I do as a teacher of software development (in JavaScript): code that you cannot trust is code that you do not understand. The reverse is true also: code that you don't understand is code you can't trust. Furthermore, if you cannot trust or understand your code, then you can't have any confidence whatsoever that the code you write is suitable to the task. You run the program and basically just cross your fingers.

What do I mean by trust? I mean that you can verify, by reading and reasoning, not just executing, that you understand what a piece of code *will* do; you aren't just relying on what it *should* do. More often than is perhaps prudent, we tend to rely on running test suites to verify our programs' correctness. I don't mean to suggest tests are bad. But I do think we should aspire to be able to understand our code well enough that we know the test suite will pass before it runs.

The techniques that form the foundation of FP are designed from the mindset of having far more confidence over our programs just by reading them. Someone who understands FP, and who's disciplined enough to diligently use it throughout their programs, will write code that they **and others** can read and verify that the program will do what they want.

Confidence is also increased when we use techniques that avoid or minimize likely sources of bugs. That's perhaps one of the biggest selling points of FP: FP programs often have fewer bugs, and the bugs that do exist are usually in more obvious places, so they're easier to find and fix. FP code tends to be more bug-resistant -- certainly not bug-proof, though.

As you journey through this book, you will begin to develop more confidence in the code you write, because you will use patterns and practices that are already well proven; and you'll avoid the most common causes of program bugs!

## Communication

Why is Functional Programming important? To answer that, we need to take a bigger step back and talk about why programming itself is important.

It may surprise you to hear this, but I don't believe that code is primarily a set of instructions for the computer. Actually, I think the fact that code instructs the computer is almost a happy accident.

I believe very deeply that the vastly more important role of code is as a means of communication with other human beings.

You probably know by experience that an awful lot of your time spent "coding" is actually spent reading existing code. Very few of us are so privileged as to spend all or most of our time simply banging out all new code and never dealing with code that others (or our past selves) wrote.

It's widely estimated that developers spend 70% of code maintenance time on reading to understand it. That is eye-opening. 70%. No wonder the global average for a programmer's lines of code written per day is about 10. We spend up to 7 hours of our day just reading the code to figure out where those 10 lines should go!

We need to focus a lot more on the readability of our code. And by the way, readability is not just about fewer characters. Readability is actually most impacted by familiarity.<a href="#user-content-footnote-1"><sup>1</sup></a>

If we are going to spend our time concerned with making code that will be more readable and understandable, FP is central in that effort. The principles of FP are well established, deeply studied and vetted, and provably verifiable. Taking the time to learn and employ these FP principles will ultimately lead to more readily and recognizably familiar code for you and others. The increase in code familiarity, and the expediency of that recognition, will improve code readability.

For example, once you learn what `map(..)` does, you'll be able to almost instantly spot and understand it when you see it in any program. But every time you see a `for` loop, you're going to have to read the whole loop to understand it. The syntax of the `for` loop may be familiar, but the substance of what it's doing is not; that has to be *read*, every time.

By having more code that's recognizable at a glance, and thus spending less time figuring out what the code is doing, our focus is freed up to think about the higher levels of program logic; this is the important stuff that most needs our attention anyway.

FP (at least, without all the terminology weighing it down) is one of the most effective tools for crafting readable code. *That* is why it's so important.

## Readability

Readability is not a binary characteristic. It's a largely subjective human factor describing our relationship to code. And it will naturally vary over time as our skills and understanding evolve. I have experienced effects similar to the following figure, and anecdotally many others I've talked to have as well.

<p align="center">
    <img src="images/fig17.png" width="50%">
</p>

You may just find yourself experiencing similar effects as you work through the book. But take heart; if you stick this out, the curve comes back up!

*Imperative* describes the code most of us probably already write naturally; it's focused on precisely instructing the computer *how* to do something. Declarative code -- the kind we'll be learning to write, which adheres to FP principles -- is code that's more focused on describing the *what* outcome.

Let's revisit the two code snippets presented earlier in this chapter.

The first snippet is imperative, focused almost entirely on *how* to do the tasks; it's littered with `if` statements, `for` loops, temporary variables, reassignments, value mutations, function calls with side effects, and implicit data flow between functions. You certainly *can* trace through its logic to see how the numbers flow and change to the end state, but it's not at all clear or straightforward.

The second snippet is more declarative; it does away with most of those aforementioned imperative techniques. Notice there's no explicit conditionals, loops, side effects, reassignments, or mutations; instead, it employs well-known (to the FP world, anyway!) and trustable patterns like filtering, reduction, transducing, and composition. The focus shifts from low-level *how* to higher level *what* outcomes.

Instead of messing with an `if` statement to test a number, we delegate that to a well-known FP utility like `gte(..)` (greater-than-or-equal-to), and then focus on the more important task of combining that filter with another filter and a summation function.

Moreover, the flow of data through the second program is explicit:

1. A list of numbers goes into `printMagicNumber(..)`.
2. One at a time those numbers are processed by `sumOnlyFavorites(..)`, resulting in a single number total of only our favorite kinds of numbers.
3. That total is converted to a message string with `constructMsg(..)`.
4. The message string is printed to the console with `console.log(..)`.

You may still feel this approach is convoluted, and that the imperative snippet was easier to understand. You're much more accustomed to it; familiarity has a profound influence on our judgments of readability. By the end of this book, though, you will have internalized the benefits of the second snippet's declarative approach, and that familiarity will spring its readability to life.

I know asking you to believe that at this point is a leap of faith.

It takes a lot more effort, and sometimes more code, to improve its readability as I'm suggesting, and to minimize or eliminate many of the mistakes that lead to bugs. Quite honestly, when I started writing this book, I could never have written (or even fully understood!) that second snippet. As I'm now further along on my journey of learning, it's more natural and comfortable.

If you're hoping that FP refactoring, like a magic silver bullet, will quickly transform your code to be more graceful, elegant, clever, resilient, and concise -- that it will come easy in the short term -- unfortunately that's just not a realistic expectation.

FP is a very different way of thinking about how code should be structured, to make the flow of data much more obvious and to help your reader follow your thinking. It will take time. This effort is eminently worthwhile, but it can be an arduous journey.

It still often takes me multiple attempts at refactoring a snippet of imperative code into more declarative FP, before I end up with something that's clear enough for me to understand later. I've found converting to FP is a slow iterative process rather than a quick binary flip from one paradigm to another.

I also apply the "teach it later" test to every piece of code I write. After I've written a piece of code, I leave it alone for a few hours or days, then come back and try to read it with fresh eyes, and pretend as if I need to teach or explain it to someone else. Usually, it's jumbled and confusing the first few passes, so I tweak it and repeat!

I'm not trying to dampen your spirits. I really want you to hack through these weeds. I am glad I did it. I can finally start to see the curve bending upward toward improved readability. The effort has been worth it. It will be for you, too.

## Perspective

Most other FP texts seem to take a top-down approach, but we're going to go the opposite direction: working from the ground up, we'll uncover the basic foundational principles that I believe formal FPers would admit are the scaffolding for everything they do. But for the most part we'll stay arm's length away from most of the intimidating terminology or mathematical notation that can so easily frustrate learners.

I believe it's less important what you call something and more important that you understand what it is and how it works. That's not to say there's no importance to shared terminology -- it undoubtedly eases communication among seasoned professionals. But for the learner, I've found it can be distracting.

So this book will try to focus more on the base concepts and less on the fancy fluff. That's not to say there won't be terminology; there definitely will be. But don't get too wrapped up in the sophisticated words. Wherever necessary, look beyond them to the ideas.

I call the less formal practice herein "Functional-Light Programming" because I think where the formalism of true FP suffers is that it can be quite overwhelming if you're not already accustomed to formal thought. I'm not just guessing; this is my own personal story. Even after teaching FP and writing this book, I can still say that the formalism of terms and notation in FP is very, very difficult for me to process. I've tried, and tried, and I can't seem to get through much of it.

I know many FPers who believe that the formalism itself helps learning. But I think there's clearly a cliff where that only becomes true once you reach a certain comfort with the formalism. If you happen to already have a math background or even some flavors of CS experience, this may come more naturally to you. But some of us don't, and no matter how hard we try, the formalism keeps getting in the way.

So this book introduces the concepts that I believe FP is built on, but comes at it by giving you a boost from below to climb up the cliff wall, rather than condescendingly shouting down at you from the top, prodding you to just figure out how to climb as you go.

## How to Find Balance

If you've been around programming for very long, chances are you've heard the phrase "YAGNI" before: "You Ain't Gonna Need It". This principle primarily comes from extreme programming, and stresses the high risk and cost of building a feature before it's needed.

Sometimes we guess we'll need a feature in the future, build it now believing it'll be easier to do as we build other stuff, then realize we guessed wrong and the feature wasn't needed, or needed to be quite different. Other times we guess right, but build a feature too early, and suck up time from the features that are genuinely needed now; we incur an opportunity cost in diluting our energy.

YAGNI challenges us to remember: even if it's counterintuitive in a situation, we often should postpone building something until it's presently needed. We tend to exaggerate our mental estimates of the future refactoring cost of adding it later when it is needed. Odds are, it won't be as hard to do later as we might assume.

As it applies to functional programming, I would offer this admonition: there will be plenty of interesting and compelling patterns discussed in this text, but just because you find some pattern exciting to apply, it may not necessarily be appropriate to do so in a given part of your code.

This is where I will differ from many formal FPers: just because you *can* apply FP to something doesn't mean you *should* apply FP to it. Moreover, there are many ways to slice a problem, and even though you may have learned a more sophisticated approach that is more "future-proof" to maintenance and extensibility, a simpler FP pattern might be more than sufficient in that spot.

Generally, I'd recommend seeking balance in what you code, and to be conservative in your application of FP concepts as you get the hang of things. Default to the YAGNI principle in deciding if a certain pattern or abstraction will help that part of the code be more readable or if it's just introducing clever sophistication that isn't (yet) warranted.

> Reminder, any extensibility point that’s never used isn’t just wasted effort, it’s likely to also get in your way as well
>
> Jeremy D. Miller @jeremydmiller 2/20/15
>
> https://twitter.com/jeremydmiller/status/568797862441586688

Remember, every single line of code you write has a reader cost associated with it. That reader may be another team member, or even your future self. Neither of those readers will be impressed with overly clever, unnecessary sophistication just to show off your FP prowess.

The best code is the code that is most readable in the future because it strikes exactly the right balance between what it can/should be (idealism) and what it must be (pragmatism).

## Resources

I have drawn on a great many different resources to be able to compose this text. I believe you, too, may benefit from them, so I wanted to take a moment to point them out.

### Books

Some FP/JavaScript books that you should definitely read:

* [Professor Frisby's Mostly Adequate Guide to Functional Programming](https://mostly-adequate.gitbook.io/mostly-adequate-guide/) by [Brian Lonsdorf](https://twitter.com/drboolean)
* [JavaScript Allongé](https://leanpub.com/javascriptallongesix) by [Reg Braithwaite](https://twitter.com/raganwald)
* [Functional JavaScript](http://shop.oreilly.com/product/0636920028857.do) by [Michael Fogus](https://twitter.com/fogus)

### Blogs/sites

Some other authors and content you should check out:

* [Fun Fun Function Videos](https://www.youtube.com/watch?v=BMUiFMZr7vk) by [Mattias P Johansson](https://twitter.com/mpjme)
* [Awesome FP JS](https://github.com/stoeffel/awesome-fp-js)
* [Kris Jenkins](http://blog.jenkster.com/2015/12/what-is-functional-programming.html)
* [Eric Elliott](https://medium.com/@_ericelliott)
* [James A Forbes](https://james-forbes.com/)
* [James Longster](https://github.com/jlongster)
* [André Staltz](http://staltz.com/)
* [Functional Programming Jargon](https://github.com/hemanth/functional-programming-jargon#functional-programming-jargon)
* [Functional Programming Exercises](https://github.com/InceptionCode/Functional-Programming-Exercises)

### Libraries

The code snippets in this book largely do not rely on libraries. Each operation that we discover, we'll derive how to implement it in standalone, plain ol' JavaScript. However, as you begin to build more of your real code with FP, you'll soon want a library to provide optimized and highly reliable versions of these commonly accepted utilities.

By the way, you need to check the documentation for the library functions you use to ensure you know how they work. There will be a lot of similarities in many of them to the code we build on in this text, but there will undoubtedly be some differences, even between popular libraries.

Here are a few popular FP libraries for JavaScript that are a great place to start your exploration with:

* [Ramda](http://ramdajs.com)
* [lodash/fp](https://github.com/lodash/lodash/wiki/FP-Guide)
* [functional.js](http://functionaljs.com/)
* [Immutable.js](https://github.com/facebook/immutable-js)

[Appendix C takes a deeper look at these libraries](apC.md/#stuff-to-investigate) and others.

## Summary

You may have a variety of reasons for starting to read this book, and different expectations of what you'll get out of it. This chapter has explained why I want you to read the book and what I want you to get out of the journey. It also helps you articulate to others (like your fellow developers) why they should come on the journey with you!

Functional programming is about writing code that is based on proven principles so we can gain a level of confidence and trust over the code we write and read. We shouldn't be content to write code that we anxiously *hope* works, and then abruptly breathe a sigh of relief when the test suite passes. We should *know* what it will do before we run it, and we should be absolutely confident that we've communicated all these ideas in our code for the benefit of other readers (including our future selves).

This is the heart of Functional-Light JavaScript. The goal is to learn to effectively communicate with our code but not have to suffocate under mountains of notation or terminology to get there.

The journey to learning functional programming starts with deeply understanding the nature of what a function is. That's what we tackle in the next chapter.

----

<a name="footnote-1"><sup>1</sup></a>Buse, Raymond P. L., and Westley R. Weimer. “Learning a Metric for Code Readability.” IEEE Transactions on Software Engineering, IEEE Press, July 2010, dl.acm.org/citation.cfm?id=1850615.


================================================
FILE: manuscript/ch10.md
================================================
# Functional-Light JavaScript
# Chapter 10: Functional Async

At this point of the book, you now have all the raw concepts in place for the foundations of FP that I call "Functional-Light Programming". In this chapter, we're going to apply these concepts to a different context, but we won't really present particularly new ideas.

So far, almost everything we've done is synchronous, meaning that we call functions with immediate inputs and immediately get back output values. A lot of work can be done this way, but it's not nearly sufficient for the entirety of a modern JS application. To be truly ready for FP in the real world of JS, we need to understand async FP.

Our goal in this chapter is to expand our thinking about managing values with FP, to spread out such operations over time. We'll see that Observables (and Promises!) are one great way to do that.

## Time as State

The most complicated state in your entire application is time. That is, it's far easier to manage state when the transition from one state to another is immediate and affirmatively in your control. When the state of your application changes implicitly in response to events spread out over time, management becomes exponentially more difficult.

Every part of how we've presented FP in this text has been about making code easier to read by making it more trustable and more predictable. When you introduce asynchrony to your program, those efforts take a big hit.

But let's be more explicit: it's not the mere fact that some operations don't finish synchronously that is concerning; firing off asynchronous behavior is easy. It's the coordination of the responses to these actions, each of which has the potential to change the state of your application, that requires so much extra effort.

So, is it better for you the author to take that effort, or should you just leave it to the reader of your code to figure out what the state of the program will be if A finishes before B, or vice versa? That's a rhetorical question but one with a pretty concrete answer from my perspective: to have any hope of making such complex code more readable, the author has to take a lot more care than they normally would.

### Reducing Time

One of the most important outcomes of async programming patterns is simplifying state change management by abstracting out time from our sphere of concern. To illustrate, let's first look at a scenario where a race condition (aka, time complexity) exists, and must be manually managed:

```js
var customerId = 42;
var customer;

lookupCustomer( customerId, function onCustomer(customerRecord){
    var orders = customer ? customer.orders : null;
    customer = customerRecord;
    if (orders) {
        customer.orders = orders;
    }
} );

lookupOrders( customerId, function onOrders(customerOrders){
    if (!customer) {
        customer = {};
    }
    customer.orders = customerOrders;
} );
```

The `onCustomer(..)` and `onOrders(..)` callbacks are in a binary race condition. Assuming they both run, it's possible that either might run first, and it's impossible to predict which will happen.

If we could embed the call to `lookupOrders(..)` inside of `onCustomer(..)`, we'd be sure that `onOrders(..)` was running after `onCustomer(..)`. But we can't do that, because we need the two lookups to occur concurrently.

So to normalize this time-based state complexity, we use a pairing of `if`-statement checks in the respective callbacks, along with an outer lexically closed over variable `customer`. When each callback runs, it checks the state of `customer`, and thus determines its own relative ordering; if `customer` is unset for a callback, it's the first to run, otherwise it's the second.

This code works, but it's far from ideal in terms of readability. The time complexity makes this code harder to read. Let's instead use a JS Promise to factor time out of the picture:

```js
var customerId = 42;

var customerPromise = lookupCustomer( customerId );
var ordersPromise = lookupOrders( customerId );

customerPromise.then( function onCustomer(customer){
    ordersPromise.then( function onOrders(orders){
        customer.orders = orders;
    } );
} );
```

The `onOrders(..)` callback is now inside of the `onCustomer(..)` callback, so their relative ordering is guaranteed. The concurrency of the lookups is accomplished by making the `lookupCustomer(..)` and `lookupOrders(..)` calls separately before specifying the `then(..)` response handling.

It may not be obvious, but there would otherwise inherently be a race condition in this snippet, were it not for how Promises are defined to behave. If the lookup of the `orders` finishes before the `ordersPromise.then(..)` is called to provide an `onOrders(..)` callback, *something* needs to be smart enough to keep that `orders` list around until `onOrders(..)` can be called. In fact, the same concern could apply to `customer` being present before `onCustomer(..)` is specified to receive it.

That *something* is the same kind of time complexity logic we discussed with the previous snippet. But we don't have to worry about any of that complexity, either in the writing of this code or -- more importantly -- in the reading of it, because the promises take care of that time normalization for us.

A Promise represents a single (future) value in a time-independent manner. Moreover, extracting the value from a promise is the asynchronous form of the synchronous assignment (via `=`) of an immediate value. In other words, a promise spreads an `=` assignment operation out over time, but in a trustable (time-independent) fashion.

We'll now explore how we similarly can spread various synchronous FP operations from earlier in this book asynchronously over time.

## Eager vs. Lazy

Eager and lazy in the realm of computer science aren't compliments or insults, but rather ways to describe whether an operation will finish right away or progress over time.

The FP operations that we've seen in this text can be characterized as eager because they operate synchronously (right now) on a discrete immediate value or list/structure of values.

Recall:

```js
var a = [1,2,3]

var b = a.map( v => v * 2 );

b;          // [2,4,6]
```

This mapping from `a` to `b` is eager because it operates on all the values in the `a` array at that moment, and produces a new `b` array. If you later modify `a` (for example, by adding a new value to the end of it) nothing will change about the contents of `b`. That's eager FP.

But what would it look like to have a lazy FP operation? Consider something like this:

```js
var a = [];

var b = mapLazy( a, v => v * 2 );

a.push( 1 );

a[0];       // 1
b[0];       // 2

a.push( 2 );

a[1];       // 2
b[1];       // 4
```

The `mapLazy(..)` we've imagined here essentially "listens" to the `a` array, and every time a new value is added to the end of it (with `push(..)`), it runs the `v => v * 2` mapping function and pushes the transformed value to the `b` array.

**Note:** The implementation of `mapLazy(..)` has not been shown because this is a fictional illustration, not a real operation. To accomplish this kind of lazy operation pairing between `a` and `b`, we'll need something smarter than basic arrays.

Consider the benefits of being able to pair an `a` and `b` together, where any time (even asynchronously!) you put a value into `a`, it's transformed and projected to `b`. That's the same kind of declarative FP power from of a `map(..)` operation, but now it can be stretched over time; you don't have to know all the values of `a` *right now* to set up the mapping from `a` to `b`.

## Reactive FP

To understand how we could create and use a lazy mapping between two sets of values, we need to abstract our idea of list (array) a bit. Let's imagine a smarter kind of array, not one which simply holds values but one which lazily receives and responds (aka "reacts") to values. Consider:

```js
var a = new LazyArray();

var b = a.map( function double(v){
    return v * 2;
} );

setInterval( function everySecond(){
    a.push( Math.random() );
}, 1000 );
```

So far, this snippet doesn't look any different than a normal array. The only unusual thing is that we're used to the `map(..)` running eagerly and immediately producing a `b` array with all the currently mapped values from `a`. The timer pushing random values into `a` is strange, since all those values are coming *after* the `map(..)` call.

But this fictional `LazyArray` is different; it assumes that values will come one at a time, over time; just `push(..)` values in whenever you want. `b` will be a lazy mapping of whatever values eventually end up in `a`.

Also, we don't really need to keep values in `a` or `b` once they've been handled; this special kind of array only holds a value as long as it's needed. So these arrays don't strictly grow in memory usage over time, an important characteristic of lazy data structures and operations. In fact, it's less like an array and more like a buffer.

A normal array is eager in that it holds all of its values right now. A "lazy array" is an array where the values will come in over time.

Since we won't necessarily know when a new value has arrived in `a`, another key thing we need is to be able to listen to `b` to be notified when new values are made available. We could imagine a listener like this:

```js
b.listen( function onValue(v){
    console.log( v );
} );
```

`b` is *reactive* in that it's set up to *react* to values as they come into `a`. There's an FP operation `map(..)` that describes how each value transfers from the origin `a` to the target `b`. Each discrete mapping operation is exactly how we modeled single-value operations with normal synchronous FP, but here we're spreading out the sourcing of values over time.

**Note:** The term most commonly applied to these concepts is Functional Reactive Programming (FRP). I'm deliberately avoiding that term because there's some debate as to whether FP + Reactive genuinely constitutes FRP. We're not going to fully dive into all the implications of FRP here, so I'll just keep calling it reactive FP. Alternatively, you could call it evented-FP if that feels less confusing.

We can think of `a` as producing values and `b` as consuming them. So for readability, let's reorganize this snippet to separate the concerns into *producer* and *consumer* roles:

```js
// producer:

var a = new LazyArray();

setInterval( function everySecond(){
    a.push( Math.random() );
}, 1000 );


// **************************
// consumer:

var b = a.map( function double(v){
    return v * 2;
} );

b.listen( function onValue(v){
    console.log( v );
} );
```

`a` is the producer, which acts essentially like a stream of values. We can think of each value arriving in `a` as an *event*. The `map(..)` operation then triggers a corresponding event on `b`, which we `listen(..)` to so we can consume the new value.

The reason we separate the *producer* and *consumer* concerns is so that different parts of our application can be responsible for each concern. This code organization can drastically improve both code readability and maintenance.

### Declarative Time

We're being very careful about how we introduce time into the discussion. Specifically, just as promises abstract time away from our concern for a single asynchronous operation, reactive FP abstracts (separates) time away from a series of values/operations.

From the perspective of `a` (the producer), the only evident time concern is our manual `setInterval(..)` loop. But that's only for demonstration purposes.

Imagine `a` could actually be attached to some other event source, like the user's mouse clicks or keystrokes, websocket messages from a server, etc. In that scenario, `a` doesn't actually have to concern itself with time. It's merely a time-independent conduit for values, whenever they are ready.

From the perspective of `b` (the consumer), we do not know or care when/where the values in `a` come from. As a matter of fact, all the values could already be present. All we care about is that we want those values, whenever they are ready. Again, this is a time-independent (aka lazy) modeling of the `map(..)` transformation operation.

The *time* relationship between `a` and `b` is declarative (and implicit!), not imperative (or explicit).

The value of organizing such operations-over-time this way may not feel particularly effective yet. Let's compare to how this same sort of functionality could have been expressed imperatively:

```js
// producer:

var a = {
    onValue(v){
        b.onValue( v );
    }
};

setInterval( function everySecond(){
    a.onValue( Math.random() );
}, 1000 );


// **************************
// consumer:

var b = {
    map(v){
        return v * 2;
    },
    onValue(v){
        v = this.map( v );
        console.log( v );
    }
};
```

It may seem rather subtle, but there's an important difference between this more-imperative version of the code and the previous more-declarative version, aside from just `b.onValue(..)` needing to call `this.map(..)` itself. In the former snippet, `b` pulls from `a`, but in the latter snippet, `a` pushes to `b`. In other words, compare `b = a.map(..)` to `b.onValue(v)`.

In the latter imperative snippet, it's not clear (readability wise) from the consumer's perspective where the `v` values are coming from. Moreover, the imperative hard coding of `b.onValue(..)` in the middle of producer `a`'s logic is a violation of separation-of-concerns. That can make it harder to reason about producer and consumer independently.

By contrast, in the former snippet, `b = a.map(..)` declares that `b`'s values are sourced from `a`, and treats `a` as an abstract event stream data source that we don't have to concern ourselves with at that moment. We *declare* that any value that comes from `a` into `b` will go through the `map(..)` operation as specified.

### More Than Map

For convenience, we've illustrated this notion of pairing `a` and `b` together over time via a one-to-one `map(..)`ing. But many of our other FP operations could be modeled over time as well.

Consider:

```js
var b = a.filter( function isOdd(v) {
    return v % 2 == 1;
} );

b.listen( function onlyOdds(v){
    console.log( "Odd:", v );
} );
```

Here, a value from `a` only comes into `b` if it passes the `isOdd(..)` predicate.

Even `reduce(..)` can be modeled over time:

```js
var b = a.reduce( function sum(total,v){
    return total + v;
} );

b.listen( function runningTotal(v){
    console.log( "New current total:", v );
} );
```

Since we don't specify an `initialValue` to the `reduce(..)` call, neither the `sum(..)` reducer nor the `runningTotal(..)` event callback will be invoked until at least two values have come through from `a`.

This snippet implies that the reduction has a *memory* of sorts, in that each time a future value comes in, the `sum(..)` reducer will be invoked with whatever the previous `total` was as well as the new next value `v`.

Other FP operations extended over time could even involve an internal buffer, like for example `unique(..)` keeping track of every value it's seen so far.

### Observables

Hopefully by now you can see the importance of a reactive, evented, array-like data structure like the fictional `LazyArray` we've conjured. The good news is, this kind of data structure already exists, and it's called an Observable.

**Note:** Just to set some expectation: the following discussion is only a brief intro to the world of Observables. This is a far more in-depth topic than we have space to fully explore. But if you've understood Functional-Light Programming in this text, and now grasped how asynchronous-time can be modeled via FP principles, Observables should follow very naturally for your continued learning.

Observables have been implemented by a variety of userland libraries, most notably [RxJS](https://github.com/Reactive-Extensions/RxJS) and [Most](https://github.com/cujojs/most). At the time of this writing, there's an in-progress proposal to add Observables natively to JS, just like Promises were added in ES6. For the sake of demonstration, we'll use RxJS-flavored Observables for these next examples.

Here's our earlier reactive example, expressed with observables instead of `LazyArray`:

```js
// producer:

var a = new Rx.Subject();

setInterval( function everySecond(){
    a.next( Math.random() );
}, 1000 );


// **************************
// consumer:

var b = a.map( function double(v){
    return v * 2;
} );

b.subscribe( function onValue(v){
    console.log( v );
} );
```

In the RxJS universe, an Observer subscribes to an Observable. If you combine the functionality of an Observer and an Observable, you get a Subject. So, to keep our snippet simpler, we construct `a` as a Subject, so that we can call `next(..)` on it to push values (events) into its stream.

If we want to keep the Observer and Observable separate:

```js
// producer:

var a = Rx.Observable.create( function onObserve(observer){
    setInterval( function everySecond(){
        observer.next( Math.random() );
    }, 1000 );
} );
```

In this snippet, `a` is the observable, and unsurprisingly, the separate observer is called `observer`; it's able to "observe" some events (like our `setInterval(..)` loop); we use its `next(..)` method to feed events into the `a` observable stream.

In addition to `map(..)`, RxJS defines well over a hundred operators that are invoked lazily as each new value comes in. Just like with arrays, each operator on an Observable returns a new Observable, meaning they are chainable. If an invocation of operator function determines a value should be passed along from the input Observable, it will be fired on the output Observable; otherwise it's discarded.

Example of a declarative observable chain:

```js
var b =
    a
    .filter( v => v % 2 == 1 )      // only odd numbers
    .distinctUntilChanged()         // only consecutive-distinct
    .throttle( 100 )                // slow it down a bit
    .map( v => v * 2 );             // double them

b.subscribe( function onValue(v){
    console.log( "Next:", v );
} );
```

**Note:** It's not necessary to assign the observable to `b` and then call `b.subscribe(..)` separately from the chain; that's done here to reinforce that each operator returns a new observable from the previous one. In many coding examples you'll find, the `subscribe(..)` call is just the final method in the chain. Because `subscribe(..)` is technically mutating the internal state of the observable, FPers generally prefer these two steps separated, to mark the side effect more obviously.

## Summary

This book has detailed a wide variety of FP operations that take a single value (or an immediate list of values) and transform them into another value/values.

For operations that will be proceed over time, all of these foundational FP principles can be applied time-independently. Exactly like promises model single future values, we can model eager lists of values instead as lazy Observable (event) streams of values that may come in one-at-a-time.

A `map(..)` on an array runs its mapping function once for each value currently in the array, putting all the mapped values in the outcome array. A `map(..)` on an Observable runs its mapping function once for each value, whenever it comes in, and pushes all the mapped values to the output Observable.

In other words, if an array is an eager data structure for FP operations, an Observable is its lazy-over-time counterpart.

**Note:** For a different twist on asynchronous FP, check out a library called [**fasy**, which is discussed in Appendix C](apC.md/#bonus-2-fasy).


================================================
FILE: manuscript/ch11.md
================================================
# Functional-Light JavaScript
# Chapter 11: Putting It All Together

By now, you have everything you need to understand Functional-Light JavaScript. There's no more new concepts to introduce.

In this final chapter, our main goal is conceptual cohesiveness. We'll look at code that brings many of the major themes from this book together -- application of what we've learned. Above all, this example code is intended to illustrate the "Functional Light" approach to JavaScript -- that is, balance and pragmatism over dogma.

You'll want to practice these techniques yourself, extensively. Digesting this chapter is critical to helping you apply FP principles to your real-world code.

## Setup

Let's build a simple stock ticker widget.

**Note:** For reference, the entirety of the code for this example resides in the `ch11-code/` sub-directory -- see the [GitHub repository for this book](https://github.com/getify/Functional-Light-JS). Also, selected FP helpers we've discussed throughout this book that we need for this example are included in `ch11-code/fp-helpers.js`. In this chapter we will only focus on the relevant parts of the code for our discussion.

First, let's talk about the markup for this widget, so we have somewhere to display our information. We start out with an empty `<ul ..>` element in our `ch11-code/index.html` file, but while running, the DOM will be populated to look like:

```html
<ul id="stock-ticker">
    <li class="stock" data-stock-id="AAPL">
        <span class="stock-name">AAPL</span>
        <span class="stock-price">$121.95</span>
        <span class="stock-change">+0.01</span>
    </li>
    <li class="stock" data-stock-id="MSFT">
        <span class="stock-name">MSFT</span>
        <span class="stock-price">$65.78</span>
        <span class="stock-change">+1.51</span>
    </li>
    <li class="stock" data-stock-id="GOOG">
        <span class="stock-name">GOOG</span>
        <span class="stock-price">$821.31</span>
        <span class="stock-change">-8.84</span>
    </li>
</ul>
```

Before we go any further, let me remind you: interacting with the DOM is I/O, and that means side effects. We can't eliminate these side effects, but we can limit and control them. We'll want to be really intentional about minimizing the surface area of our application that deals with the DOM. We learned all about these techniques in [Chapter 5](ch5.md).

Summarizing our widget's functionality: the code will add the `<li ..>` elements each time a new-stock event is "received", and will update the price and change as stock-update events come through.

In the Chapter 11 example code, in `ch11-code/mock-server.js`, we set up some timers to push out randomly generated fake stock data to a simple event emitter, to simulate as if we were getting messages of stock information from a server. We expose a `connectToServer()` function which pretends to do so, but really just returns the faked event emitter instance.

**Note:** This file is all fake/mock behavior, so I didn't spend much effort trying to make it very FP-adherent. I wouldn't suggest spending too much time concerned with the code in this file. If you wrote a real server -- a very interesting extra credit exercise for the ambitious reader! -- you'd clearly want to give that code the FP attention it deserves.

In `ch11-code/stock-ticker-events.js`, we create some observables (via RxJS) hooked up to an event emitter object. We call the `connectToServer()` to get this event emitter, then listen to the event names `"stock"` (adding a new stock to our ticker) and `"stock-update"` (updating the stock's listed price and change amount). Finally, we define transformations on the incoming data of these observables, formatting the data as needed.

In `ch11-code/stock-ticker.js`, we define our UI (DOM side effect) behavior as methods on the `stockTickerUI` object. We also define a variety of helpers, including `getElemAttr(..)`, `stripPrefix(..)`, and others. Finally, we `subscribe(..)` to the two observables that provide us formatted data to render to the DOM.

## Stock Events

Let's look at the code in `ch11-code/stock-ticker-events.js`. We'll start with some basic helpers:

```js
function addStockName(stock) {
    return setProp( "name", stock, stock.id );
}
function formatSign(val) {
    if (Number(val) > 0) {
        return `+${val}`;
    }
    return val;
}
function formatCurrency(val) {
    return `$${val}`;
}
```

These pure functions should be pretty straightforward to interpret. Recall [`setProp(..)` from Chapter 4](ch4.md/#user-content-setprop) actually clones the object before setting the new property. That exercises the principle we saw in Chapter 6: avoiding side effects by treating values as immutable even if they're not.

`addStockName(..)` is used to add a `name` property to a stock message object that's equal to its `id`. The `name` value is later used as the visible stock name in the widget.

When a stock message is received from the "server", it'll look like:

```js
{ id: "AAPL", price: 121.7, change: 0.01 }
```

Prior to display in the DOM, the `price` needs to be formatted with `formatCurrency(..)` (to look like `"$121.70"`), and the `change` needs to be formatted with `formatChange(..)` (to look like `"+0.01"`). But we don't want to mutate the message object, so we need a helper that formats both the numbers and gives us a new stock object:

```js
function formatStockNumbers(stock) {
    var stockDataUpdates = [
        [ "price", formatPrice( stock.price ) ],
        [ "change", formatChange( stock.change ) ]
    ];

    return reduce( function formatter(stock,[propName,val]){
        return setProp( propName, stock, val );
    } )
    ( stock )
    ( stockDataUpdates );
}
```

We create the `stockDataUpdates` array to hold tuples (just arrays) of the property name and the new formatted value, for `price` and `change` respectively. We `reduce(..)` (see [Chapter 9](ch9.md/#reduce)) over that array, with the `stock` object as the `initialValue`. We destructure the tuple into `propName` and `val`, and then return the `setProp(..)` call, which returns a new cloned object with the property having been set.

Now let's define some more helpers:

```js
var formatDecimal = unboundMethod( "toFixed" )( 2 );
var formatPrice = pipe( formatDecimal, formatCurrency );
var formatChange = pipe( formatDecimal, formatSign );
var processNewStock = pipe( addStockName, formatStockNumbers );
```

The `formatDecimal(..)` function takes a number (like `2.1`) and calls its `toFixed( 2 )` method call. We use [Chapter 9's `unboundMethod(..)`](ch9.md/#adapting-methods-to-standalones) to create a standalone late-bound method.

`formatPrice(..)`, `formatChange(..)`, and `processNewStock(..)` are all compositions with `pipe(..)`, each composing a couple of operations left-to-right (see [Chapter 4](ch4.md)).

For creating our observables (see [Chapter 10](ch10.md/#observables)) from our event emitter, we're going to want a helper that's a curried (see [Chapter 3](ch3.md/#one-at-a-time)) standalone of RxJS's `Rx.Observable.fromEvent(..)`:

```js
var makeObservableFromEvent =
    curry( Rx.Observable.fromEvent, 2 )( server );
```

This function is specified to listen to the `server` (event emitter), and is just waiting for an event name string to produce its observable. We have all the pieces in place now to create observers for our two events, and to map-transform those observers to format the incoming data:

```js
var observableMapperFns = [ processNewStock, formatStockNumbers ];

var stockEventNames = [ "stock", "stock-update" ];

var [ newStocks, stockUpdates ] = pipe(
    map( makeObservableFromEvent ),
    curry( zip )( observableMapperFns ),
    map( spreadArgs( mapObservable ) )
)
( stockEventNames );
```

We start with `stockEventNames`, an array of event names (`["stock","stock-update"]`), then `map(..)` (see [Chapter 9](ch9.md/#map)) that to a list of two observables, and `zip(..)` (see [Chapter 9](ch9.md/#zip)) that to a list of observable-mapper functions, producing a list of tuples like `[ observable, mapperFn ]`. Finally, we `map(..)` those tuples with `mapObservable(..)`, spreading out each tuple as individual arguments using `spreadArgs(..)` (see [Chapter 3](ch3.md/#user-content-spreadargs)).

The final result is a list of two mapped observables, which we array-destructure into the assignments for `newStocks` and `stockUpdates`, respectively.

That's it; that's our FP-Light approach to setting up our stock ticker event observables! We'll subscribe to these two observables in `ch11-code/stock-ticker.js`.

Take a step back and reflect on our usage of FP principles here. Did it make sense? Can you see how we applied various concepts covered across the previous chapters from this book? Can you think of other ways to accomplish these tasks?

More importantly, how would you have done it imperatively, and how do you think those two approaches would have compared, broadly? Try that exercise. Write the equivalent using well-established imperative approaches. If you're like me, the imperative form will still feel more natural.

What you need to *get* before moving on is that you can *also* understand and reason about the FP-style we just presented. Think about the shape (the inputs and output) of each function and piece. Do you see how they fit together?

Keep practicing until this stuff clicks for you.

## Stock Ticker UI

If you felt pretty comfortable with the FP of the last section, you're ready to dig into `ch11-code/stock-ticker.js`. It's considerably more involved, so we'll take our time to look at each piece in its entirety.

Let's start by defining some helpers that will assist in our DOM tasks:

```js
function isTextNode(node) {
    return node && node.nodeType == 3;
}
function getElemAttr(prop,elem) {
    return elem.getAttribute( prop );
}
function setElemAttr(elem,prop,val) {
    // !!SIDE EFFECTS!!
    return elem.setAttribute( prop, val );
}
function matchingStockId(id,node){
    return getStockId( node ) == id;
}
function isStockInfoChildElem(elem) {
    return /\bstock-/i.test( getClassName( elem ) );
}
function appendDOMChild(parentNode,childNode) {
    // !!SIDE EFFECTS!!
    parentNode.appendChild( childNode );
    return parentNode;
}
function setDOMContent(elem,html) {
    // !!SIDE EFFECTS!!
    elem.innerHTML = html;
    return elem;
}

var createElement = document.createElement.bind( document );

var getElemAttrByName = curry( getElemAttr, 2 );
var getStockId = getElemAttrByName( "data-stock-id" );
var getClassName = getElemAttrByName( "class" );
var isMatchingStock = curry( matchingStockId, 2 );
```

These should be mostly self-explanatory.

Notice that I called out the side effects of mutating a DOM element's state. We can't as easily clone a DOM object and replace it, so we settle here for a side effect of changing an existing one. At least if we have a bug in our DOM rendering, we can easily search for those code comments to narrow in on likely suspects.

Here are some other miscellaneous helpers:

```js
function stripPrefix(prefixRegex,val) {
    return val.replace( prefixRegex, "" );
}

function listify(listOrItem) {
    if (!Array.isArray( listOrItem )) {
        return [ listOrItem ];
    }
    return listOrItem;
}
```

Let's define a helper to get the child nodes of a DOM element:

```js
var getDOMChildren = pipe(
    listify,
    flatMap(
        pipe(
            curry( prop )( "childNodes" ),
            Array.from
        )
    )
);
```

First, we use `listify(..)` to ensure we have a list of elements (even if it's only a single item in length). Recall [`flatMap(..)` from Chapter 9](ch9.md/#user-content-flatmap), which maps a list and then flattens a list-of-lists into a shallower list.

Our mapping function here maps from an element to its `childNodes` list, which we make into a real array (instead of a live NodeList) with `Array.from(..)`. These two functions are composed (via `pipe(..)`) into a single mapper function, which is fusion (see [Chapter 9](ch9.md/#fusion)).

Now, let's use this `getDOMChildren(..)` helper to define utilities for retrieving specific DOM elements in our widget:

```js
function getStockElem(tickerElem,stockId) {
    return pipe(
        getDOMChildren,
        filterOut( isTextNode ),
        filterIn( isMatchingStock( stockId ) )
    )
    ( tickerElem );
}
function getStockInfoChildElems(stockElem) {
    return pipe(
        getDOMChildren,
        filterOut( isTextNode ),
        filterIn( isStockInfoChildElem )
    )
    ( stockElem );
}
```

`getStockElem(..)` starts with the `tickerElem` DOM element for our widget, retrieves its child elements, then filters to make sure we have the element matching the specified stock identifier. `getStockInfoChildElems(..)` does almost the same thing, except it starts with a stock element, and narrows with different filters.

Both utilities filter out text nodes (since they don't work the same as real DOM nodes), and both utilities return an array of DOM elements, even if it's just a single element.

### Main API

We'll use a `stockTickerUI` object to organize our three main UI manipulation methods, like this:

```js
var stockTickerUI = {

    updateStockElems(stockInfoChildElemList,data) {
        // ..
    },

    updateStock(tickerElem,data) {
        // ..
    },

    addStock(tickerElem,data) {
        // ..
    }
};
```

Let's first examine `updateStock(..)`, as it's the simplest of the three:

```js
updateStock(tickerElem,data) {
    var getStockElemFromId = curry( getStockElem )( tickerElem );
    var stockInfoChildElemList = pipe(
        getStockElemFromId,
        getStockInfoChildElems
    )
    ( data.id );

    return stockTickerUI.updateStockElems(
        stockInfoChildElemList,
        data
    );
},
```

Currying the earlier helper `getStockElem(..)` with `tickerElem` gives us `getStockElemFromId(..)`, which will receive `data.id`.

Via `pipe(..)`, the return value `getStockElemFromId(data.id)` is an `<li>` element (actually, a list containing only that element), which is passed to `getStockInfoChildElems(..)`.

The result is a list (`stockInfoChildElemList`) with the three child `<span>` elements for the stock display info. We pass that list and the stock's `data` message object along to `stockTickerUI.updateStockElems(..)` for actually updating those three `<span>` elements with the new data.

Now let's look at how `stockTickerUI.updateStockElems(..)` is defined:

```js
updateStockElems(stockInfoChildElemList,data) {
    var getDataVal = curry( reverseArgs( prop ), 2 )( data );
    var extractInfoChildElemVal = pipe(
        getClassName,
        curry( stripPrefix )( /\bstock-/i ),
        getDataVal
    );
    var orderedDataVals =
        map( extractInfoChildElemVal )( stockInfoChildElemList );
    var elemsValsTuples =
        filterOut( function updateValueMissing([infoChildElem,val]){
            return val === undefined;
        } )
        ( zip( stockInfoChildElemList, orderedDataVals ) );

    // !!SIDE EFFECTS!!
    compose( each, spreadArgs )
    ( setDOMContent )
    ( elemsValsTuples );
},
```

That's a fair bit to take in, I know. But we'll break it down statement by statement.

`getDataVal(..)` is bound to the `data` message object, having been curried after argument-reversing, so it's now waiting for a property name to extract from `data`.

Next, let's look at how `extractInfoChildElemVal(..)` is defined:

```js
var extractInfoChildElemVal = pipe(
    getClassName,
    curry( stripPrefix )( /\bstock-/i ),
    getDataVal
);
```

This function takes a DOM element, retrieves it DOM class, strips the `"stock-"` prefix from that value, then uses that resulting value (`"name"`, `"price"`, or `"change"`) as a property name to extract from the `data` object via `getDataVal(..)`.

This may seem like a convoluted way to retrieve values from the `data` object. But the purpose is to be able to extract those values from `data` in the same order as the `<span>` elements appear in the `stockInfoChildElemList` list; we accomplish this by using `extractInfoChildElem(..)` as the mapping function over that list of DOM elements, calling the resulting list `orderedDataVals`.

Next, we're going to zip the list of `<span>`s back with the ordered data values, producing tuples where the DOM element and the value to update it with are paired up:

```js
zip( stockInfoChildElemList, orderedDataVals )
```

An interesting wrinkle that wasn't at all obvious up to this point is that because of how we defined the observable's transforms, new-stock message objects will have a `name` property in `data` to match up with the `<span class="stock-name">` element, but `name` will be absent on stock-update message objects.

If the data message object doesn't have a property, we shouldn't update that corresponding DOM element. So, we need to `filterOut(..)` any tuples where the second position (the data value, in this case) is `undefined`:

```js
var elemsValsTuples =
    filterOut( function updateValueMissing([infoChildElem,val]){
        return val === undefined;
    } )
    ( zip( stockInfoChildElemList, orderedDataVals ) );
```

The result after this filtering is a list of tuples (like `[ <span>, ".." ]`) ready for DOM content updating, which we assign to `elemsValsTuples`.

**Note:** Since the `updateValueMissing(..)` predicate is specified inline here, we're in control of its signature. Instead of using `spreadArgs(..)` to adapt it to spread out a single array argument as two individual named parameters, we use parameter array-destructuring in the function declaration (`function updateValueMissing([infoChildElem,val]){ ..`); see [Chapter 2](ch2.md/#user-content-funcparamdestr) for more information.

Finally, we need to update the DOM content of our `<span>` elements:

```js
// !!SIDE EFFECTS!!
compose( each, spreadArgs )( setDOMContent )
( elemsValsTuples );
```

We iterate this `elemsValsTuples` list with `each(..)` (see [`forEach(..)` discussion in Chapter 9](ch9.md/#mapping-vs-eaching)).

Instead of using `pipe(..)` as elsewhere, this composition uses `compose(..)` (see [Chapter 4](ch4.md/#user-content-generalcompose)) to pass `setDomContent(..)` into `spreadArgs(..)`, and then that is passed as the iterator-function to `each(..)`. Each tuple is spread out as the arguments to `setDOMContent(..)`, which then updates the DOM element accordingly.

That's two of the main UI methods down, one to go: `addStock(..)`. Let's define it in its entirety, then we'll examine it step by step as before:

```js
addStock(tickerElem,data) {
    var [stockElem, ...infoChildElems] = map(
        createElement
    )
    ( [ "li", "span", "span", "span" ] );
    var attrValTuples = [
        [ ["class","stock"], ["data-stock-id",data.id] ],
        [ ["class","stock-name"] ],
        [ ["class","stock-price"] ],
        [ ["class","stock-change"] ]
    ];
    var elemsAttrsTuples =
        zip( [stockElem, ...infoChildElems], attrValTuples );

    // !!SIDE EFFECTS!!
    each( function setElemAttrs([elem,attrValTupleList]){
        each(
            spreadArgs( partial( setElemAttr, elem ) )
        )
        ( attrValTupleList );
    } )
    ( elemsAttrsTuples );

    // !!SIDE EFFECTS!!
    stockTickerUI.updateStockElems( infoChildElems, data );
    reduce( appendDOMChild )( stockElem )( infoChildElems );
    appendDOMChild( tickerElem, stockElem );
}
```

This UI method needs to create the bare DOM structure for a new stock element, and then use `stockTickerUI.updateStockElems(..)` to update its content. First:

```js
var [stockElem, ...infoChildElems] = map(
    createElement
)
( [ "li", "span", "span", "span" ] );
```

We create the parent `<li>` and the three children `<span>` elements, assigning them respectively to `stockElem` and the `infoChildElems` list.

To initialize these elements with the appropriate DOM attributes, we create a list of lists-of-tuples. Each item in the main list corresponds to the four DOM elements, in order. Each sub-list contains tuples that represent attribute-value pairs to be set on each corresponding DOM element, respectively:

```js
var attrValTuples = [
    [ ["class","stock"], ["data-stock-id",data.id] ],
    [ ["class","stock-name"] ],
    [ ["class","stock-price"] ],
    [ ["class","stock-change"] ]
];
```

We now want to `zip(..)` a list of the four DOM elements with this `attrValTuples` list:

```js
var elemsAttrsTuples =
    zip( [stockElem, ...infoChildElems], attrValTuples );
```

The structure of this list would now look like:

```txt
[
    [ <li>, [ ["class","stock"], ["data-stock-id",data.id] ] ],
    [ <span>, [ ["class","stock-name"] ] ],
    ..
]
```

If we wanted to imperatively process this kind of data structure to assign the attribute-value tuples into each DOM element, we'd probably use nested `for`-loops. Our FP approach will be similar, but with nested `each(..)` iterations:

```js
// !!SIDE EFFECTS!!
each( function setElemAttrs([elem,attrValTupleList]){
    each(
        spreadArgs( partial( setElemAttr, elem ) )
    )
    ( attrValTupleList );
} )
( elemsAttrsTuples );
```

The outer `each(..)` iterates the list of tuples, with each `elem` and its associated `attrValTupleList` spread out as named parameters to `setElemAttrs(..)` via parameter array-destructuring as explained earlier.

Inside this outer iteration "loop", the sub-list of attribute-value tuples is iterated with an inner `each(..)`. The inner iterator-function is an arguments-spread (of each attribute-value tuple) for the partial-application of `setElemAttr(..)` with `elem` as its first argument.

At this point, we have a list of `<span>` elements, each filled out with attributes, but no `innerHTML` content. We set the `data` in the `<span>` elements with `stockTickerUI.updateStockElems(..)`, the same as for a stock-update event.

Now, we need to append these `<span>`s to the parent `<li>`, and we do that with a `reduce(..)` (see [Chapter 9](ch9.md/#reduce)):

```js
reduce( appendDOMChild )( stockElem )( infoChildElems );
```

Finally, a plain ol' DOM mutation side effect to append the new stock element to the widget's DOM:

```js
appendDOMChild( tickerElem, stockElem );
```

Phew! Did you follow all that? I recommend re-reading that discussion a few times, and practicing with the code, before you move on.

### Subscribing to Observables

Our last major task is to subscribe to the observables defined in `ch11-code/stock-ticker-events.js`, attaching these subscriptions to the appropriate main UI methods (`addStock(..)` and `updateStock(..)`).

First, we notice that those methods each expect `tickerElem` as first parameter. Let's make a list (`stockTickerUIMethodsWithDOMContext`) that encapsulates the ticker widget's DOM element with each of these two methods, via partial application (aka, [closure; see Chapter 2](ch2.md/#keeping-scope)):

```js
var ticker = document.getElementById( "stock-ticker" );

var stockTickerUIMethodsWithDOMContext = map(
    pipe( partialRight, unary )( partial, ticker )
)
( [ stockTickerUI.addStock, stockTickerUI.updateStock ] );
```

First, we use `partialRight(..)` (right-partial application) on the `partial(..)` utility, presetting its right-most argument to be `ticker`. Then we pass this right-partially-applied `partial(..)` function through `unary(..)` to protect it from receiving undesired extra arguments from `map(..)` (see [Chapter 3](ch3.md/#user-content-mapunary)), via `pipe(..)`. The result is a mapper function which is expecting a function to partially-apply (with one argument: `ticker`). We use that mapper function to `map(..)` the `stockTickerUI.addStock(..)` and `stockTickerUI.updateStock(..)` functions, respectively.

The result of `map(..)` is the array `stockTickerUIMethodsWithDOMContext`, which holds the two partially applied functions; these two functions are now suitable as observable-subscription handlers.

Though we're using closure to preserve the `ticker` state with these two functions, in [Chapter 7](ch7.md) we saw that we could have "kept" this `ticker` value as a property on an object, perhaps via `this`-binding each function to `stockTickerUI`. Because `this` is an implicit input (see [Chapter 2](ch2.md/#whats-this)) and that's generally not as preferable, I chose the closure form over the object form.

To subscribe to the observables, let's make an unbound-method helper:

```js
var subscribeToObservable =
    pipe( unboundMethod, uncurry )( "subscribe" );
```

`unboundMethod("subscribe")` is curried so we `uncurry(..)` it (see [Chapter 3](ch3.md/#no-curry-for-me-please)).

Now, we just need a list of the observables, so we can `zip(..)` that with the list of DOM-bound UI methods; the resulting tuples will then include both the observable and the listener function to subscribe to it. We process each tuple with `each(..)` and use `spreadArgs(..)` (see [Chapter 3](ch3.md/#user-content-spreadargs)) to spread the tuple's contents out as the two arguments to `subscribeToObservable(..)`:

```js
var stockTickerObservables = [ newStocks, stockUpdates ];

// !!SIDE EFFECTS!!
each( spreadArgs( subscribeToObservable ) )
( zip( stockTickerUIMethodsWithDOMContext, stockTickerObservables ) );
```

We're technically mutating the state of those observables to subscribe to them, and moreover, we're using `each(..)` -- pretty much always associated with side effects! -- so we call that out with our code comment.

That's it! Spend the same time reviewing and comparing this code to its imperative alternatives as we did with the stock ticker events discussion earlier. Really, take your time. I know it's been a lot to read, but your whole journey through this book comes down to being able to digest and understand this kind of code.

How do you feel now about using FP in a balanced way in your JavaScript? Keep practicing just like we did here!

## Summary

The example code we discussed in this chapter should be viewed in its entirety, not just in the broken-out snippets as presented in this chapter. Stop right now and go read through the full files. Make sure you understand them in full context.

This example code is not meant to be prescriptive of exactly how you should write your code. It's meant to be more descriptive of how to think about and begin approaching such tasks with FP-Light techniques. It's meant to draw as many correlations between the different concepts of this book as possible. It's meant to explore FP in the context of more "real" code than we typically afford for a single snippet.

I am quite sure that as I learn FP better on my own journey, I will continue to improve how I would write this example code. What you see now is just a snapshot on my curve. I hope it will just be such for you, as well.

As we draw the main text of this book to a close, I want to remind you of that readability curve that I [shared back in Chapter 1](ch1.md/#readability):

<p align="center">
    <img src="images/fig17.png" width="50%">
</p>

It's so important that you internalize the truth of that graph and set realistic expectations for yourself on this journey to learn and apply FP principles to your JavaScript. You've made it this far, and that's quite an accomplishment.

But don't stop when you dip toward that trough of despair and disenchantment. What's waiting on the other side is a way of thinking about and communicating with your code that's more readable, understandable, verifiable, and ultimately, more reliable.

I can't think of any more noble goal for us as developers to strive toward. Thanks for sharing in my journey to learn FP principles in JavaScript. I hope your experience is as rich and hopeful as mine!


================================================
FILE: manuscript/ch2.md
================================================
# Functional-Light JavaScript
# Chapter 2: The Nature Of Functions

Functional Programming is **not just programming with the `function` keyword.** Oh, if only it was that easy -- I could end the book right here! Nevertheless, functions really *are* at the center of FP. And it's how we use functions that makes our code *functional*.

But how sure are you that you know what *function* really means?

In this chapter, we're going to lay the groundwork for the rest of the book by exploring all the foundational aspects of functions. Actually, this is a review of all the things even a non-FP programmer should know about functions. But certainly if we want to get the most out of FP concepts, it's essential we *know* functions inside and out.

Brace yourself, because there's a lot more to the function than you may have realized.

## What Is a Function?

The question "What is a function?" superficially seems to have an obvious answer: a function is a collection of code that can be executed one or more times.

While this definition is reasonable, it's missing some very important essence that is the core of a *function* as it applies to FP. So let's dig below the surface to understand functions more completely.

### Brief Math Review

I know I've promised we'd stay away from math as much as possible, but bear with me for a moment as we quickly observe some fundamental things about functions and graphs from algebra before we proceed.

Do you remember learning anything about `f(x)` back in school? What about the equation `y = f(x)`?

Let's say an equation is defined like this: <code>f(x) = 2x<sup>2</sup> + 3</code>. What does that mean? What does it mean to graph that equation? Here's the graph:

<p align="center">
    <img src="images/fig1.png" width="40%">
</p>

What you can notice is that for any value of `x`, say `2`, if you plug it into the equation, you get `11`. What is `11`, though? It's the *return value* of the `f(x)` function, which earlier we said represents a `y` value.

In other words, we can choose to interpret the input and output values as a point at `(2,11)` on that curve in the graph. And for every value of `x` we plug in, we get another `y` value that pairs with it as a coordinate for a point. Another is `(0,3)`, and another is `(-1,5)`. Put all those points together, and you have the graph of that parabolic curve as shown here.

So what's any of this got to do with FP?

In math, a function always takes input(s), and always gives an output. A term you'll often hear around FP is "morphism"; this is a fancy way of describing a set of values that maps to another set of values, like the inputs of a function related to the outputs of that function.

In algebraic math, those inputs and outputs are often interpreted as components of coordinates to be graphed. In our programs, however, we can define functions with all sorts of input(s) and output(s), even though they'll rarely be interpreted as a visually plotted curve on a graph.

### Function vs Procedure

So why all the talk of math and graphs? Because essentially Functional Programming is about embracing using functions as *functions* in this mathematical sense.

You may be more accustomed to thinking of functions as procedures. What's the difference? A procedure is an arbitrary collection of functionality. It may have inputs, it may not. It may have an output (`return` value), it may not.

A function takes input(s) and definitely always has a `return` value.

If you plan to do Functional Programming, **you should be using functions as much as possible**, and trying to avoid procedures wherever possible. All your `function`s should take input(s) and return output(s).

Why? The answer to that will have many levels of meaning that we'll uncover throughout this book.

## Function Input

So far, we can conclude that functions must expect input. But let's dig into how function inputs work.

You sometimes hear people refer to these inputs as "arguments" and sometimes as "parameters". So what's that all about?

*Arguments* are the values you pass in, and *parameters* are the named variables inside the function that receive those passed-in values. Example:

```js
function foo(x,y) {
    // ..
}

var a = 3;

foo( a, a * 2 );
```

`a` and `a * 2` (actually, the result of `a * 2`, which is `6`) are the *arguments* to the `foo(..)` call. `x` and `y` are the *parameters* that receive the argument values (`3` and `6`, respectively).

**Note:** In JavaScript, there's no requirement that the number of *arguments* matches the number of *parameters*. If you pass more *arguments* than you have declared *parameters* to receive them, the values pass in just fine untouched. These values can be accessed in a few different ways, including the old-school `arguments` object you may have heard of before. If you pass fewer *arguments* than the declared *parameters*, each unmatched parameter is treated as an "undefined" variable, meaning it's present and available in the scope of the function, but just starts out with the empty `undefined` value.

### Defaulting Parameters

As of ES6, parameters can declare *default values*. In the case where the argument for that parameter is not passed, or it's passed the value `undefined`, the default assignment expression is substituted.

Consider:

```js
function foo(x = 3) {
    console.log( x );
}

foo();                  // 3
foo( undefined );       // 3
foo( null );            // null
foo( 0 );               // 0
```

It's always a good practice to think about any default cases that can aid the usability of your functions. However, defaulting parameters can lead to more complexity in terms of reading and understanding the variations of how a function is called. Be judicious in how much you rely on this feature.

### Counting Inputs

The number of arguments a function "expects" -- how many arguments you'll likely want to pass to it -- is determined by the number of parameters that are declared:

```js
function foo(x,y,z) {
    // ..
}
```

`foo(..)` *expects* three arguments, because it has three declared parameters. This count has a special term: arity. Arity is the number of parameters in a function declaration. The arity of `foo(..)` is `3`.

Furthermore, a function with arity 1 is also called "unary", a function with arity 2 is also called "binary", and a function with arity 3 or higher is called "n-ary".

You may wish to inspect a function reference during the runtime of a program to determine its arity. This can be done with the `length` property of that function reference:

```js
function foo(x,y,z) {
    // ..
}

foo.length;             // 3
```

One reason for determining the arity during execution would be if a piece of code received a function reference from multiple sources, and sent different values depending on the arity of each.

For example, imagine a case where an `fn` function reference could expect one, two, or three arguments, but you always want to just pass a variable `x` in the last position:

```js
// `fn` is set to some function reference
// `x` exists with some value

if (fn.length == 1) {
    fn( x );
}
else if (fn.length == 2) {
    fn( undefined, x );
}
else if (fn.length == 3) {
    fn( undefined, undefined, x );
}
```

**Tip:** The `length` property of a function is read-only and it's determined at the time you declare the function. It should be thought of as essentially a piece of metadata that describes something about the intended usage of the function.

One gotcha to be aware of is that certain kinds of parameter list variations can make the `length` property of the function report something different than you might expect:

```js
function foo(x,y = 2) {
    // ..
}

function bar(x,...args) {
    // ..
}

function baz( {a,b} ) {
    // ..
}

foo.length;             // 1
bar.length;             // 1
baz.length;             // 1
```

What about counting the number of arguments the current function call received? This was once trivial, but now the situation is slightly more complicated. Each function has an `arguments` object (array-like) available that holds a reference to each of the arguments passed in. You can then inspect the `length` property of `arguments` to figure out how many were actually passed:

```js
function foo(x,y,z) {
    console.log( arguments.length );
}

foo( 3, 4 );    // 2
```

As of ES5 (and strict mode, specifically), `arguments` is considered by some to be sort of deprecated; many avoid using it if possible. In JS, we "never" break backward compatibility no matter how helpful that may be for future progress, so `arguments` will never be removed. But it's now commonly suggested that you avoid using it whenever possible.

However, I suggest that `arguments.length`, and only that, is OK to keep using for those cases where you need to care about the passed number of arguments. A future version of JS might possibly add a feature that offers the ability to determine the number of arguments passed without consulting `arguments.length`; if that happens, then we can fully drop usage of `arguments`!

Be careful: **never** access arguments positionally, like `arguments[1]`. Stick to `arguments.length` only, and only if you must.

Except, how will you access an argument that was passed in a position beyond the declared parameters? I'll answer that in a moment; but first, take a step back and ask yourself, "Why would I want to do that?" Seriously. Think about that closely for a minute.

It should be pretty rare that this occurs; it shouldn't be something you regularly expect or rely on when writing your functions. If you find yourself in such a scenario, spend an extra 20 minutes trying to design the interaction with that function in a different way. Name that extra argument even if it's exceptional.

A function signature that accepts an indeterminate amount of arguments is referred to as a variadic function. Some people prefer this style of function design, but I think you'll find that often the FPer wants to avoid these where possible.

OK, enough harping on that point.

Say you do need to access the arguments in a positional array-like way, possibly because you're accessing an argument that doesn't have a formal parameter at that position. How do we do it?

ES6 to the rescue! Let's declare our function with the `...` operator -- variously referred to as "spread", "rest", or (my preference) "gather":

```js
function foo(x,y,z,...args) {
    // ..
}
```

See the `...args` in the parameter list? That's an ES6 declarative form that tells the engine to collect (ahem, "gather") all remaining arguments (if any) not assigned to named parameters, and put them in a real array named `args`. `args` will always be an array, even if it's empty. But it **will not** include values that are assigned to the `x`, `y`, and `z` parameters, only anything else that's passed in beyond those first three values:

```js
function foo(x,y,z,...args) {
    console.log( x, y, z, args );
}

foo();                  // undefined undefined undefined []
foo( 1, 2, 3 );         // 1 2 3 []
foo( 1, 2, 3, 4 );      // 1 2 3 [ 4 ]
foo( 1, 2, 3, 4, 5 );   // 1 2 3 [ 4, 5 ]
```

So, if you *really* want to design a function that can account for an arbitrary number of arguments to be passed in, use `...args` (or whatever name you like) on the end. Now, you'll have a real, non-deprecated, non-yucky array to access those argument values from.

Just pay attention to the fact that the value `4` is at position `0` of that `args`, not position `3`. And its `length` value won't include those three `1`, `2`, and `3` values. `...args` gathers everything else, not including the `x`, `y`, and `z`.

You *can* use the `...` operator in the parameter list even if there's no other formal parameters declared:

```js
function foo(...args) {
    // ..
}
```

Now `args` will be the full array of arguments, whatever they are, and you can use `args.length` to know exactly how many arguments have been passed in. And you're safe to use `args[1]` or `args[317]` if you so choose. Please don't pass in 318 arguments, though.

### Arrays of Arguments

What if you wanted to pass along an array of values as the arguments to a function call?

```js
function foo(...args) {
    console.log( args[3] );
}

var arr = [ 1, 2, 3, 4, 5 ];

foo( ...arr );                      // 4
```

Our new friend `...` is used, but now not just in the parameter list; it's also used in the argument list at the call-site. It has the opposite behavior in this context. In a parameter list, we said it *gathered* arguments together. In an argument list, it *spreads* them out. So the contents of `arr` are actually spread out as individual arguments to the `foo(..)` call. Do you see how that's different from just passing in a reference to the whole `arr` array?

By the way, multiple values and `...` spreadings can be interleaved, as you see fit:

```js
var arr = [ 2 ];

f
Download .txt
gitextract_xx3xfcwu/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── content-question.md
│       ├── foreign-translation-request.md
│       ├── report-technical-mistake.md
│       └── textual-grammar-typo.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── LICENSE.txt
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── ch11-code/
│   ├── fp-helpers.js
│   ├── index.html
│   ├── mock-server.js
│   ├── stock-ticker-events.js
│   ├── stock-ticker.css
│   └── stock-ticker.js
└── manuscript/
    ├── README.md
    ├── apA.md
    ├── apB.md
    ├── apC.md
    ├── ch1.md
    ├── ch10.md
    ├── ch11.md
    ├── ch2.md
    ├── ch3.md
    ├── ch4.md
    ├── ch5.md
    ├── ch6.md
    ├── ch7.md
    ├── ch8.md
    ├── ch9.md
    ├── foreword.md
    ├── images/
    │   └── marketing/
    │       └── front-cover-hd.tiff
    └── preface.md
Download .txt
SYMBOL INDEX (38 symbols across 4 files)

FILE: ch11-code/fp-helpers.js
  function filterOut (line 20) | function filterOut(predicateFn,arr) {
  function unary (line 24) | function unary(fn) {
  function not (line 30) | function not(predicate) {
  function reverseArgs (line 36) | function reverseArgs(fn) {
  function spreadArgs (line 42) | function spreadArgs(fn) {
  function partial (line 48) | function partial(fn,...presetArgs) {
  function partialRight (line 54) | function partialRight(fn,...presetArgs) {
  function curry (line 60) | function curry(fn,arity = fn.length) {
  function uncurry (line 75) | function uncurry(fn) {
  function zip (line 87) | function zip(arr1,arr2) {
  function compose (line 99) | function compose(...fns) {
  function prop (line 107) | function prop(name,obj) {
  function setProp (line 111) | function setProp(name,obj,val) {
  function unboundMethod (line 117) | function unboundMethod(methodName,argCount = 2) {

FILE: ch11-code/mock-server.js
  function connectToServer (line 1) | function connectToServer() {
  method on (line 14) | on(evtName,cb) {
  method addEventListener (line 18) | addEventListener(...args) {
  method removeEventListener (line 21) | removeEventListener(){}
  method emit (line 22) | emit(evtName,...args) {
  function randInRange (line 61) | function randInRange(min = 0,max = 1E9) {

FILE: ch11-code/stock-ticker-events.js
  function addStockName (line 23) | function addStockName(stock) {
  function formatStockNumbers (line 27) | function formatStockNumbers(stock) {
  function formatSign (line 40) | function formatSign(val) {
  function formatCurrency (line 47) | function formatCurrency(val) {

FILE: ch11-code/stock-ticker.js
  method updateStockElems (line 5) | updateStockElems(stockInfoChildElemList,data) {
  method updateStock (line 25) | updateStock(tickerElem,data) {
  method addStock (line 39) | addStock(tickerElem,data) {
  function stripPrefix (line 100) | function stripPrefix(prefixRegex,val) {
  function listify (line 104) | function listify(listOrItem) {
  function isTextNode (line 111) | function isTextNode(node) {
  function getElemAttr (line 115) | function getElemAttr(prop,elem) {
  function setElemAttr (line 119) | function setElemAttr(elem,prop,val) {
  function matchingStockId (line 124) | function matchingStockId(id,node) {
  function isStockInfoChildElem (line 128) | function isStockInfoChildElem(elem) {
  function getStockElem (line 132) | function getStockElem(tickerElem,stockId) {
  function getStockInfoChildElems (line 141) | function getStockInfoChildElems(stockElem) {
  function appendDOMChild (line 150) | function appendDOMChild(parentNode,childNode) {
  function setDOMContent (line 156) | function setDOMContent(elem,html) {
Condensed preview — 35 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (562K chars).
[
  {
    "path": ".editorconfig",
    "chars": 158,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = tab\nindent_size = 4\n\n[*.md]"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 208,
    "preview": "# These are supported funding model platforms\n\ngithub: [getify]\npatreon: getify\ncustom: ['https://www.paypal.com/paypalm"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/content-question.md",
    "chars": 358,
    "preview": "---\nname: Content Question\nabout: Ask a question about something you read in the books?\nlabels: \n\n---\n\n**Yes, I promise "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/foreign-translation-request.md",
    "chars": 981,
    "preview": "---\nname: Foreign Translation Request\nabout: Want to request a translation into a foreign language?\nlabels: \n\n---\n\nPleas"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/report-technical-mistake.md",
    "chars": 347,
    "preview": "---\nname: Report Technical Mistake\nabout: Help us fix a mistake in the code.\nlabels: \n\n---\n\n**Yes, I promise I've read t"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/textual-grammar-typo.md",
    "chars": 365,
    "preview": "---\nname: Textual/Grammar Typo\nabout: Help us correct a spelling or grammar error in the text.\nlabels: \n\n---\n\n**Yes, I p"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1848,
    "preview": "# Contributing\n\nPlease feel free to contribute to the quality of this content by submitting PR's for improvements to cod"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "chars": 255,
    "preview": "**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONT"
  },
  {
    "path": "LICENSE.txt",
    "chars": 19116,
    "preview": "Attribution-NonCommercial-NoDerivatives 4.0 International\n\n============================================================="
  },
  {
    "path": "PULL_REQUEST_TEMPLATE.md",
    "chars": 255,
    "preview": "**Yes, I promise I've read the [Contributions Guidelines](https://github.com/getify/Functional-Light-JS/blob/master/CONT"
  },
  {
    "path": "README.md",
    "chars": 6439,
    "preview": "# Functional-Light JavaScript\n\n[![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC%20BY--NC--ND%204.0-b"
  },
  {
    "path": "ch11-code/fp-helpers.js",
    "chars": 2371,
    "preview": "\"use strict\";\n\nvar pipe = reverseArgs(compose);\n\n// curried list operators\nvar map = unboundMethod( \"map\", 2 );\nvar filt"
  },
  {
    "path": "ch11-code/index.html",
    "chars": 632,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>Functional-Light JavaScript, Ch11: Stock Ticker</title>\n<lin"
  },
  {
    "path": "ch11-code/mock-server.js",
    "chars": 1617,
    "preview": "function connectToServer() {\n\t// faking an event emitter attached to a server-event stream\n\treturn evtEmitter;\n}\n\n\n// **"
  },
  {
    "path": "ch11-code/stock-ticker-events.js",
    "chars": 1210,
    "preview": "var server = connectToServer();\n\nvar formatDecimal = unboundMethod( \"toFixed\" )( 2 );\nvar formatPrice = pipe( formatDeci"
  },
  {
    "path": "ch11-code/stock-ticker.css",
    "chars": 435,
    "preview": "*, *:before, *:after {\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n#stock-ticker {\n\tbackground-color: #e"
  },
  {
    "path": "ch11-code/stock-ticker.js",
    "chars": 3740,
    "preview": "\"use strict\";\n\nvar stockTickerUI = {\n\n\tupdateStockElems(stockInfoChildElemList,data) {\n\t\tvar getDataVal = curry( reverse"
  },
  {
    "path": "manuscript/README.md",
    "chars": 4691,
    "preview": "# Functional-Light JavaScript\n\n<a href=\"https://leanpub.com/fljs\"><img src=\"images/marketing/front-cover-small.png\" widt"
  },
  {
    "path": "manuscript/apA.md",
    "chars": 27958,
    "preview": "# Functional-Light JavaScript\n# Appendix A: Transducing\n\nTransducing is a more advanced technique than we've covered in "
  },
  {
    "path": "manuscript/apB.md",
    "chars": 22608,
    "preview": "# Functional-Light JavaScript\n# Appendix B: The Humble Monad\n\nLet me just start off this appendix by admitting: I did no"
  },
  {
    "path": "manuscript/apC.md",
    "chars": 17156,
    "preview": "# Functional-Light JavaScript\n# Appendix C: FP Libraries\n\nIf you've been reading this book from start to finish, take a "
  },
  {
    "path": "manuscript/ch1.md",
    "chars": 23590,
    "preview": "# Functional-Light JavaScript\n# Chapter 1: Why Functional Programming?\n\n> Functional programmer: (noun) One who names va"
  },
  {
    "path": "manuscript/ch10.md",
    "chars": 19738,
    "preview": "# Functional-Light JavaScript\n# Chapter 10: Functional Async\n\nAt this point of the book, you now have all the raw concep"
  },
  {
    "path": "manuscript/ch11.md",
    "chars": 27730,
    "preview": "# Functional-Light JavaScript\n# Chapter 11: Putting It All Together\n\nBy now, you have everything you need to understand "
  },
  {
    "path": "manuscript/ch2.md",
    "chars": 47114,
    "preview": "# Functional-Light JavaScript\n# Chapter 2: The Nature Of Functions\n\nFunctional Programming is **not just programming wit"
  },
  {
    "path": "manuscript/ch3.md",
    "chars": 51992,
    "preview": "# Functional-Light JavaScript\n# Chapter 3: Managing Function Inputs\n\n[Chapter 2](ch2.md) explored the core nature of JS "
  },
  {
    "path": "manuscript/ch4.md",
    "chars": 42549,
    "preview": "# Functional-Light JavaScript\n# Chapter 4: Composing Functions\n\nBy now, I hope you're feeling much more comfortable with"
  },
  {
    "path": "manuscript/ch5.md",
    "chars": 50434,
    "preview": "# Functional-Light JavaScript\n# Chapter 5: Reducing Side Effects\n\nIn [Chapter 2](ch2.md), we discussed how a function ca"
  },
  {
    "path": "manuscript/ch6.md",
    "chars": 25931,
    "preview": "# Functional-Light JavaScript\n# Chapter 6: Value Immutability\n\nIn [Chapter 5](ch5.md), we talked about the importance of"
  },
  {
    "path": "manuscript/ch7.md",
    "chars": 32395,
    "preview": "# Functional-Light JavaScript\n# Chapter 7: Closure vs. Object\n\nA number of years ago, Anton van Straaten crafted what ha"
  },
  {
    "path": "manuscript/ch8.md",
    "chars": 37430,
    "preview": "# Functional-Light JavaScript\n# Chapter 8: Recursion\n\nDid you have fun down our little closures/objects rabbit hole in t"
  },
  {
    "path": "manuscript/ch9.md",
    "chars": 65213,
    "preview": "# Functional-Light JavaScript\n# Chapter 9: List Operations\n\n> *If you can do something awesome, keep doing it repeatedly"
  },
  {
    "path": "manuscript/foreword.md",
    "chars": 4057,
    "preview": "# Functional-Light JavaScript\n# Foreword\n\nIt's no secret that I am a Functional Programming nut. I evangelize functional"
  },
  {
    "path": "manuscript/preface.md",
    "chars": 5366,
    "preview": "# Functional-Light JavaScript\n# Preface\n\n> *A monad is just a monoid in the category of endofunctors.*\n\nDid I just lose "
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the getify/Functional-Light-JS GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 35 files (22.4 MB), approximately 127.7k tokens, and a symbol index with 38 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!