“功能”和“程序”有什么区别?

时间:2009-04-06 11:48:10

标签: function terminology procedure

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

所以,我的问题是:

  

它们的功能,用途和用途有何不同?

一个例子将不胜感激。

17 个答案:

答案 0 :(得分:267)

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

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

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

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

但是如果你想保持一个功能干净,(只看功能语言),你需要确保一个功能没有副作用。

答案 1 :(得分:37)

这取决于具体情况。

在类似Pascal的语言中,函数和过程是不同的实体,不同的是它们是否返回值。他们表现得与众不同。语言语法(例如,过程调用表单语句;您不能在表达式中使用过程调用,而函数调用不会形成语句,您必须在其他语句中使用它们)。因此,Pascal-bred程序员区分它们。

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

在函数式语言中,通常没有程序这样的东西 - 一切都是函数。

答案 2 :(得分:15)

C:

中的示例
// function
int square( int n ) {
   return n * n;
}

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

虽然你应该注意C标准不讨论程序,只讨论函数。

答案 3 :(得分:11)

通常,程序是一系列指令 函数可以是相同的,但通常会返回结果。

答案 4 :(得分:10)

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

功能和程序是这些的实现。通常函数返回值和过程不返回任何内容。

答案 5 :(得分:6)

基本差异

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

高级差异

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

在SQL中:

  • 一个过程允许SELECT以及其中的DML(INSERTUPDATEDELETE)语句,而Function只允许SELECT语句
  • 不能在SELECT语句中使用过程,而可以在SELECT语句中嵌入函数。
  • 存储过程不能在WHERE(或HAVINGSELECT)块中的任何位置的SQL语句中使用,而函数可以。
  • 返回表的函数可以视为另一个Rowset。这可以在JOIN块中与其他表一起使用。
  • 内联函数可以被视为带参数的视图,可以在JOIN块和其他Rowset操作中使用。

答案 6 :(得分:5)

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

因此,rand()或print(“Hello”)等不是函数而是程序。 虽然sqrt(2.0)应该是一个函数:没有可观察到的效果或状态改变,无论多少次调用它,它总是返回1.41和一些。

答案 7 :(得分:4)

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

基本答案

传统上(在structured programming的意义上)和非正式地,过程是可重用的结构构造,具有“输入”并进行一些可编程的操作。当需要在过程中执行某些操作时,可以在源代码中编码的过程调用中为过程提供(实际)参数(通常以一种表达式),然后在程序 body 中编码的操作(在程序的定义中提供)将参数替换为(正式)参数来执行用在体内。

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

传统上,过程调用(而不是函数调用)用于指示没有输出必须是有兴趣的,并且必须有side effects才能避免无操作调用,因此强调了imperative programming paradigm 。许多传统的编程语言(例如Pascal)都提供“过程”和“功能”,以区分这种故意的样式差异。

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

但是,如果不需要函数调用的结果,则可以(至少在逻辑上)忽略它,并且函数定义/函数调用应以此方式与过程定义/过程调用一致。类似于C,C ++和Java的类似于ALGOL的语言都以这种方式提供“函数”的功能:通过将结果类型void编码为类似于传统过程的函数的特例,无需提供分别具有“程序”的功能。这样可以防止语言设计出现膨胀。

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

我对分歧背后的确切原因并不十分了解,但是据我所知,如今的语言设计师似乎会更加高兴,而不会出现规范膨胀。即,不需要“程序”作为独立功能。像void类型这样的技术已经足以标记应强调副作用的用途。对于拥有数十年来流行的类C语言经验的用户来说,这也更自然。而且,它避免了在R n RS之类的情况下的尴尬,在这种情况下,“过程”实际上是广义上的“功能”。

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

  • 就像在R n RS中一样,只需将不感兴趣的结果标记为“未指定”值(如果语言必须提及,则为未指定类型),就可以将其忽略。
  • 将不感兴趣的结果指定为专用单位类型的值(例如Kernel#inert)也可以。
  • 当该类型又是底部类型时,可以(希望)对其进行静态验证,并防止将其用作表达式类型。类似ALGOL的语言中的void类型正是这种技术的一个示例。 ISO C11的_Noreturn是类似但更微妙的一种。

进一步阅读

作为源自数学的传统概念,有tons of black magic多数人不愿知道。严格来说,按照数学书籍,您可能不太清楚整个过程。 CS书籍也可能没有太大帮助。

关于编程语言,有几个警告:

  • 数学的不同分支中的函数并非总是定义为具有相同的含义。不同编程范例中的函数也可能完全不同(甚至有时函数调用的语法看起来相似)。有时导致差异的原因是相同的,但有时并非如此。
    • 习惯上是先用数学函数对计算建模,然后用编程语言实现基础计算。除非您知道所谈论的内容,否则请避免将它们一对一地映射。
  • 不要将模型与要建模的实体混淆。
    • 后者只是前者的实现之一。取决于上下文(例如,对数学感兴趣的分支),可以有多个选择。
    • 尤其是,除了某些有限的上下文外,将“函数”视为“映射”或笛卡尔积的子集或多或少都非常荒谬,例如将自然数视为Von-Neumann encoding of ordinals (looking like a bunch of {{{}}, {}}...)
  • 从数学上讲,函数可以是partial or total。不同的编程语言在这里有不同的处理方式。
    • 某些函数式语言可能会使用totality个函数,以确保函数调用内的计算始终以有限的步长终止。但是,这基本上不是图灵完备的,因此计算表达能力较弱,并且除了类型检查的语义(预期是总计)之外,在通用语言中很少见。
    • 如果程序和功能之间的差异很大,是否应该有“全部程序”?嗯...
  • 类似于用于model the general computationthe semantics of the programming languages的计算中函数的构造(例如lambda calculi中的lambda抽象)在操作数上可以具有不同的evaluation strategies
    • 传统上,纯结石的减少以及pure functional languages中表达式的评估,没有副作用会改变计算结果。结果,不需要在类似函数的构造体之前对操作数进行求值(因为用于定义“相同结果”的不变性由β的属性保留,Church-Rosser property保证了等价性) 。
    • 但是,许多编程语言在表达式求值过程中可能会有副作用。这就是说,严格的评估策略(如“应用评估” / emem)与非严格评估的策略(如“按需致电” / em)是不一样的。这是很重要的,因为没有区别,就不需要将类似于函数的宏(即与自变量一起使用)与(传统)函数区分开。但是根据理论的风格,这仍然可能是人工制品。也就是说,从广义上讲,类似于函数的宏(尤其是hygienic宏)是具有某些不必要限制(语法阶段)的数学函数。 在没有限制的情况下,将(一流的)类函数宏视为过程可能是理智的。
    • 对于对此主题感兴趣的读者,请考虑some modern abstractions
  • 过程通常被认为超出了传统数学的范围。但是,在计算计算和编程语言语义以及当代编程语言设计的演算建模中,可能会有相当多的相关概念家族共享“可调用”性质。其中一些用于实现/扩展/替换过程/功能。还有更细微的区别。

答案 8 :(得分:3)

如果我们在这里与语言无关,那么过程通常会指定一系列可靠且明确地实现某些结果所需的行为。也就是说,程序基本上是一种算法。

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

答案 9 :(得分:3)

在大多数情况下:函数返回一个值,而一个过程则不返回。两者都是组合在一起的代码片段来做同样的事情。

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

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

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

答案 10 :(得分:2)

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

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

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

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

但是如果你想保持一个功能干净,(只看功能语言),你需要确保一个功能没有副作用。

答案 11 :(得分:1)

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

插入,更新和创建语句不能包含在函数中,但过程可以包含这些语句。

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

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

缓存了函数和过程的执行计划,因此两种情况下的性能都相同。

答案 12 :(得分: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

这个比喻是可以的,但是当你考虑到当你处理计算机程序时,一切都是抽象的,它就会崩溃。因此,与机器配方的情况不同,我们正在比较两个本身就是抽象的东西;两件事可能是同一件事。而且我认为它们(出于所有意图和目的)都是一样的。

答案 13 :(得分:0)

db 的上下文中: 存储过程是预编译的执行计划,其中功能不是。

答案 14 :(得分:0)

就С#/ 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.");
    }

答案 15 :(得分:-2)

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

3.无法从功能中调用程序。

<强>功能 1.功能在结构上类似于程序,但在语义上模仿数学函数。 2.它可以返回值 3.可以从程序调用函数。

答案 16 :(得分:-4)

程序和函数都是子程序,它们之间的唯一差异是程序返回多个(或至少可以做)值,而一个函数只能返回一个值(这就是数学中使用函数符号的原因,因为通常在一个给定时间只找到一个值),尽管某些编程语言不遵循这些规则这是它们的真正定义