関数のComposition


[Functional JavaScript: Function Composition For Every Day Use.](https://hackernoon.com/javascript-functional-composition-for-every-day-use-22421ef65a10)

```javascript
// Arrow function
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions
const encodeAttribute = (x = '') => {
  return x.replace(/"/g, '&quot;')
}

const toAttributeString = (x = {}) => {
  return Object.keys(x)
          .map(attr => `${encodeAttribute(attr)}="${encodeAttribute(x[attr])}"`)
          .join(" ")
}

const tagAttributes = x => (c = "") => {
  return `<${x.tag}${x.attr? " " :""}${toAttributeString(x.attr)}>${c}</${x.tag}>`
}

const tag = x => {
  return typeof x === "string"
            ? tagAttributes({tag: x})
            : tagAttributes(x)
}

console.log(tag("b")("content"))
console.log(tag({tag: "b", attr: {class: "title", src: "http"}})("content"))

const listGroup = tag({tag: "ul", attr: {class: "list-group"}})
const listGroupItem = tag({tag: "li", attr: {class: "list-group-item"}})
const listGroupItems = items => {
  return items.map(listGroupItem).join("")
}

// listGroup is a function which takes content as argument, below calling without any content
console.log(listGroup()) //<ul class="list-group"></ul>
console.log(listGroupItem()) //<li class="list-group-item"></li>
console.log(listGroupItems(['Cras justo', 'Dapibus ac']))
// <li class="list-group-item">Cras justo</li><li class="list-group-item">Dapibus ac</li>

// Passing listGroupItems as argument for listGroup
console.log(listGroup(listGroupItems(['Cras justo', 'Dapibus ac'])))
// <ul class="list-group">
//  <li class="list-group-item">Cras justo</li>
//  <li class="list-group-item">Dapibus ac</li>
// </ul>

const listGroupTag = tag({tag: "ul", attr: {class: "list-group"}})
const listGroup2 = items => {
  return listGroupTag(listGroupItems(items))
}

console.log((listGroup2(['Cras justo', 'Dapibus ac'])))

// compose: call functions right to left
const compose = (...functions) => data => {
  return functions.reduceRight((value, func) => func(value), data)
}
// pipe: call functions left to right
const pipe = (...functions) => data => {
  return functions.reduce((value, func) => func(value), data)
}

const listGroup3 = items => {
  return compose(listGroupTag, listGroupItems)(items)
}

console.log(listGroup3(['Cras justo', 'Dapibus ac']))

// compose returns function which takes "data" as argument, so we can write as below
const listGroup4 = compose(listGroupTag, listGroupItems)

console.log((listGroup4(['Cras justo', 'Dapibus ac'])))

// The power of function composition is realized as your codebase grows,
// allowing you to create numerous compositions.

const panelTag = tag({tag: "div", attr: {class: "panel panel-default"}})
const panelBody = tag({tag: "div", attr: {class: "panel-body"}})
const basicPanel = compose(panelTag, panelBody)

console.log(basicPanel("content"))
// <div class="panel panel-default"><div class="panel-body">content</div></div>
const listGroupPanel = compose(basicPanel, listGroupTag, listGroupItems)
console.log(listGroupPanel(['Cras justo', 'Dapibus ac']))
/*
<div class="panel panel-default">
  <div class="panel-body">
    <ul class="list-group">
      <li class="list-group-item">Cras justo</li>
      <li class="list-group-item">Dapibus ac</li>
    </ul>
  </div>
</div>
*/

```