238

一般来说,我们都听说过编程语言中的函数过程。但是,我刚刚发现我几乎可以互换使用这些术语(这可能是非常错误的)。

所以,我的问题是:

它们的功能、用途和用途有什么区别?

一个例子将不胜感激。

4

18 回答 18

339

一个函数返回一个值,一个过程只执行命令。

名称函数来自数学。它用于根据输入计算值。

过程是一组可以按顺序执行的命令。

在大多数编程语言中,甚至函数也可以有一组命令。因此,区别只是返回一个值。

但是如果你想保持函数干净,(看看函数式语言),你需要确保函数没有副作用。

于 2009-04-06T11:52:03.427 回答
48

这取决于上下文。

在类 Pascal 语言中,函数和过程是不同的实体,不同之处在于它们是否返回值。他们的行为不同。语言语法(例如,过程调用形成语句;您不能在表达式中使用过程调用,而函数调用不形成语句,您必须在其他语句中使用它们)。因此,Pascal 培养的程序员将它们区分开来。

在类 C 语言和许多其他当代语言中,这种区别已经消失了。在静态类型语言中,过程只是具有有趣返回类型的函数。这可能就是为什么它们可以互换使用的原因。

在函数式语言中,通常没有过程之类的东西——一切都是函数。

于 2009-04-06T12:00:10.757 回答
23

C中的示例:

// function
int square( int n ) {
   return n * n;
}

// procedure
void display( int n ) {
   printf( "The value is %d", n );
}

尽管您应该注意 C 标准不讨论过程,只讨论函数。

于 2009-04-06T11:57:01.467 回答
13

一般来说,一个过程是一个指令序列。
一个函数可以相同,但它通常返回一个结果。

于 2009-04-06T11:51:43.570 回答
11

有一个术语子程序子程序,它代表可以从不同位置调用的参数化代码段。

函数和过程是它们的实现。通常函数返回值和过程不返回任何东西。

于 2009-04-06T11:53:03.707 回答
10

基本差异

  • 函数必须返回一个值,但在存储过程中它是可选的:一个过程可以返回 0 或n 个值。
  • 函数只能有输入参数,而过程可以有输入/输出参数。
  • 对于一个函数,它必须接受一个输入参数,但一个存储过程可能需要 0 到n 个输入参数。
  • 可以从过程调用函数,而不能从函数调用过程。

高级差异

  • 异常可以通过过程中的 try-catch 块来处理,而 try-catch 块不能在函数中使用。
  • 我们可以在过程中进行事务管理,而在函数中我们不能。

在 SQL 中:

  • 过程允许其中SELECT包含 DML ( INSERT, UPDATE, DELETE) 语句,而函数仅允许其中包含SELECT语句。
  • 过程不能在SELECT语句中使用,而函数可以嵌入在SELECT语句中。
  • 存储过程不能用于WHERE(或 aHAVING或 a SELECT)块中的任何位置的 SQL 语句中,而函数可以。
  • 返回表的函数可以被视为另一个 Rowset。这可以在JOIN与其他表的块中使用。
  • 内联函数可以被认为是接受参数的视图,可以在JOIN块和其他行集操作中使用。
于 2013-12-18T09:27:46.947 回答
7

这是一个众所周知的老问题,但我想分享一些关于现代编程语言研究和设计的更多见解。

基本答案

传统上(在结构化编程的意义上)和非正式地,过程是一种可重用的结构构造,具有“输入”并执行可编程操作。当需要在过程中完成某些事情时,您可以在源代码中编码的过程调用(通常以一种表达式)中为过程提供(实际)参数,以及在过程主体中编码的动作(提供在过程的定义中)将通过将参数替换为主体中使用的(正式)参数来执行。

函数不仅仅是一个过程,因为返回也可以指定为主体中的“输出”。函数调用或多或少与过程调用相同,只是您还可以在语法上使用函数调用的结果(通常作为某个其他表达式的子表达式)。

传统上,过程调用(而不是函数调用)用于表示必须对输出不感兴趣,并且必须有副作用以避免调用是无操作的,因此强调了命令式编程范式。许多像 Pascal 这样的传统编程语言都提供了“过程”和“函数”来区分这种有意的风格差异。

(需要明确的是,上面提到的“输入”和“输出”是基于函数句法属性的简化概念。许多语言还支持通过引用/共享将参数传递给参数,以允许用户在调用期间传输编码在参数中的信息. 这样的参数甚至可以被称为“输入/输出参数”。这个特性是基于在调用中传递的对象的性质,它与过程/函数的特性的特性正交。)

但是,如果不需要函数调用的结果,则可以(至少在逻辑上)忽略它,并且函数定义/函数调用应该以这种方式与过程定义/过程调用保持一致。类似 ALGOL 的语言,如 C、C++ 和 Java,都以这种方式提供“函数”的特性:通过将结果类型编码void为看起来像传统过程的函数的特例,不需要提供“过程”的特性“ 分别地。这可以防止语言设计中的一些膨胀。

由于提到了 SICP,还值得注意的是,在R n RS指定的 Scheme 语言中,过程可能必须或可能不必返回计算结果。这是传统“函数”(返回结果)和“过程”(不返回任何内容)的结合,与许多类似 ALGOL 的语言的“函数”概念基本相同(实际上共享更多保证,例如对调用前的操作数)。然而,即使在像SRFI-96这样的规范性文件中,仍然存在老式差异。

我不太了解这种分歧背后的确切原因,但正如我所经历的那样,现在没有规范膨胀的语言设计者似乎会更快乐。也就是说,作为独立功能的“程序”是不必要的。像void类型这样的技术已经足以标记应该强调副作用的使用。这对于有类似 C 语言经验的用户来说也更自然,这些语言已经流行了几十年。此外,它避免了在 R n RS 这样的情况下的尴尬,其中“程序”实际上是更广泛意义上的“功能”。

理论上,一个函数可以指定一个指定的单元类型作为函数调用结果的类型,表示结果是特殊的。这将传统过程(调用结果不感兴趣)与其他过程区分开来。语言设计有不同的风格:

  • 与 R n RS 中一样,只需将不感兴趣的结果标记为“未指定”值(如果语言必须提及,则为未指定类型)并且足以被忽略。
  • 将不感兴趣的结果指定为专用单元类型(例如Kernel 's #inert)的值也可以。
  • 当该类型进一步是底部类型时,它可以(希望)静态验证并防止用作表达式类型。类 ALGOL 语言中的void类型正是这种技术的一个例子。ISO C11_Noreturn与此类类似,但更微妙。

进一步阅读

作为源自数学的传统概念,有很多大多数人都懒得知道的黑魔法。严格地说,你不可能按照你的数学书把所有的事情都弄清楚。CS书籍也可能不会提供太多帮助。

关于编程语言,有几个注意事项:

  • 不同数学分支中的函数并不总是被定义为具有相同的含义。不同编程范式中的函数也可能完全不同(甚至有时函数调用的语法看起来很相似)。有时导致差异的原因是相同的,但有时却不是。
    • 通过数学函数对计算进行建模,然后用编程语言实现底层计算是惯用的。请小心避免将它们一一对应,除非您知道所谈论的内容。
  • 不要将模型与要建模的实体混淆。
  • 在数学上,函数可以是部分的或全部的。不同的编程语言在这里有不同的处理。
    • 一些函数式语言可能会尊重函数的整体,以保证函数调用中的计算总是以有限的步骤终止。然而,这本质上不是图灵完备的,因此计算表达能力较弱,并且除了类型检查的语义(预计是全部的)之外,在通用语言中并不多见。
    • 如果程序和功能之间的差异很大,是否应该有“总程序”?唔...
  • 类似于 calculi 中用于对一般计算编程语言的语义建模的函数的构造(例如 lambda calculi 中的 lambda 抽象可以对操作数具有不同的评估策略
    • 在传统的纯微积分的简化以及纯函数式语言中表达式的评估中,没有改变计算结果的副作用。因此,不需要在类函数构造体之前评估操作数(因为定义“相同结果”的不变量由Church-Rosser 属性保证的β等价性等属性保持)。
    • 然而,许多编程语言在表达式的计算过程中可能会产生副作用。这意味着,应用评估等严格评估策略与call-by-need等非严格评估策略不同。这很重要,因为没有区别,就没有必要将类函数(即与参数一起使用)宏与(传统)函数区分开来。但根据理论的风格,这仍然可以是一个人工制品。也就是说,在更广泛的意义上,类似函数的宏(尤其是卫生宏)是具有一些不必要限制(句法阶段)的数学函数。如果没有这些限制,将(一流)类似函数的宏视为过程可能是明智的......
    • 对于对此主题感兴趣的读者,请考虑一些现代抽象
  • 过程通常被认为超出了传统数学的范围。然而,在计算和编程语言语义以及当代编程语言设计的微积分建模中,可能有相当多的相关概念共享“可调用”性质。其中一些用于实现/扩展/替换过程/功能。还有更细微的区别。
于 2020-01-12T12:57:43.693 回答
5

更严格地说,如果 x = y,函数 f 遵循 f(x) = f(y) 的性质,即每次使用相同的参数调用它时,它都会计算相同的结果(因此它不会改变系统。)

因此,rand() 或 print("Hello") 等不是函数而是过程。虽然 sqrt(2.0) 应该是一个函数:无论调用它的频率如何,都没有可观察到的效果或状态变化,它总是返回 1.41 和一些。

于 2009-04-06T12:01:24.327 回答
4

如果我们在这里与语言无关,则过程通常指定一系列可靠且幂等地实现特定结果所需的行为。也就是说,一个过程基本上就是一个算法。

另一方面,函数是较大程序中的一段独立的代码。换句话说,函数是一个过程的实现。

于 2009-04-06T11:56:35.803 回答
3

在大多数情况下:函数返回一个值,而过程不返回。两者都是组合在一起以执行相同操作的代码段。

在函数式编程上下文(所有函数都返回值)中,函数是一个抽象对象:

f(x)=(1+x)
g(x)=.5*(2+x/2)

这里,f 与 g 的功能相同,但过程不同。

于 2009-04-06T11:56:11.623 回答
3

在程序内部我们可以使用 DML(插入/更新/删除)语句,但在函数内部我们不能使用 DML 语句。

过程可以有输入\输出参数,但函数只能有输入参数。

我们可以在存储过程中使用 Try-Catch 块,但在函数中我们不能使用 Try-Catch 块。

我们不能在 Select 语句中使用存储过程,但在函数中我们可以在 Select 语句中使用。

存储过程可以返回 0 或 n 个值(最大 1024),但函数只能返回 1 个值,这是强制性的。

存储过程不能从函数中调用,但是我们可以从存储过程中调用函数。

我们可以在存储过程中使用事务,但在函数中我们不能使用事务。

我们不能在 Where/Having/select 部分的任何地方使用 Sql 语句中的存储过程,但在函数中我们可以使用。

我们不能加入存储过程,但我们可以加入函数。

更多.. 点击这里... http://dotnet-developers-cafe.blogspot.in/2013/08/difference-between-stored-procedure-and.html

于 2013-12-31T06:10:17.783 回答
2

一个函数返回一个值,一个过程只执行命令。

名称函数来自数学。它用于根据输入计算值。

过程是一组可以按顺序执行的命令。

在大多数编程语言中,甚至函数也可以有一组命令。因此,区别仅在于返回值部分。

但是如果你想保持函数干净,(看看函数式语言),你需要确保函数没有副作用。

于 2012-05-22T04:17:15.107 回答
1

函数可以在 sql 语句中使用,而过程不能在 sql 语句中使用。

Insert、Update 和 Create 语句不能包含在函数中,但过程可以包含这些语句。

过程支持事务,但函数不支持事务。

函数必须返回一个且只有一个值(另一个可以由 OUT 变量返回),但过程返回尽可能多的数据集和返回值。

函数和过程的执行计划都被缓存了,所以两种情况下的性能是一样的。

于 2012-07-18T10:44:20.210 回答
1

我反对我在大多数这些答案中一遍又一遍地看到的东西,即使函数成为函数的是它返回一个值。

函数不仅仅是任何返回值的旧方法。不是这样:为了让一个方法成为一个真正的函数,它必须返回相同的值,总是给定一个特定的输入。不是函数的random方法的一个例子是大多数语言中的方法,因为尽管它确实返回一个值,但值并不总是相同的。

因此,函数更类似于映射(例如,x -> x'一维函数的位置)。这是常规方法和函数之间的一个非常重要的区别,因为在处理实际函数时,它们被评估的时间和顺序永远都不重要,因为非函数并不总是如此。

这是另一个不是函数但仍会返回值的方法的示例。

// The following is pseudo code:
g(x) = {
  if (morning()) {
     g = 2 * x;
  }
  else {
   g = x;
  }
  return g;
}

我进一步反对过程不返回值的概念。过程只是谈论功能或方法的特定方式。这意味着如果您的过程定义或实现的底层方法返回一个值,那么猜测该过程返回的值是什么。以SICP中的以下片段为例:

// We can immediately translate this definition into a recursive procedure 
// for computing Fibonacci numbers:

(define (fib n)
  (cond ((= n 0) 0)
        ((= n 1) 1)
        (else (+ (fib (- n 1))
                 (fib (- n 2))))))

你最近听说过递归过程吗?他们正在谈论一个递归函数(一个真正的函数)并且它正在返回一个值,并且他们正在使用“过程”这个词。那么有什么区别呢?

对函数的另一种思考方式(除了上面提到的含义)是对理想的抽象表示,例如数字 1。过程是该事物的实际实现。我个人认为它们是可以互换的。

(注意,如果您从我提供的链接中阅读该章节,您可能会发现更难掌握的概念不是函数和过程之间的区别,而是过程和过程之间的区别。您知道递归过程可以有迭代过程?)

程序的类似物是食谱。例如; 假设您有一台机器,称为make-pies这台机器,它接收 的成分,(fruit, milk, flower, eggs, sugar, heat)而这台机器返回一个pie.

这台机器的表示可能看起来像

make-pies (fruit, milk, flower, eggs, sugar, heat) = {
   return (heat (add fruit (mix eggs flower milk)))
}

当然,这不是制作馅饼的唯一方法。

在这种情况下,我们可以看到:

A       function     is to a     machine
as a    procedure    is to a     recipe
as      attributes   are to      ingredients
as      output       is to       product

这个类比是可以的,但是当你考虑到当你处理一个计算机程序时,一切都是抽象的。因此,与机器的配方不同,我们将两个本身是抽象的事物进行比较;两件事也可能是同一件事。我认为它们(出于所有意图和目的)是同一件事。

于 2014-02-24T01:35:20.843 回答
1

在С#/Java 中,function是返回特定值的代码块,而procedure是返回void(无)的代码块。在 C#/Java 中,函数和过程通常都称为方法

    //This is a function
    public DateTime GetCurrentDate()
    {
        return DateTime.Now.Date;
    }

    //This is a procedure(always return void)
    public void LogMessage()
    {
        Console.WriteLine("Just an example message.");
    }
于 2017-07-06T11:30:28.983 回答
0

db的上下文中:存储过程是预编译的执行计划,而函数则不是。

于 2016-11-26T21:36:58.347 回答
-3

过程: 1.过程是定义参数化计算的语句的集合。2.程序不能返回值。

3.程序不能从函数中调用。

函数 1.函数在结构上类似于过程,但在语义上以数学函数为模型。2.它可以返回值 3.函数可以从程序中调用。

于 2014-12-21T09:48:19.573 回答
-8

过程和函数都是子例程,它们之间的唯一区别是过程返回多个(或至少可以做)值,而函数只能返回一个值(这就是为什么在数学中使用函数表示法,因为通常只能找到一个值在某个特定时间)尽管某些编程语言不遵循这些规则,但这是它们的真实定义

于 2015-03-30T18:50:36.700 回答