これは興味深い議論です。@flodel さんの例は素晴らしいと思います。ただし、機能的なコーディングスタイルの代わりに命令return
を使用する場合に理にかなっている私のポイント(および@koshkeがコメントでこれに言及している)を示していると思います.
要点を非難するつもりはありませんが、私は次のように書き直したでしょうfoo
:
foo = function() ifelse(a,a,b)
機能的なスタイルは、 の値を格納するなど、状態の変更を回避しますoutput
。このスタイルでreturn
は、場違いです。foo
数学関数のように見えます。
私は@flodelに同意します。ブール変数の複雑なシステムを使用するbar
ことは、あまり明確ではなく、return
. ステートメントをbar
非常に受け入れやすいものにしてreturn
いるのは、それが命令的なスタイルで書かれていることです。実際、ブール変数は、機能的なスタイルで回避される「状態」の変更を表します。
bar
単なる疑似コードなので、関数型に書き直すのは本当に難しいですが、アイデアは次のようなものです。
e_func <- function() do_stuff
d_func <- function() ifelse(any(sapply(seq(d),e_func)),2,3)
b_func <- function() {
do_stuff
ifelse(c,1,sapply(seq(b),d_func))
}
bar <- function () {
do_stuff
sapply(seq(a),b_func) # Not exactly correct, but illustrates the idea.
}
ループは へのwhile
状態変化によって制御されるため、書き換えが最も困難a
です。
の呼び出しによる速度の低下return
は無視できますが、回避return
して関数型のスタイルで書き直すことによって得られる効率は、多くの場合非常に大きくなります。新しいユーザーに使用をやめるように言ってreturn
もおそらく役に立たないでしょうが、機能的なスタイルに誘導することで利益が得られます.
@Paulreturn
は、ループ内のさまざまなポイントで関数を終了したいことが多いため、命令型スタイルで必要です。機能的なスタイルはループを使用しないため、必要ありませんreturn
。純粋に機能的なスタイルでは、ほとんどの場合、最後の呼び出しが目的の戻り値になります。
Python では、関数にはreturn
ステートメントが必要です。ただし、関数スタイルで関数をプログラミングした場合は、関数return
の最後に 1 つのステートメントしかない可能性があります。
TRUE
別の StackOverflow 投稿の例を使用して、指定されたすべての値のx
長さが奇数の場合に返される関数が必要だとしましょう。2 つのスタイルを使用できます。
# Procedural / Imperative
allOdd = function(x) {
for (i in x) if (length(i) %% 2 == 0) return (FALSE)
return (TRUE)
}
# Functional
allOdd = function(x)
all(length(x) %% 2 == 1)
関数型では、返される値は当然関数の最後にあります。繰り返しますが、数学関数のように見えます。
@GSeeで概説されている警告?ifelse
は間違いなく興味深いものですが、関数の使用を思いとどまらせようとしているとは思いません。実際、ifelse
関数を自動的にベクトル化するという利点があります。たとえば、わずかに変更されたバージョンの を考えてみましょうfoo
:
foo = function(a) { # Note that it now has an argument
if(a) {
return(a)
} else {
return(b)
}
}
この関数length(a)
は が 1 のときに問題なく動作しますfoo
。ifelse
foo = function (a) ifelse(a,a,b)
foo
の任意の長さで機能するようになりましたa
。a
実際、が行列の場合でも機能します。と同じ形状の値を返すtest
ことは、ベクトル化に役立つ機能であり、問題ではありません。