在函数式编程中,是否有一种干净的方法可以对某些数据执行许多操作,而无需将数据显式传递到每个函数中?(代码片段)

author author     2022-12-28     292

关键词:

假设我有一些函数可以对某些数据执行业务逻辑:

function addEmployees(data, numberOfNewEmployees)
    // Business logic...
    data.employeeCount += numberOfNewEmployees;
    return data;


function withdrawFunds(data, withdrawAmount)
    // Business logic...
    data.checkingAccount -= withdrawAmount;
    return data;


function completeAnOrder(data)
    // Business logic...
    data.pendingOrders -- 1;
    return data;

现在,要对某些数据执行几个操作,我有类似的东西(让我们假设数据是通过复制传递的):

const data = 
    employeeCount: 5,
    checkingAccount: 5000,
    pendingOrders: 2


let newData = addEmployees(data, 2);
newData = withdrawFunds(newData, 2000);
newData = completeAnOrder(newData);

我很好奇是否在函数式编程世界中有一种优雅的方法可以实现更接近这一点的方法:

const data = 
    employeeCount: 5,
    checkingAccount: 5000,
    pendingOrders: 2


let biz = createBiz(data);

const newData = biz.addEmployees(2)
    .withdrawFunds(2000)
    .completeAnOrder()
    .toValue();

在JavaScript中我知道一个对象可以返回this,这就是JQuery方法链接的工作原理。

但在功能世界中有一种优雅的方法可以做类似的事情吗?我意识到我可能会试图将OOP的想法强加到FP中。

Monad是否解决了这个问题?为特定的业务逻辑创建自己的自定义Monads是否有意义?

答案

这在很大程度上取决于语言和语言提供的工具。

Clojure,这是homoiconic,这样的任务通常使用宏来解决。在这种情况下,这将使用“线程”宏来完成。

说我有你的功能:

;  All of these functions return the modified data
(defn add-employees [data number-of-new-employees]
  ...)

(defn withdraw-funds [data withdraw-amount]
  ...)

(defn complete-an-order [data]
  ...)

由于“this”(data)是第一个参数,我可以使用->自动“线程化”每个调用的参数:

(def data :employee-count 5,
           :checking-account 5000,
           :pending-orders 2)

(-> data
  (add-employees 2) ; The result of this gets passed as the first argument to withdraw-funds
  (withdraw-funds 2000) ; Then the result of this gets passed to complete-an-order...
  (complete-an-order) ; Same as above
  (to-value))

在宏扩展之后,这基本上变成了:

(to-value (complete-an-order (withdraw-funds (add-employees data 2) 2000)))

但是使用->将来更容易阅读和更容易。

另一答案

你会使用作文。在Haskell中,如果操作是在结构上运行并返回新结构的纯函数,而不是I / O操作,那么您可以用几种不同的方式编写,例如:toValue . completeOrder . withdrawFunds 2000 . addEmployees 2 $ data。 (你也可以用&从左到右书写。)

但是,你更有可能看到这个例子变成了有关外部数据库副作用的有状态代码。在Haskell中,这将使用应用程序或monad的抽象,但大多数其他函数式语言不会成为数学形式主义的粘合剂。应用版本可以让你写像runValue $ completeOrder <$> withdrawFunds 2000 <$> addEmployees 2 <$> data。或者你可以把它写成do块。

Facebook为some real-world examples提供了如何为其部分数据库代码执行此操作。命令式代码:

NumCommonFriends(x, y) = Length(Intersect(FriendsOf(x), FriendsOf(y)))

有适用版本

numCommonFriends x y =
  length <$> (intersect <$> friendsOf x <*> friendsOf y)

这可以写成一些语法糖作为

numCommonFriends x y = do
  fx <- friendsOf x
  fy <- friendsOf y
  return (length (intersect fx fy))

如何编码 Haskell/函数式编程中的选择公理?

】如何编码Haskell/函数式编程中的选择公理?【英文标题】:HowtoencodetheaxiomofchoiceinHaskell/Functionalprogramming?【发布时间】:2016-03-1020:39:56【问题描述】:>-#LANGUAGERankNTypes#-我想知道是否有一种方法可以在haskell和/或其他一些函数... 查看详情

scala函数式编程函数式的错误处理(代码片段)

前情提要Scala函数式编程指南(一)函数式思想介绍scala函数式编程(二)scala基础语法介绍Scala函数式编程(三)scala集合和函数Scala函数式编程(四)函数式的数据结构上Scala函数式编程(四)函数式的数据结构下1.面向对象的... 查看详情

函数式语言

    函数式语言(functionallanguage)一类程序设计语言,是一种非冯·诺伊曼式的程序设计语言。函数式语言主要成分是原始函数、定义函数和函数型。    这种语言具有较强的组织数据结构的能力,可以把某一数据结... 查看详情

javascript进阶笔记

js是一门函数式语言,因为js的强大威力依赖于是否将其作为函数式语言进行使用。在js中,我们通常要大量使用函数式编程风格。函数式编程专注于:少而精、通常无副作用、将函数作为程序代码的基础构件块。在函数式编程中... 查看详情

是否有一种 FastAPI 方法可以在全球范围内访问当前的请求数据?

...架内:虽然请求数据当然可以作为参数传递,但我想知道函数是否可以在不传递参数的情况下访问有关当前请求的信息。免责声明:我不认为全局访问请求数据是一种好的做法,但我有一个用例, 查看详情

是否有一种简单的方法可以在此 Access 数据库架构中填充下拉列表?

】是否有一种简单的方法可以在此Access数据库架构中填充下拉列表?【英文标题】:IsthereasimplewayofpopulatingdropdowninthisAccessDatabaseschema?【发布时间】:2010-10-2923:03:33【问题描述】:我有3个表格,如下所示:LocationNodeSektor-------------... 查看详情

函数式编程语言

  函数式编程语言(functionalprogramlanguage)是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambdacalculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)... 查看详情

在 QBVideoChat 中暴露 AVAudioSession

...oninQBVideoChat【发布时间】:2014-01-2921:28:01【问题描述】:是否有计划在QBVideoChat中公开现有的AVAudioSession?我意识到有一种方法可以创建自己的并将单个帧移交给QBVideoChat,但在某些情况下,对现有会话进行操作会更干净,而不必... 查看详情

是否有一种优雅的方法可以在 SQL 插入语句中反转位值?

】是否有一种优雅的方法可以在SQL插入语句中反转位值?【英文标题】:IsthereanelegantwaytoInvertaBitvalueinanSQLinsertStatement?【发布时间】:2011-03-2011:32:15【问题描述】:我正在SQLServer中转换一些数据:INSERTINTOMYTABLE(AllowEdit)(SelectPreventE... 查看详情

如何在现实世界中使用函数式编程? [关闭]

】如何在现实世界中使用函数式编程?[关闭]【英文标题】:HowcanIusefunctionalprogrammingintherealworld?[closed]【发布时间】:2010-09-1315:57:23【问题描述】:函数式语言很好,因为它们通过消除状态来避免错误,还因为它们可以轻松地为... 查看详情

stream流式编程详解

...对象(源集合)Stream接口中几乎所有方法的参数都是四大函数式接口接口类型的参数。而函数式接口可以使用lambda表达式来简化开发,并且Stream接口中的方法基本都是返回对象本身(返回对象本身的方法可以使用链式编程)。所... 查看详情

函数式编程之-f#类型系统(代码片段)

在深入到函数式编程思想之前,了解函数式独有的类型是非常有必要的。函数式类型跟OO语言中的数据结构截然不同,这也导致使用函数式编程语言来解决问题的思路跟OO的思路有明显的区别。什么是类型?类型在编程语言中有... 查看详情

函数式编程语言

函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambdacalculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 和指令式编程相比,函数式编程... 查看详情

什么是函数式编程(代码片段)

主要参考的是《Java函数式编程》高清华译版本定义函数式编程其实就是编写非故意副作用的程序。课外知识——什么是函数函数简单的说就是从A(定义域)到B(值域)的一个映射过程。当然具体的函数还有各种限制,具体见链接。... 查看详情

java8函数式编程(代码片段)

Lambda表达式函数式接口方法引用与构造器引用StreamAPI接口中的默认方法与静态方法新时间日期API其他新特性速度更快代码更少(增加了新的语法Lambda表达式)强大的StreamAPI便于并行最大化减少空指针异常Optional其中最为核... 查看详情

是否有任何算法可以在某些模式中对数组进行分类?

...BCAAA、...。每个模式与输入数组的长度相同。我需要一个函数,它将任何 查看详情

在连接共享某些列名的两个表时,是不是有一种动态方法可以为一个表的所有列名添加前缀?

...tableswhosharesomecolumnnames?在连接共享某些列名的两个表时,是否有一种动态方法可以为一个表的所有列名添加前缀?【发布时间】:2020-11-1000:47:02【问题描述】 查看详情

函数式编程思维学习

1. 语言的演进   函数式编程与面向对象编程对于代码的重用方式是不同的,面向对象喜欢创建有很多操作的各种数据结构,函数式变成的数据结构却很少。  函数式编程重用表现在函数的通用性上,面向对... 查看详情