一般来说,在编程语言中,我们都会听到 函数 或 过程 的概念。然而,我刚刚发现我几乎将这些术语互换使用(可能是非常错误的)。
那么我的问题是:
就它们的功能、目的和用法而言,它们有什么区别?请举个例子。
如果能提供一个例子就更好了。
一般来说,在编程语言中,我们都会听到 函数 或 过程 的概念。然而,我刚刚发现我几乎将这些术语互换使用(可能是非常错误的)。
那么我的问题是:
就它们的功能、目的和用法而言,它们有什么区别?请举个例子。
如果能提供一个例子就更好了。
一个函数会返回一个值,而一个过程则只是执行一系列命令。
函数这个名字来源于数学。它用于根据输入计算一个值。
过程是一组按顺序执行的命令。
在大多数编程语言中,即使是函数也可以有一组命令。因此,区别只在于是否返回值。
但是如果你想保持函数的简洁性(只看看函数式语言),那么你需要确保函数没有副作用。
plusOne(2, i)
而不是int i = plusOne(2);
)。 - Vegaaaa这取决于上下文。
在类Pascal语言中,函数和过程是不同的实体,它们之间的区别在于它们是否返回值。它们在语言语法方面有所不同(例如,过程调用形成语句;您无法在表达式内部使用过程调用,而函数调用不形成语句,您必须在其他语句中使用它们)。因此,受Pascal影响的程序员会对它们进行区分。
在类C语言和许多其他现代语言中,这种区别已经消失了;在静态类型的语言中,过程只是带有奇怪返回类型的函数。这可能就是为什么它们可以互换使用。
在函数式编程语言中,通常没有过程这样的概念-一切都是函数。
C语言示例:
// function
int square( int n ) {
return n * n;
}
// procedure
void display( int n ) {
printf( "The value is %d", n );
}
虽然您应该注意到,C标准只涉及函数而不是过程。
一般来说,一个过程是一系列指令的序列。
一个函数可以相同,但通常会返回一个结果。
有一个术语叫做子程序(subroutine)或子程序(subprogram),它指的是一段参数化的代码块,可以从不同的地方调用。
函数和过程是这些的实现。通常情况下,函数会返回值,而过程则不会返回任何内容。
这是一个众所周知的老问题,但我想分享一些关于现代编程语言研究和设计的更多见解。
传统上(在结构化编程的意义上)和非正式地说,一个过程是一种可重用的结构性构造,用于“输入”并执行可编程操作。当需要在过程内完成某些操作时,您可以在源代码中提供(实际)参数以在过程调用中调用该过程(通常在某种表达式中),并将参数替换为在定义过程时使用的(形式)参数,然后执行过程体中编码的操作。
函数不仅是过程,因为还可以在体中指定返回值作为“输出”。函数调用与过程调用几乎相同,除了您还可以使用函数调用的结果,在语法上(通常作为其他某个表达式的子表达式)。
传统上,过程调用(而不是函数调用)用于表示不需要关注输出,并且必须有副作用以避免调用成为无操作,从而强调了命令式编程范式。许多传统的编程语言如Pascal提供了“过程”和“函数”来区分这种意图上的风格差异。
(需要明确的是,上述“输入”和“输出”是基于函数的语法属性的简化概念。许多语言还支持通过引用/共享将参数传递给参数,以允许用户在调用期间传输编码在参数中的信息。这样的参数甚至可以被称为“输入/输出参数”。此功能基于传递调用中传递的对象的性质,这与过程/函数的特性是正交的。)
然而,如果函数调用的结果不需要,它可以被(至少在逻辑上)忽略,函数定义/函数调用应该与过程定义/过程调用保持一致。像C、C++和Java这样的ALGOL类语言都以这种方式提供“函数”功能:通过将结果类型void
编码为传统过程的特殊情况,无需单独提供“过程”功能,从而避免了语言设计中的一些膨胀。
由于提到了SICP,值得注意的是,在RnRS指定的Scheme语言中,一个过程可能需要或不需要返回计算结果。这是传统“函数”(返回结果)和“过程”(不返回任何内容)的结合体,本质上与许多ALGOL类语言的“函数”概念相同(实际上还共享更多的保证,如在调用之前对操作数进行应用评估)。然而,即使在像SRFI-96这样的规范文档中,仍然存在着老式的差异。
我对于语言设计师不再使用规范臃肿的具体原因并不了解,但是根据我的经验来看,似乎“procedure”作为一个独立的特点已经变得不必要了。像 void
类型这样标记应该强调副作用的用法已经足够。对于那些有 C 语言经验的用户来说,这也更加自然,因为 C 语言等类似语言流行了几十年。此外,它也避免了在类似 RnRS 的情况下出现“procedures”实际上是以更广义的意义上的“functions”的尴尬情况。
理论上,可以使用指定的 unit type 作为函数调用结果的类型来指示结果很特殊,从而指定函数。这将传统过程(其中调用结果不感兴趣)与其他过程区分开来。在语言设计上有不同的风格:
#inert
)也可以起到作用。void
类型正是这种技术的一个例子。ISO C11的_Noreturn
也是其中更微妙的一个。由于传统概念源自数学,有大量黑魔法大多数人不会费心去了解。严格来说,你不太可能像数学书籍那样完全清楚地理解所有事情。计算机科学书籍可能也提供不了太多帮助。
关于编程语言,有几个需要注意的地方:
{{{
, {}}
...)}}除了某些有限的上下文之外。SELECT
和DML(INSERT
、UPDATE
、DELETE
)语句,而函数只允许使用SELECT
语句。SELECT
语句中使用存储过程,但可以在SELECT
语句中嵌入函数。WHERE
(或HAVING
或SELECT
)块中的SQL语句中使用,但函数可以。JOIN
块中与其他表一起使用。JOIN
块和其他行集操作中使用。f(x)=(1+x)
g(x)=.5*(2+x/2)
(define (sqrt x) (newtons-method (lambda (y) (- (square y) x)) 1.0))
。 - mk12