javascript - 如何在 JavaScript 中使用 pointfree 风格而不失可读性?

标签 javascript functional-programming ramda.js pointfree

当我尝试以 pointfree 风格编写 JavaScript 时,我发现如果强制每个函数都采用这种风格,有时会失去其可读性。例如:

import R from 'ramda'

const ceil = Math.ceil

const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}

// ================= Pointful style ==================
const pageCount = (pagination) => {
  const pages = ceil(pagination.total / pagination.itemsPerPage)
  const remainPages = pagination.total % pagination.itemsPerPage === 0 ? 0 : 1
  return pages + remainPages
} 

pageCount(pagination) // => 11

// ================ Pointfree style ==================
const getPages = R.pipe(
  R.converge(R.divide, [R.prop('total'), R.prop('itemsPerPage')]),
  ceil
)

const getRemainPages = R.ifElse(
  R.pipe(
     R.converge(R.modulo, [R.prop('total'), R.prop('itemsPerPage')]),
     R.equals(0)
  ),
  R.always(0),
  R.always(1)
)

const pageCount2 = R.converge(R.add, [
  getPages,
  getRemainPages
])

pageCount2(pagination) // => 11

我编写了一个简单的分页模块来计算 pageCount,以 pointful 样式和 pointfree 样式给出总项目数和每页项目数。显然,pointful 样式比 pointfree 样式版本更具可读性。后者有点晦涩。

我做的对吗?有什么方法可以使 pointfree 风格的代码更具可读性吗?

最佳答案

手工作文

让我们从手动组合函数开始:

const calcPages = (totalItems, itemsPerPage) =>
 ceil(div(totalItems, itemsPerPage));


const div = (x, y) => x / y;

const ceil = Math.ceil;


const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}


console.log(
  calcPages(pagination.total, pagination.itemsPerPage)
);

程序组成

下一步我们将参数抽象出来:

const comp2 = (f, g) => (x, y) => f(g(x, y));

const div = (x, y) => x / y;

const ceil = Math.ceil;


const calcPages = comp2(ceil, div);


const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}


console.log(
  calcPages(pagination.total, pagination.itemsPerPage)
);

函数定义现在是无点的。但是调用代码不是。如果您知道高阶函数 comp2 的工作原理,表达式 comp2(ceil, div) 对您来说就非常具有声明性。

现在很明显,calcPages 是错误的名称,因为函数组合更为通用。我们称它为 ... intDiv(好吧,可能有更好的名字,但我的数学很烂)。

解构修饰符

下一步我们修改intDiv,让它可以处理对象:

const destruct2 = (x, y) => f => ({[x]:a, [y]:b}) => f(a, b);

const comp2 = (f, g) => (x, y) => f(g(x, y));

const div = (x, y) => x / y;

const ceil = Math.ceil;


const intDiv = comp2(ceil, div);

const calcPages = destruct2("total", "itemsPerPage") (intDiv);


const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}


console.log(
  calcPages(pagination)
);

我再次调用修改后的函数 calcPages,因为它现在需要一个特定的 pagination 对象,因此不太通用。

如果您知道所涉及的高阶函数是如何工作的,那么一切都是声明式的并且可读性很好,即使它是以无点风格编写的。

结论

无点风格是函数组合、柯里化(Currying)和高阶函数的结果。它本身不是一个东西。如果您停止使用这些工具以避免无点风格,那么您将失去函数式编程提供的许多表现力和优雅。

关于javascript - 如何在 JavaScript 中使用 pointfree 风格而不失可读性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42068296/

相关文章:

javascript - 通过使用 Ramda 将 Value 中的字段附加到 Key 中来修改对象的 Key

javascript - 在 Doctype 声明之前添加 script 标签

javascript - 如何使用 Laravel 在 DataTable 中添加列并从数据库返回值

JavaScript 和 'this' 位于立即执行的函数中

scala - 函数式编程: recursive loop output fibonacci sequence in scala

javascript - 无需身份验证即可获取 JSON 形式的 Twitter Feed

kotlin - Kotlin-倍数IO的组成

python - 是否有类似 Python 中 Clojure 的线程宏的东西?

javascript - 类型 'number' 不可分配给类型 'ReadonlyArray<{}>'