首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >注入有副作用的函数

注入有副作用的函数
EN

Stack Overflow用户
提问于 2017-02-12 02:19:31
回答 1查看 318关注 0票数 0

在使用高阶函数时,我遇到了一个问题。假设我有以下不使用它们的代码(而是调用全局函数):

代码语言:javascript
复制
import {db_insert} from 'some-db-lib' // function with side-effect

const save_item = (item) => {
    // some logic like validating item data...
    db_insert(item) // call db_insert globally
}

const handle_request = (request) => {
    // some logic like sanitizing request...
    save_item(request.data) // call save_item globally
}

handle_request(some_request)

现在,同样的例子,通过使用高阶函数(将副作用作为函数参数注入):

代码语言:javascript
复制
import {db_insert} from 'some-db-lib' // function with side-effect

const save_item = (item, insert) => { // inject insert
    // some logic like validating item data...
    insert(item)
}

const handle_request = (request, save, insert) => { // inject save and insert
    // some logic like sanitizing request...
    save(request.data, insert)
}

handle_request(some_request, save_item, db_insert)

想象一下,在一个更大的函数树中互相调用。最后一个例子会变成一大堆相互传递函数的函数。

这是隔离副作用的正确方法吗?我是不是遗漏了什么?

EN

回答 1

Stack Overflow用户

发布于 2017-02-12 04:49:23

高阶函数

高阶函数用于从函数应用中抽象出来。公共HOF至少接受一个函数f和至少一个附加参数x,并将f应用于x。下面是最简单的例子:

代码语言:javascript
复制
const apply = (f, x) => f(x);

不是特别有趣。关键的一点是,每个有意义的HOF都会做一些额外的事情。例如,它迭代地应用于给定函数(mapreduce)。它由两个函数组成:

代码语言:javascript
复制
const comp = (f, g) => x => f(g(x));

const inc = x => x + 1;

console.log(
  comp(inc, inc) (0) // 2
);

它将一个函数应用于Object,即使此函数只接受Numbers:

代码语言:javascript
复制
const destruct = (x, y, f) => ({[x]:a, [y]:b}) => f(a, b);

const add = (x, y) => x + y;

const o = {propA:2, propB:3};

console.log(
  destruct("propA", "propB", add) (o) // 5
);

或者它部分应用了一个函数:

代码语言:javascript
复制
const partial = (f, ...args) => (...args2) => f(...args, ...args2);

sum5 = (v, w, x, y, z) => v + w + x + y + z;
subtotal = partial(sum5, 1, 2, 3);

console.log(
  subtotal(4, 5) // 15
);

延续传球风格

你的代码模式_a = (x, b, c) => b(x, c)实际上是来自延续传递风格。它是高阶函数的一种特殊形式,其中一个函数的最后一个参数必须始终是另一个函数,该函数表示连续,即当前计算的其余部分。延续函数不是由其周围函数的参数提供的,而是由它的计算结果提供的。延续函数,或者更确切地说,它的应用是所谓的return语句的替换。

虽然你会在函数式Javascript中一直遇到HOFs,但延续传递风格是相当罕见的。当您查看以下示例时,您将知道原因:

代码语言:javascript
复制
const eqk = (x,y,k) => k(y === x);
const mulk = (x,y,k) => k(y * x);
const subk = (x,y,k) => k(y - x);

const powerk = (x, y, k) =>
  eqk(0, y, isDone =>
    isDone
      ? k(1)
      : subk(1, y, _y=>
        powerk(x, _y, res =>
          mulk(x, res, k))));

powerk(2, 8, x => {console.log("powerk:", x); return x});

控制反转

在函数式编程中,您可以通过应用纯(高阶)函数来实现控制反转。纯函数仅根据其输入产生一个值。没有副作用。调用这种纯函数的调用者可以将生成的值用于进一步处理,也可以将其丢弃。调用者决定所产生的值如何与程序交互。因此,控件从被调用者反转到调用者。

除此之外,调用者可以使用被调用者的参数将纯函数传递给被调用者。换句话说,调用者可以在被调用者中注入惰性表达式。因此,调用者不仅控制被调用者执行的计算的结果,而且还能够影响该计算本身。

依赖注入

在函数式编程中不需要特定的依赖注入,因为范型控制的内在反转。函数之间的全局依赖是完全没有问题的,只要所有涉及的函数都是纯函数,因此不会修改全局状态。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42179513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档