CS61A hw03 make_anoymous_factorial()

发布时间 2023-10-29 20:38:14作者: laniser

CS61A hw03

make_anoymous_factorial()

自问自答&写在前面

​ 写这些是因为这道练习没写出来,刚开始看到官方的solution也没看明白,通过从答案反推之后,有了一些对lambda表达式的一些理解,在此分享,观看之前还是希望经过自己思考之后再看,毕竟聪明的你都来学cs61a了,应该已经学会独立思考的能力,参照题目,带着理解来看。鄙人也只是计算机小白,可能表达的不是很明白,如果有理解偏差请多多包涵。

  1. 如何不借助函数名实现递归: 通过额外传入一个函数变量f,通过f来实现递归

    lambda f,n:1 if n==1 else mul(n,f(f,sub(n-1)))
    

    此时该lambda表达式也可以改写为:

    def λ(f,n):
        if n==1:
            return 1
        else :
            return mul(n,f(f,sub(n-1)))
    

    到这里产生了几个疑问:

    1. 什么是f函数
    2. 为什么f函数有两个参数

​ 先回答第一个: 我们通过f实现递归,f的功能应该和示例中给出的fact函数功能完全相同,所以f函数相当于一个改写的fact函数

​ 为什么有两个参数: 示例中fact函数就是lamda n:1 if n==1 else mul(n,fact(sub(n-1)))函数本身,递归就是通过调用函数函数本身定义的,所以f函数与lambda表达式的参数保持一致

​ 但到此时又产生了一个问题: 题目要通过调用make_anoymous_factorial()(n)得到答案,按照上述的写法要调用make_anoymous_factorial()(f,n)才能得到答案,并且这里产生了一个问题,既然我能传入一个全新的函数f,那我为什么不直接用fact函数

​ 所以我们就要消去参数f,那么如何消去呢: 柯里化!!

​ 只要通过以下最基础的方式就可以实现柯里化:

def λ1(f):
    def λ2(x):
        return f(f,x)
    return λ2

​ 通过这种方式就可以通过λ1(f)(x)来代替f(f,x)最后返回只需要通过返回λ1(f)即可得到最终答案

​ 在得到最终答案前我们要先对λ1函数进行lambda表达式的改写:

lambda f:lambda x:f(f,x) #改写后的λ1函数

​ 现在我们有了λ1函数lambda f:lambda x:f(f,x)和柯里化第一个参数f函数:lambda f,n:1 if n==1 else mul(n,f(f,sub(n-1)))

​ 只要将两个带入λ1(f)表达式即可得到答案:(lambda f: lambda k: f(f, k))(lambda f, k: k if k == 1 else mul(k, f(f, sub(k, 1))))

写在最后&一点碎碎念

应该没人会看吧,写了蛮多的相当于一篇小题解了,虽然没事高深的算法,以后的使用中也大概因为代码的可读性不会这么写递归函数,但不得不说对掌握lambda表达式大有脾益,只学到点皮毛真的很难做出来,可能也是因为我太菜了,如果有人能看到这里,并且产生了一定的帮助,我真的会很开心的,当然官方的solution中还有另一种解法,也可以自行尝试一下,当然这篇自问自答也只是写给自己的,可能有些地方没有那么详细,也请谅解