“function”和“function”的区别是什么?而“程序”呢?

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

我的问题是:

它们的功能、目的和用途有什么不同?

请举例说明。

374509 次浏览

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

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

函数的名称来源于数学。它用于根据输入计算一个值。

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

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

但是如果你想让函数保持简洁(看看函数式语言就知道了),你需要确保函数没有副作用。

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

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

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

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

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

这里,f和g是同一个函数,但是过程不同。

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

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

C语言示例:

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


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

尽管你应该注意到C标准没有谈论过程,只有函数。

这取决于上下文。

在类pascal语言中,函数和过程是不同的实体,不同之处在于它们是否返回值。他们的行为不同。语言语法(例如;过程调用表单语句;你不能在表达式中使用过程调用,而函数调用不构成语句,你必须在其他语句中使用它们)。因此,pascal培养的程序员会对这两者进行区分。

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

在函数式语言中,通常没有过程这样的东西——所有东西都是函数。

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

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

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

函数的名称来源于数学。它用于根据输入计算一个值。

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

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

但是如果你想让函数保持简洁(看看函数式语言就知道了),你需要确保函数没有副作用。

Function可以在sql语句中使用,而procedure不能在sql语句中使用。

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

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

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

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

基本的不同点

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

先进的差异

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

在SQL:

  • 过程中允许SELECT和DML (INSERTUPDATEDELETE)语句,而函数中只允许SELECT语句。
  • 过程不能在SELECT语句中使用,而函数可以嵌入到SELECT语句中。
  • 存储过程不能在WHERE(或HAVINGSELECT)块中的SQL语句中使用,而函数可以。
  • 返回表的函数可以被视为另一个行集。这可以在JOIN块中与其他表一起使用。
  • 内联函数可以被认为是接受参数的视图,可以在JOIN块和其他行集操作中使用。

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

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

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

在选择语句中不能使用存储过程,但在函数中可以使用。

存储过程可以返回0或n个值(最多1024个),但函数只能返回1个必须的值。

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

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

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

我们不能连接存储过程,但可以连接函数。

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

我反对在大多数答案中反复看到的东西,函数之所以成为函数,是因为它返回一个值。

函数不是任何返回值的旧方法。事实并非如此:为了让一个方法成为一个实函数,它必须总是在给定特定输入的情况下返回相同的值。不是函数的方法的一个例子是大多数语言中的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

这个类比是可以的,但当你考虑到当你在处理一个计算机程序时,一切都是抽象的,它就不成立了。所以不像机器的配方我们比较的是两个本身就是抽象的东西;这两件事很可能是同一件事。我认为它们(出于所有意图和目的)是同一件事。

<强>程序: 1.过程是定义参数化计算的语句的集合。 2.

3.不能从函数调用过程。

< >强劲功能 1.函数在结构上类似于过程,但在语义上以数学函数为模型。 2.它可以返回值 3.函数可以从过程中调用。< / p >

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

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

在С#/Java中,函数是返回特定值的代码块,而过程是返回无效(什么都没有)的代码块。在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.");
}

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

基本的答案

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

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

传统上,过程调用(而不是函数调用)被用来表示没有输出必须是感兴趣的,并且必须有< em > < / em >副作用来避免调用是无操作的,因此强调命令式编程范式。许多传统编程语言(如Pascal)同时提供“过程”和“函数”来区分这种有意的风格差异。

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

但是,如果不需要函数调用的结果,可以忽略它(至少在逻辑上),并且函数定义/函数调用应该以这种方式与过程定义/过程调用一致。像C、c++和Java这样的algo类语言,都以这种方式提供了“函数”的特性:通过将结果类型void编码为一种特殊情况,使函数看起来像传统的过程,因此没有必要单独提供“过程”的特性。这可以防止语言设计中的一些膨胀。

既然提到了SICP,同样值得注意的是,在R <一口> n > < /晚餐RS指定的Scheme语言中,过程可以返回计算结果,也可以不返回。这是传统的“函数”(返回结果)和“过程”(不返回任何结果)的结合,本质上与许多类algo语言的“函数”概念相同(实际上共享更多的保证,例如在调用之前对操作数进行应用计算)。然而,老式的差异仍然出现在像srfi - 96这样的规范性文档中。

我不太清楚这种分歧背后的确切原因,但根据我的经验,现在没有规范膨胀,语言设计师似乎会更快乐。也就是说,“过程”作为一个独立的特性是不必要的。像void类型这样的技术已经足以在应该强调副作用的地方标记使用。对于使用过c类语言的用户来说,这也更自然,因为c类语言已经流行了几十年。此外,它避免了像RnRS这样的尴尬情况,在这种情况下,“过程”实际上是更广泛意义上的“函数”。

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

  • 就像在RnRS中一样,只要将不感兴趣的结果标记为“未指定”值(如果语言必须提到它,则为未指定类型),就足以忽略它。
  • 将不感兴趣的结果指定为专用单元类型的值(例如内核#inert)也可以。
  • 当该类型进一步为底类型时,可以(希望)静态验证并防止将其用作表达式类型。类algo语言中的void类型正是这种技术的一个例子。ISO C11的_Noreturn是类似的,但更微妙。

进一步的阅读

由于传统概念来源于数学,有大量的黑魔法大多数人懒得知道。严格地说,你不可能像你的数学书那样把所有事情都弄清楚。计算机科学书籍可能也提供不了太多帮助。

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

    不同数学分支中的函数并不总是定义有相同的含义。不同编程范式中的函数也可能有很大不同(甚至有时函数调用的语法看起来很相似)。有时造成差异的原因是相同的,但有时不是。
    • 习惯用法是用数学函数建模计算,然后在编程语言中实现 潜在的计算。注意不要把它们一一对应,除非你知道对方在说什么。
    • 李< / ul > < / >
    • 不要将模型与要建模的实体混淆。
      • 后者只是前者的实现之一。根据上下文(例如,感兴趣的数学分支),可以有多个选择。
      • 特别是,将“函数”视为“映射”或笛卡尔积的子集,或多或少类似地荒谬,就像将自然数视为序数的Von-Neumann编码(看起来像一堆\{\{{}}, {}}…)一样,除了一些有限的上下文之外。
      • 李< / ul > < / >
      • 数学上,函数可以是partialtotal。不同的编程语言在这里有不同的处理方式。
        • 一些函数式语言可能遵循函数的< em > < / em >整体,以保证函数调用中的计算总是在有限步内结束。然而,这本质上不是图灵完备的,因此计算表达性较弱,除了类型检查语义(预计是完全的)之外,在通用语言中并不常见。
        • 如果过程和功能之间的差异很大,是否应该有“全部过程”?嗯…
        • 李< / ul > < / > 类似于用于建立一般计算模型编程语言的语义的演算中的函数的构造(例如,λ结石中的lambda抽象)可以在操作数上具有不同的评估策略
          • 在传统的纯演算和纯函数式语言中表达式的求值中,没有改变计算结果的副作用。因此,操作数不需要在类似函数的构造体之前求值(因为定义“相同结果”的不变量由Church-Rosser财产保证的β-equivalence等属性保留)。
          • 然而,许多编程语言在表达式求值时可能会有副作用。这意味着,像应用评价这样的严格评估策略与像call-by-need这样的非严格评估策略是不同的。这很重要,因为如果没有这种区别,就不需要将类函数宏(即与参数一起使用)与(传统的)函数区分开来。但根据理论的不同,这仍然可能是人工制品。也就是说,在更广泛的意义上,类函数宏(特别是卫生 ones) 数学函数具有一些不必要的限制(语法阶段)。如果没有这些限制,将(一类)类函数宏视为过程可能是明智的……
          • 对这个话题感兴趣的读者可以参考一些现代抽象概念
          • 李< / ul > < / > 过程通常被认为超出了传统数学的范围。然而,在对计算和编程语言语义建模的微积分中,以及当代编程语言设计中,可以有相当多的相关概念共享“可调用”的性质。其中一些用于实现/扩展/替换过程/函数。甚至还有更微妙的区别。