回答

26

因爲我n計算機科學理論和實踐的原始概念,函數和子程序幾乎沒有任何關係。

FORTRAN通常被認爲是實現這兩種功能的第一種語言,並且證明了它們的區別。 (早期的LISP在這方面也有一些相反的作用,但它在學術界以外的影響甚微)。

從數學的傳統(CS仍然是60年代的一部分)開始,函數僅被看作是參數化數學計算的封裝,僅用於將數值返回到更大的表達式。你可以稱它爲「裸」(F = AZIMUTH(SECONDS))僅僅是一個簡單的用例。

另一方面,子例程被視爲一種方式來命名一組旨在產生某種效果的語句。參數大大提高了它們的可用性,它們被允許返回修改參數值的唯一原因是它們可以報告它們的狀態而不必依賴於全局變量。

所以,他們真的沒有概念上的連接,除了封裝和參數。

真正的問題是:「很多開發者是如何看待它們的?」

而答案是C.

K時+ R最初設計爲PDP-11的高級別宏彙編語言類型(可以在PDP-8已經開始?),他們沒有硬件獨立的妄想。實際上,語言的每個「獨特」特徵都反映了PDP機器語言和體系結構(請參閱i ++和--i)。其中之一是實現了功能和子程序可以(並且始終)在PDP中以相同的方式實現,除了調用者忽略子例程的返回值(在R0 [,R1]中)。因此誕生了虛空指針,並且在C語言接管了編程的整個世界之後,這種HW/OS實現工件(儘管在幾乎每個後續平臺上都是如此)的誤解與語言語義相同。

3

在純或效果類型的設置有天淵之別,因爲很明顯,「不返回任何東西」的方法只對其副作用有用。

這類似於表達式和語句之間的區別,它們可以剔除語言並消除一類通常錯誤的程序(當然這就是爲什麼C不這樣做))。

舉一個小例子,當你區分清楚的表達式和語句,if(x = 3)之間,相對於if(x == 3)在語法上是不正確的(用於使用其中預期的表達的陳述),而不是僅僅一種類型的錯誤(使用整數預計布爾值)。這也有一個好處,就是禁止if(x = true),在分配是具有右操作數值的表達式的上下文中,基於類型的規則將允許這種做法。

在一個封裝單子效果的語言,最重要的區別成爲一個之間:返回()這是純粹的功能,只能返回

  • 函數調用()或一個無用的空值偏離
  • 函數返回IO()(或其他單元中的單元),這些函數除了IO(或其中的任何一個)單元中的效果之外沒有「結果」函數
+0

很好的解釋,但是,示例表達式似乎假定C. – RBarryYoung 2009-06-19 17:53:17

+0

C清楚地區分表達式和語句。然而,`x = foo`是一個表達式,評估分配的值。這使得某些成語更加簡潔(例如fork,不確定迭代)。 – Novelocrat 2009-09-29 22:32:58

0

不好意思回答一個兩歲的問題,尤其是獨特的,以我自己的語言菲利克斯http://felix-lang.org的東西,但在這裏不用反正:)

在菲利克斯,函數和過程是根本不同的,它不僅是程序有副作用並在語句中調用,而函數沒有副作用並用於表達式中(因爲Felix也具有帶副作用函數的生成器。:)

不,執行模型是主要是出於性能方面的原因,但並非完全不同。該模型是:

  • 函數將它們的返回地址放在機器堆棧上,並返回值。
  • 過程使用堆上的鏈接列表。程序代碼是平的,它不使用機器堆棧。

這通常是低效的,那爲什麼呢?答案是:Felix程序都是潛在的共同程序(纖維)。他們可以通過訪問一個通道將控制切換到另一個過程。這導致交換控制權。

  • 由於性能原因,不能在控制交換機器上覆制機器堆棧。
  • 由於內存管理的原因,交換堆棧指針也不是一個選項。

操作系統通常交換堆棧指針線程,這是相當快的,但對線性地址機器的一個基本問題:你要麼必須堆棧的最大大小限制爲一個可笑的小值,或限制線程數量到一個可笑的小值。在32位機器上,沒有足夠的地址空間來設想這種解決方案。在64位機器上,堆棧交換具有更大的潛力,但當然用戶需求在其發佈後3天內總是增長超過硬件。:)

Felix只是將一個指針交換到基於堆棧的堆棧,所以上下文切換非常快,而且很少浪費地址空間。當然,成本是程序調用上的堆分配。

在編譯器中,理論模型的很多架構都是基於「as-if」優化的,所以實際的性能和實現可能與理論模型有很大不同,前提是編譯器可以證明您除了被剝奪機會製作一杯咖啡以外,還有其他的不同:)

所以,在這裏,你有一個不同的答案,爲什麼函數和過程可能會被區別對待。

相關問題