2016-03-31 3 views
-1

、私は次のような構成に興味を持っていた:どのように連鎖バイナリの機能のリストを

はのは、私がnバイナリ関数のリストとn+1引数のベクトルを持っているとしましょう。引数のために私は何をしたいことは

`-`(`+`(1,2),3) 

どこ戻り値この例では、すなわち、次の関数呼び出しF2(F1(X1、X2)、X3)を作成している

flist = c(`+`,`-`) 
args = 1:3 

を使用することができます累積結果のベクトルは、Iフォーム

f = function(x,op,res = NULL){ 
    if(is.null(res)){ 
    res = op[[1]](x[1],x[2]) 
    x = x[-1] 
    } else{ 
    res = c(res,op[[1]](res[length(res)],x[1])) 
    } 
    if(length(op) == 1) res 
    else f(x[-1],op[-1],res) 
} 
の溶液を有する

[1] 3 0 

あります

であるようには正解

f(x,flist) 
[1] 3 0 

を与えるが、それは特に、R様またはエレガントな感じがしません。これを行うより良い方法はありますか?私は自分の実装が最も効率的ではないと考えているので、より効率的なものも関心の対象となります。

いずれかのアイデアがありますか?

累積回答が必要な場合、つまり最終回答の0が返された場合は、これを行うには良い方法がありますか?私は私のfをこの代替案に対処するために修正することができると知っていますが、すでにこれを行う方法が存在する場合は、いずれかのオプションについて聞きたいと思います。

編集:私たちは、より効率的にうまくいかない

falt = function(x,op){ 
    res = numeric(length(op)) 
    res[1] = op[[1]](x[1],x[2]) 
    for(i in 2:length(res)) res[i] = op[[i]](res[i-1],x[i+1]) 
    res 
} 

を持つことができるように

コメントはforループの実装を示唆しました。しかし、私はまだこれを行うための優しい方法が必要であると感じています。

+0

なぜ再帰を使用して 'res'を成長させるのですか? 'for'ループを使い、最後のサイズにresをあらかじめ割り当ててください。 – Roland

+0

特別な理由はありませんでしたが、私は現在スカラを学習していますので、再帰は私の心にたくさんあります。 'for'ループを使った実装は大丈夫ですが速く、R深い再帰は悪いので合理的な提案です。これは良い減算操作のいくつかの並べ替えがこれのために存在する必要がありますように感じる。私は個人的な悩みを抱えていますが、私はまた、その機能的でベクトル化された性質のため、Rの 'for 'ループのファンではありません。 私はまた、Rの成長する物体の愚かさについても一時的に忘れていました。 – jamieRowen

+0

Reduceのドキュメントをチェックしますか?反復を検索する...役に立つかもしれない – chinsoon12

答えて

2

あなたの関数はカリー化形式に既にある場合、それは、すべてがカリーですので、あなたが望むように、あなたはできるだけ多くの引数を適用することができます

comp <- function (f) function (g) function (x) f(g(x)) 

comp2 <- comp (comp) (comp) # if this is confusing, details later 

add <- function (x) function (y) y + x 
mult <- function (x) function (y) y * x 

comp2 (mult) (add) (3) (4) (5) 
# 5 * (4 + 3) 
# 5 * 7 
# 35 

多くの方が簡単だし、後で

compute <- comp2 (mult) (add) 
compute (5) (6) (7) 
# 7 * (6 + 5) 
# 7 * 30 
# 210 
残りを適用

バイナリ関数のリストがある場合は、左辺(または「reduce」)を使用してシーケンス全体を作成できます

identity <- function(x) x 
comp <- function (f) function (g) function (x) f(g(x)) 
comp2 <- comp (comp) (comp) 
uncurry <- function (f) function (x,y) f(x)(y) 
reduce <- function(f) function(y) function (xs) Reduce(uncurry(f), xs, y) 
comp2All <- reduce (comp2) (identity) 

# some binary functions to use in our sequence 
sub <- function (x) function (y) y - x 
add <- function (x) function (y) y + x 
mult <- function (x) function (y) y * x 

# create a sequence of N binary functions 
compute <- comp2All (list(mult, sub, mult, add)) 

# apply the computation to N+1 args 
compute (3) (4) (5) (100) (0.2) 
# 0.2 * (100 - (5 * (3 + 4)) 
# 0.2 * (100 - (5 * 7)) 
# 0.2 * (100 - 35) 
# 0.2 * 65 
# => 13 

だから、一度に1つの引数を計算する必要はありません...

# this kind sucks, right? 
compute (3) (4) (5) (6) (7) 

まあ、我々はリストにカリー化関数を適用機能または引数バイナリの機能はまだカリー化されていない場合は

capply <- reduce (identity) 
capply (compute) (3:7) 
# 7 * (6 - (5 * (4 + 3))) 
# 7 * (6 - (5 * 7)) 
# 7 * (6 - 35) 
# 7 * -29 
# => -203 

を作ることによってこれを修正することができます

バイナリ関数を簡単にカレーすることができますcurry2

curry2 <- function(f) function(x) function(y) f(x,y) 
curry2 (`+`) (3) (4) 
# => 7 

すでにカリー化されないバイナリの機能の全体のリストを持っている場合は、あなたがしたいので、あなたがCOMP2

map

map <- function (f) function (xs) Map(f,xs) 
compute <- comp2All (map (curry2) (list (`*`, `+`, `*`, `+`))) 
compute (3) (4) (5) (6) (7) 
# 7 * (6 + (5 * (3 + 4))) 
# 7 * (6 + (5 * 7)) 
# 7 * (6 + 35) 
# 7 * 41 
# => 287 

カンプを使用して、リスト全体を変換することができますがバイナリ関数のシーケンスを作成するために、私は

comp2All <- reduce (comp2) (identity) 

あなたは単項機能のシーケンスを望んでいた場合、あなたは

compAll <- reduce (comp) (identity) 

COMP2は何を使うのでしょうか?

COMP2の定義は、我々が最初に(さらに拡張されると

comp2 <- function (x) comp(comp(x)) 

を参照してくださいね、不可解に思えるかもしれないが、我々はこれを拡張した場合、それはあなたに

comp2 <- comp (comp) (comp) 

を混同してはいけませんこれは楽しい演習です)、あなたは見てください。

comp2 <- function (f) function (g) function (x) function (y) f(g(x)(y)) 

fバイナリ関数を持つg

+0

私はこれを一般的に見るのが好きで、それが私の最小限の例にどのように適用できるかを見ることができます。どのようにこれを一般的なケースに拡張するか、 'n'関数と' n + 1'引数のリストが他のメカニズムから来ているとしましょう。 'n'が大きければ、関数が何であるか、リストが本当にどれくらい長いかを心配したくない。 – jamieRowen

+0

すべての関数はバイナリ関数ですか?彼らはすでにカレーされているのですか? – naomik

+0

ここでのすべての関数はバイナリであり、一般的にカレット化されたものではありません。最後の例では 'f'と' g'を引数 'x'と' y'で定義されたバイナリ関数に置き換えてみましたが、上記のように使用すると引数のエラーが抜けてしまいます。私は現在、どのように 'comp2(Curry(flist [[1])))(Curry(flist [2]))(.....' – jamieRowen

関連する問題