📜  函数式编程-按值调用(1)

📅  最后修改于: 2023-12-03 15:07:08.879000             🧑  作者: Mango

函数式编程-按值调用

函数式编程是一种对程序员友好的编程范式,它将计算过程视为数学函数的组合,避免了副作用和可变状态,使得程序更容易理解、调试和测试。函数式编程主要有两种调用方式,一种是按值调用,另一种是按名调用。

按值调用

按值调用是一种在函数调用时传递参数的方式,它将参数的值复制给函数的形参,这样函数内部就可以独立地操作这些值,而不会影响到函数外部的状态。例如下面这段代码:

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

a = 1
b = 2
c = add(a, b)
print(c)

在这个例子中,我们定义了一个加法函数add(x, y),它的形参x和y分别接收a和b的值,然后将它们相加并返回结果。最后我们将c赋值为调用add(a, b)的结果,也就是3,然后打印出来。在这个过程中,a和b的值没有改变,函数只是按照我们给定的值计算结果并返回,这就是按值调用的特点。

按值调用的优点是可以避免副作用和可变状态,让程序更容易理解,因为函数只是针对输入值进行计算,不会修改外部的状态。缺点是如果传入的参数比较大,就会消耗更多的内存,因为要复制参数的值。

按名调用

按名调用是一种在函数调用时传递参数的方式,它将参数的表达式传递给函数的形参,然后在函数内部对表达式进行求值。这样可以避免多余的复制和重复计算,但也会引入副作用和可变状态。例如下面这段代码:

def square(x):
    print("computing square of", x)
    return x * x

def sum_squares(x, y):
    return square(x) + square(y)

a = 1
b = 2
c = sum_squares(a, b)
print(c)

在这个例子中,我们定义了一个平方函数square(x),它会打印一条信息表示正在计算x的平方,然后返回x的平方值。我们还定义了一个求和函数sum_squares(x, y),它会调用square(x)和square(y),然后将它们的值相加并返回结果。最后我们将c赋值为调用sum_squares(a, b)的结果,也就是5,然后打印出来。在这个过程中,我们只计算了a和b的平方,没有浪费计算资源,这就是按名调用的优点。

按名调用的缺点是会引入副作用和可变状态,因为表达式可能会多次求值,而且表达式的值有可能会改变。例如下面这个例子:

def f(x):
    print("x =", x)
    x = x + 1
    print("x =", x)
    return x

y = 1
z = f(y) + f(y)
print("z =", z)

在这个例子中,我们定义了一个函数f(x),它会打印一条信息表示x的值,然后将x加1并返回结果。我们还定义了两个变量y和z,它们分别赋值为1和f(y)+f(y)的结果。在计算z的过程中,f(y)被调用了两次,所以x的值也被打印了两次,输出结果如下:

x = 1
x = 2
x = 1
x = 2
z = 5

可以看到,f(y)被调用两次,但是x的值被修改了两次,这就是按名调用引入的可变状态。为了避免这种问题,我们可以使用按值调用,或者使用纯函数式编程的方式,即将函数设计得没有副作用,也不依赖可变状态。