2016-07-19 16 views
0

は、以下の再帰mapの関数である:明らかにcurried形式の再帰関数は末尾再帰型にできますか?考える

const U = f => f(f); 
 
    
 
const map = f => U(h => acc => ([head, ...tail]) => head === undefined 
 
? acc 
 
: h(h)([...acc, f(head)])(tail))([]); 
 
    
 
const xs = [1,2,3,4,5]; 
 
console.log(map(x => x * x)([1,2,3,4,5]));

、再帰呼び出しh(h)は、再帰関数の最後のアクションではありません。しかし、スタックが巻き戻されたときに起こることは、完成したアキュムレータがそれ以上の変更や操作なしで返されることです。 mapは私の期待どおりに再帰的ですか?

+0

を、私はこれが混乱 'map'の実装だと思います。一つの手続きで 'map'と' reduce'を組み合わせています。私は2つの別々の手順が 'map'の可読性を助けることを示すために[gist:u.js、y.js](https://gist.github.com/anonymous/6ccdd17b0b16f75bc38af2930ca6655f)を共有しています。私はまた、2つの実装がどのように比較されるかを示すために 'Y'を使って実装を行いました。あなたはおそらくこれを知っているでしょうが、 'Y'との唯一の違いは本当に' h(h) 'の代わりに' h'を適用することだけです。ああ、はい。さて、私たちは、テールコール除去を実装しているエンジンを待っています... – naomik

+0

ありがとう@naomik、私はあなたに絶対に同意します。これは 'map'を' reduce'から導出せずにどのように実装できるかという挑戦に過ぎませんでした。私はこれを公表するつもりはなく、カイルしたテールポジションのアプリケーションが私を困惑させた。 – ftor

+0

問題ありません**^_^** – naomik

答えて

2

再帰呼び出しh(h)

h(h)が再帰呼び出しではありません再帰関数の最後のアクションではありません。 …(tail)は再帰呼び出しであり、はい、末尾にあります。

これは、あなたがそのovercomplicated Uコンビネータ(あるいは少なくともすぐにYコンビネータを使用)ドロップすると、より明白かもしれません:

const map = f => { 
    const mapF = acc => ([head, ...tail]) => head === undefined 
    ? acc 
    : mapF([...acc, f(head)])(tail); 
    return mapF([]); 
}; 
+0

ありがとうございますが、 'U'は' f'を繰り返し渡す必要があり( 'h')、ブロックが必要です。 Btw、 '{} 'のような矢の名前はどうですか? – ftor

+0

私が暗示したように、あなたが気にしていた 'mapF'の宣言を行うために' Y'を使うことができます。しかし、それは本当に重要ではありません、私はこのシンタックスを少しだけ明確にしました。元のコードはちょうどテール再帰的なものです。簡潔なボディのない矢印は、単に矢印の機能です。 – Bergi

+0

ああ、私の場合、再帰呼び出しは、カルト関数の手続き型アプリケーションが終了したときに実行されます。私はそんな私です...私はそれを見たことがありません! – ftor

関連する問題