為什麼大多數編程語言被設計成函數只有一個返回值,而不是多個?

程序語言的發展很大的部分受人類正常思維方式的影響,在生活中,給一個輸入,有兩個輸出很常見,而大多數編程語言為什麼不這麼設計?

—————————————————————

不同編程語言因設計的不同支持1個或多個返回值,故於2016—02—06更改問題。


現代編程語言中「函數」概念多來自 ALGOL 和 Fortran

ALGOL 和 Fotrean 的概念借自數學

數學函數有多元之說,然而你見過幾個「多返回值」的?


python允許你干多個返回值的事情。然並卵,其實會包裹成一個tuple,加之tuple本來就可以原素綁定…


根據函數的定義,值域只能是一個單一的對象,例如一個數,一個列表,一個對象,但不能是多個數。


其實這個問題也不是一句「返回一個數據結構」就可以清楚解決的。既然返回值可以是一個數據結構,那麼參數其實也可以。為什麼從C、Pascal這些古老的語言開始,參數就可以是多個,而返回值卻是一個呢?這個問題值得探討一下。

假設我們設計了一個語言叫C-,函數的參數和返回值都只能是一個,那麼在C-里,一個多參數多返回值的函數的定義和使用過程就是這樣的:

struct Para...;//define a parameter struct
struct Ret...;//define a return struct
Ret func(Para p){
...
}

Para para = XXX;
Ret ret;
ret = func(para);

為了使用這個函數,我們需要定義數據結構Para和Ret,是不是很麻煩?如果能去掉會省很多事。

好了,那麼問題就變成了:為什麼編程語言大多去掉了Para而不是Ret?

這和函數本身的行為有關。一個函數的行為如下圖:

大家看出什麼問題沒?

參數可以看做是函數的屬性,因為Para這個結構可能只在函數內使用(大多數情況下)。因此,我們為這個函數定義Para結構的行為,其實就是函數定義過程中的一個步驟。既然如此,那麼把Para的定義放到函數定義里就好了嘛。

把下面的代碼:

struct Para{
int a;
int b;
}
int func(Para p)
...

變成:

int func(int a, int b)
...

是不是變得簡單清晰易讀了?

那為什麼Ret的結構不放在函數定義中呢?

因為Ret是函數的產出,別的地方肯定也要用。一個公用的數據結構放在函數定義里顯然不是合理的設計。

當然,很多情況下我們也可能會給函數傳入一個自己定義的數據結構作為參數。不過這大多是因為這個數據結構本來就是要到處用的(比如用結構(x,y)來代表平面上的一個點)。一般而言,我們不會為了表達一個函數的參數結構,而單獨地定義一個數據結構。因此參數結構就內化為了函數的屬性。


在runtime允許多值return並不是很有用,雖然看上去好像非常有用,如果這是一個必要的語言機制,那現在大多數語言就應該已經都支持了。如果你用過有這個功能的語言,比如Go,也多用來方便錯誤處理,它不一定要這麼用,但實際的代碼里通常就是這樣

result, err := func()
result, _ := func()

而少見(不是說沒有)

val1, val2 := func()

為什麼?

因為return一個數據結構更自然

return array(tuple) | dict(struct/map) | object | function;

語言本身有更強大,封裝性更好的數據結構可以用,再在語言里實現multiple return value就不是必要的了。Go的例子,用在錯誤處理上是務實的,因為你不想在所有可能return的數據結構里封裝error成員,但想把錯誤處理和正常返回區分開,這是Go的取捨,不具有普遍性。

一個語言支持這個功能以後,寫程序更容易了嗎?我個人不覺得,多值賦值有次序依賴,實際寫代碼的時候還要關注這個東西,反而麻煩,所以與其:

product_id, product_name, product_desc = getProduct()

不如

product = getProduct() // { product_id: ... product_name: ... product_desc: ... }

試想如果product的結構變化了,哪一個方法的代碼更好維護呢,顯然是後者。


這是一個好問題。為什麼函數只返回一個值。這是存儲和計算的一種統一。一個沒有副作用的函數,返回一個值,那他在使用上其實是可以看做一個變數,一個有條件的變數,可以很好的簡化程序。


你用的語言太落後了,問題不成立+1

至於上邊說寄存器的那位,拜託高級語言的函數返回值什麼時候直接對應寄存器了


請看Lua,函數參數可多可少,返回值可多可少,接收返回值也是可多可少。


取決於編程語言的設計,例如c函數的返回值只有一個,PHP則可以有多個。

函數的返回值本質是將數據壓棧,重點是知道棧的大小,返回值的個數不重要。

之所以需要說明返回值的個數,是因為把他們的大小相加,便決定了棧的大小。

從這個意義上說,函數的返回值被設計成有1個或是有多個並沒有關係,返回2個int,就是返回一個float,或者是返回一個大小為sizeof(int) * 2的結構體。

而之所以不同的編程語言被設計成有不同個數的返回值,可能是出於歷史繼承或者編程風格的原因。(個人觀點,僅供參考。)


首先,樓主,這個問題不該有Python標籤,因為Python是可以返回多個值構成一個元組的,這個元組你願意拆開用也可以,一起用也行。

另外,即使是最普通的C語言,你也可以通過返回一個結構體的方式返回一堆數據,保存在結構體里就行了。

我覺得你似乎是想說為什麼函數只能有一次返回行為,不過,這個問題對python也是不成立的,python有yield。


有些語言可以直接返回多個返回值,有些要通過封裝。但總的來說是大部分主流語言都能直接或間接實現這個功能。


很多支持多個返回值,lua就支持,現在js也支持了(es6)。

多個返回值,在彙編很常見,一般來說彙編函數,eax,ecx,edx這3個寄存器是不需要保存的,其他寄存器在函數進入的時候push,返回的時候popup,c語言就是用eax來返回的,ecx,edx還能用來返回2個參數。就是說高級語言支持多個返回參數,如果返回參數在3個以內(99%),是可以在彙編這級優化的。如果是通過一個類似c語言結構來返回多值,那就沒有啥意義。


C里調一個指針或者結構體指針,你想返回多少都行,只要內存夠。


流行得比較早的語言,比如pascal和c,都只有一個返回比較簡單類型的返回值,這可能是為了把返回值放到某寄存器中返回,這樣調用者可以直接用,有利於提高程序的速度。過去cpu是很慢的,這種優化很有價值。

c++大概是繼承了c,所以只有一個i返回值。java從語法上模仿c++,所以也只有一個返回值。

設計一個多個返回值的語言,並不困難。golang就是一個。


怎麼沒人提matlab,matlab可以有多個返回值的


1.返回多個值通常來說並不常用

2.大部分語言都可以返回一個數組或者一個對象來實現返回多個值的效果

3.Python等語言提供直接返回多個值的功能


Python可以返回多個。


C++

return make_pair(a,b)

Python

Return a,b

(抱歉目前我只會這兩種語言


從本質上說,因為圖靈機只有一個返回值(或者說狀態)。有一個返回值就能達到圖靈完備,為何需要兩個返回值?另外,多個返回值就需要多個寄存器,既浪費又不利於編譯器優化。從我們的直覺來看,你得到的兩個返回值,它們一定能在某個層級上被抽象為一個東西,這在程序中的表現就是返回抽象體的指針(或引用)


該複習下函數的定義,數學上函數就是可以有多輸入,但是只能有唯一輸出的,因此大部分解析幾何圖像都不是函數


推薦閱讀:

用 Python 做策略回測,耗時很長,有什麼加速辦法?
怎麼看待最近 Python 變成 Web 開發語言排行第二?
ruby和python該學那一個?

TAG:編程語言 | Python | Java | 編程思想 |