lambda 演算对返回值有何说明?
到目前为止,lambda 演算的一个众所周知的定理是,任何采用两个或多个参数的函数都可以通过柯里化编写为采用一个参数的一系列函数:事实证明,
# Pseudo-code for currying
f(x,y) -> f_curried(x)(y)
这不仅在研究函数的行为方面非常强大,而且在研究函数的行为方面也非常强大。在实际使用中(Haskell等)。
然而,返回值的函数似乎没有被讨论。程序员通常通过返回一些元对象(R 中的列表、C++ 中的结构等)来解决无法从函数返回多个值的问题。我一直觉得它有点杂乱,但却很有用。
例如:
# R code for "faking" multiple return values
uselessFunc <- function(dat) {
model1 <- lm( y ~ x , data=dat )
return( list( coef=coef(model1), form=formula(model1) ) )
}
问题
- lambda 演算对返回值的多重性有什么说法吗?如果是这样,会得出什么令人惊讶的结论吗?
- 同样,是否有任何语言允许真正的多个返回值?
It is by now a well known theorem of the lambda calculus that any function taking two or more arguments can be written through currying as a chain of functions taking one argument:
# Pseudo-code for currying
f(x,y) -> f_curried(x)(y)
This has proven to be extremely powerful not just in studying the behavior of functions but in practical use (Haskell, etc.).
Functions returning values, however, seem to not be discussed. Programmers typically deal with their inability to return more than one value from a function by returning some meta-object (lists in R, structures in C++, etc.). It has always struck me as a bit of a kludge, but a useful one.
For instance:
# R code for "faking" multiple return values
uselessFunc <- function(dat) {
model1 <- lm( y ~ x , data=dat )
return( list( coef=coef(model1), form=formula(model1) ) )
}
Questions
- Does the lambda calculus have anything to say about a multiplicity of return values? If so, do any surprising conclusions result?
- Similarly, do any languages allow true multiple return values?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据 lambda 演算的维基百科页面:
以及数学意义上的函数:
所以回答你的第一个问题不,lambda 演算(或任何其他基于数学函数的形式)不能有多个返回值。
对于你的第二个问题,据我所知,实现多个返回值的编程语言是通过将多个结果打包在某种数据结构(无论是元组、数组,甚至堆栈)中,然后稍后将其解包来实现的 -这就是差异所在,因为某些编程语言使打包/解包部分对程序员透明(例如Python在幕后使用元组),而其他语言则让程序员显式地完成工作,例如Java程序员可以模拟多个返回在一定程度上通过包装来体现价值返回的对象数组中的多个结果,然后手动提取并转换返回的结果。
According to the Wikipedia page on lambda calculus:
And a function, in the mathematical sense:
So answering your first question no, lambda calculus (or any other formalism based on mathematical functions) can not have multiple return values.
For your second question, as far as I know, programming languages that implement multiple return values do so by packing multiple results in some kind of data structure (be it a tuple, an array, or even the stack) and then unpacking it later - and that's where the differences lie, as some programming languages make the packing/unpacking part transparent for the programmer (for instance Python uses tuples under the hood) while other languages make the programmer do the job explicitly, for example Java programmers can simulate multiple return values to some extent by packing multiple results in a returned Object array and then extracting and casting the returned result by hand.
函数返回单个值。这就是数学中函数的定义方式。您可以通过将多个值打包为一个复合值来返回它们。但它仍然是单一值。我将其称为向量,因为它有组件。数学中有向量函数,编程语言中也有向量函数。唯一的区别是语言本身的支持程度以及是否有利于它。
A function returns a single value. This is how functions are defined in mathematics. You can return multiple values by packing them into one compound value. But then it is still a single value. I'd call it a vector, because it has components. There are vector functions in mathematics there, so there are also in programming languages. The only difference is the support level from the language itself and does it facilitate it or not.
没有什么可以阻止您拥有多个函数,每个函数都返回您想要返回的多个结果之一。
例如,假设您在 python 中有以下函数返回一个列表。
对于
x=3
,它返回[0, 3, 6]
;对于,它返回
。相反,你完全可以拥有[0, 5, 10, 15, 20]
x=5然后你可以请求给定输入的任何输出,并获取它,或者如果没有足够的输出,则获取
None
:如果你有,计算资源可能会被浪费做一些相同的工作,就像在本例中一样。理论上,可以通过返回另一个将所有结果保存在其内部的函数来避免这种情况。
所以现在我们
传统的无类型 lambda 演算完全能够表达这个想法。 (毕竟,它是图灵完备的。)每当您想要返回一堆值时,只需返回一个可以为任何
n
提供第 n-th 值的函数即可。关于第二个问题,Python允许这样的语法,如果你确切地知道函数将返回多少个值。
最后,这是 Lisp 教程 中的一个示例:
Nothing prevents you from having multiple functions, each one returning one of the multiple results that you would like to return.
For example, say, you had the following function in python returning a list.
It returns
[0, 3, 6]
forx=3
and[0, 5, 10, 15, 20]
forx=5
. Instead, you can totally haveThen you can request any of the outputs for a given input, and get it, or get
None
, if there aren't enough outputs:Computational resources may be wasted if you have to do some of the same work, as in this case. Theoretically, it can be avoided by returning another function that holds all the results inside itself.
So now we have
Traditional untyped lambda calculus is perfectly capable of expressing this idea. (After all, it is Turing complete.) Whenever you want to return a bunch of values, just return a function that can give the
n-th
value for anyn
.In regard to the second question, python allows for such a syntax, if you know exactly, just how many values the function is going to return.
Lastly, here is an example from this Lisp tutorial:
我写这篇文章是对已接受答案的迟到回应,因为它是错误的!
Lambda 演算确实有多个返回值,但需要花点时间才能理解返回多个值的含义。
Lambda 演算没有对事物集合的固有定义,但它确实允许您使用乘积和教堂数字来发明它。
本示例将使用纯函数式 JavaScript。
让我们定义一个产品如下:
然后我们可以定义church_0和church_1又名true,false,又名左,右,又名汽车,cdr,又名第一个,其余如下:
让我们开始创建一个返回两个值的函数,20,和“你好”。
正如预期的那样,我们得到了 20 和“Hello”。
要返回 2 个以上的值,就有点棘手:
如您所见,函数可以返回任意数量的返回值,但要访问这些值,不能简单地使用 result()[0]、result() [1],或 result()[2],但您必须使用过滤出您想要的位置的函数。
这与电路非常相似,因为电路没有“0”、“1”、“2”、“3”,但它们确实有做出决定的方法,并通过用字节(反向列表)抽象出我们的电路 0, 0, 0, 0] 相当于:
8 个输入),单词(16 个输入的反向列表),在这种语言中,0 作为一个字节将是 [0, 0, 0, 0 , 数字,我们可以制定一个算法,给定一个字节索引数组,以及一个表示我们想要从此数组中索引的字节,它将处理样板文件。
无论如何,我们所说的数组无非是以下内容,以更高的级别表达以表明要点:
除了它不执行 2^32 - 1 if 语句之外,它只执行 8 条并递归地缩小你想要的特定元素的范围。本质上,它的作用与多路复用器完全相同(除了“单个”信号实际上是唯一寻址元素所需的固定数量的位(余积,选择))。
我的观点是,数组、映射、关联数组、列表、位、字节、字都是基本函数,无论是在电路级别(我们可以只用电线和开关来表示复杂的宇宙),还是在数学级别(其中一切最终是乘积(序列,不需要嵌套就难以管理,例如列表),余积(类型,集合)和指数(自由函子(lambda),健忘函子))。
I write this as a late response to the accepted answer since it is wrong!
Lambda Calculus does have multiple return values, but it takes a bit to understand what returning multiple values mean.
Lambda Calculus has no inherent definition of a collection of stuff, but it does allow you to invent it using products and church numerals.
pure functional JavaScript will be used for this example.
let's define a product as follows:
then we can define church_0, and church_1 aka true, false, aka left, right, aka car, cdr, aka first, rest as follows:
let's start with making a function that returns two values, 20, and "Hello".
As expected, we got 20 and "Hello".
To return more than 2 values, it gets a bit tricky:
As you can see, a function can return an arbitrary number of return values, but to access these values, a you cannot simply use result()[0], result()[1], or result()[2], but you must use functions that filter out the position you want.
This is mindblowingly similar to electrical circuits, in that circuits have no "0", "1", "2", "3", but they do have means to make decisions, and by abstracting away our circuitry with byte(reverse list of 8 inputs), word(reverse list of 16 inputs), in this language, 0 as a byte would be [0, 0, 0, 0, 0, 0, 0, 0] which is equivalent to:
After inventing a number, we can make an algorithm to, given a byte-indexed array, and a byte representing index we want from this array, it will take care of the boilerplate.
Anyway, what we call arrays is nothing more than the following, expressed in higher level to show the point:
except it doesnt do 2^32 - 1 if statements, it only does 8 and recursively narrows down the specific element you want. Essentially it acts exactly like a multiplexor(except the "single" signal is actually a fixed number of bits(coproducts, choices) needed to uniquely address elements).
My point is that is Arrays, Maps, Associative Arrays, Lists, Bits, Bytes, Words, are all fundamentally functions, both at circuit level(where we can represent complex universes with nothing but wires and switches), and mathematical level(where everything is ultimately products(sequences, difficult to manage without requiring nesting, eg lists), coproducts(types, sets), and exponentials(free functors(lambdas), forgetful functors)).