LoginSignup
0
0

More than 5 years have passed since last update.

関数のComposition

Posted at

Functional JavaScript: Function Composition For Every Day Use.

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

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>
*/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0