Python:使用cons,car和cdr进行函数式编程 输出: cons::(a, b) -> (((a, b) -> c) -> c) cons car

如何解决Python:使用cons,car和cdr进行函数式编程 输出: cons::(a, b) -> (((a, b) -> c) -> c) cons car

有这样的问题:

cons(a,b)构造一对,car(pair)cdr(pair)返回 该对的第一个和最后一个元素。例如,car(cons(3,4)) 返回3,而cdr(cons(3,4))返回4

现在,我已经看到了解决方案,但是我想知道是否有人可以解释如何思考以达到解决方案?

  1. cdr(cons(3,4)):这两个函数的评估顺序是什么?我通常会认为首先对cons(3,4)求值,但是在这种情况下这没有意义,因为cons(3,4)返回的函数将参数3和4进行了“集成”,因此没有任何方法排除争论。
  2. 在我看来car(f)返回一个函数,那么cons(3,4)如何返回3编辑:错字应为car(cons(3,4)),而不是cons(3,4)
  3. 我显然想解决此问题,因为我想学习Python,但是您会建议我跳过这些问题吗?我很想阅读这里的内容:Why program functionally in Python?

解决方案:

def cons(a,b):
    def pair(f):
        return f(a,b)
    return pair

def car(f):
    def pair(a,b):
        return a
    return f(pair)

def cdr(f):
    def pair(a,b):
        return b
    return f(pair)

print(car(cons(3,4)))
Output: 3
print(cdr(cons(3,4)))
Output: 4

解决方法

a(b())中,b将始终被首先评估。我不知道Python中有一个例外。 a必须是一个宏,相反的情况才能成立。

请注意cdrcar的参数名称是:f,如“函数”中所示。每个函数都接受一个函数作为参数。不过,这是可行的,因为您注意到cons返回了一个函数。

car(cons(3,4))中,cons返回一个函数(本地称为pair)。然后将该功能提供给carcar在这里使用它:f(pair)。在这种情况下,f是传入的函数。此处的复杂部分是f是接受另一个函数并使用两个参数调用它的函数。这两个参数是最初提供给cons的数据:34


cons(3,4)不会返回3,而car(cons(3,4))会返回cons(3,4)car返回一个函数,该函数对提供给它的数据起作用。在这种情况下,pair的{​​{1}}函数最终会丢弃第二个传递的参数(4),而是返回第一个传递的参数(3)。


是的,暂时远离这样的代码一段时间。传递函数非常有用,但是此代码更像是一种实验玩具。这是一种显示样式的理论代码(基于术语,源自诸如Scheme之类的Lisp)。有很多简单的方法可以达到相同的最终结果。

实践Higher Order Functions的简单示例(例如mapreduce),使他们精通它们,然后重新阅读此代码。仍然很难理解(因为该代码本身不易于理解),但是更有意义。

,

您显示的问题也可以通过这种方式解决。

def cons(a,b):
    return (a,b)

def car(pair):
    return pair[0]

def cdr(pair):
    return pair[1]

这是您将如何使用它:

lst = cons(1,cons(2,3))

# Get the first element of lst
print(car(lst))

# Get the second element of lst
print(car(cdr(lst)))

# Get the last element of lst
print(cdr(cdr(lst)))

输出:

1
2
3

我仅显示此内容,以便您可以看到解决该问题的方法不止一种,而发现的方法很少在python中完成。任何想在python中解决此问题的人都将有99%的时间按照我在此处所示的方法进行操作。

现在解决您的问题。


def cons(a,b):
    def pair(f):
        return f(a,b)
    return pair

def car(f):
    def pair(a,b):
        return a
    return f(pair)

def cdr(f):
    def pair(a,b):
        return b
    return f(pair)

首先,我们使用一些haskell函数符号来讨论这些函数,以便您可以看到这些函数的完整类型:

cons::(a,b) -> (((a,b) -> c) -> c)

cons是一个带有两个参数ab的函数,然后它返回一个函数f,该函数带有另一个在给定参数({{ 1}},a)返回b,其中c可以是ca或其他。 b然后返回f的值。

好吃!

另一种思考方式是c返回的函数f((a,b) -> c) -> c)用于将consa转发给任何运算符(或映射功能)要作用于b上。该运算符返回consc然后简单返回此映射函数返回的值,恰好是f

暂时不要担心c是什么。只需考虑一下将函数应用于c的结果即可。

cons

car::(((a,b) -> a) -> a) -> a定义了从car(a,b)的可能映射,并使用此映射返回调用c的值。

f使用函数car,该函数想要从输入f到某些输出(a,b)的映射。在这种情况下,c将映射定义为car,这意味着传递给(a,b) -> a的任何函数f都将返回car的第一个参数,即仅(a,b)。这就是a将返回的内容。

car

类似于cdr::(((a,b) -> b) -> b) -> b,但由car定义的映射返回cdr而不是b


注意acdr的输入与car返回的函数(f)有多相似?这就是为什么我只是将他们的输入称为cons


现在回答您的一些问题:

f:这两个函数按什么顺序求值?我通常会认为首先对cdr(cons(3,4))求值,但是在这种情况下这没有意义,因为cons(3,4)返回的函数将参数3和4进行了“集成”,因此没有任何方法排除参数。

根据我上面的解释,从cons(3,4)返回的函数与cons期望的函数类型完全相同。现在,cdr所要做的就是提供到cdr的映射函数,并返回f返回的内容。

在我看来f返回一个函数,那么car(f)如何返回cons(3,4)编辑:错别字应为3,而不是car(cons(3,4))

cons(3,4)不一定返回一个函数。请参阅上面的类型签名。它只返回car(f)返回的值,如果恰好是一个函数,则它将返回一个函数。

通常,f返回car的第一个元素。在这种情况下,由于cons返回一个函数(cons(3,4))并将此函数传递给f,因此car将为该函数提供另一个选择第一个函数的函数。它是参数,在这种情况下为car。现在,此33的结果。

我希望一切都可以清除。

,

您粘贴的代码应按以下方式使用:

首先,您定义您的对:

f = cons(3,4)

然后,您定义一个可成对使用的函数:

add = lambda x,y: x + y

现在,您可以像这样使用“对”:

f(add)

输出:

7

因此,它的作用是:将对转换为一个函数,该函数可以对以定义的对作为参数的对“执行”函数。 carcds实际上可以“转换”成对函数并返回一个元素。

编辑:

如果您对lambda表达式不熟悉,请参阅this tutorial

现在,您也可以选择

def add(x,y):
    return x + y

并以相同的方式使用它。 :)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res