0

我的目標是創建一個自定義映射函數,首先需要過濾列表以保留,例如,在調用每個項目上提供的函數之前,只有偶數項目。我確實需要將curried函數和第一個參數作爲函數,而不是列表。我相信簽名看起來是這樣的:(a -> b) -> [a] -> [b]用於生成更高階函數的習語拉姆達?

當然有很多方法可以做到這一點。這是我第一次嘗試的樣子。

var isEven = x => x % 2 === 0; 

var filterEvensMap = R.curry((fn, items) => R.map(fn, R.filter(isEven, items))); 

filterEvensMap(R.negate, [1,2,3,4]); // [-2, -4] 

然而,由於上述使用匿名函數與fnitems「膠水參數」,我不知道這是Ramda旨在使用方式。

下面我介紹了另一種方式來做到這一點。這似乎更多的是拉姆達的精神,但我不確定我是否過於複雜。

var filterEvensMap = R.compose(
    R.flip, 
    R.uncurryN(2) 
)(R.compose(
    R.flip(R.map), 
    R.filter(isEven) 
)); 

我是否過度使用多個撰寫和uncurryN?有沒有更實用的方法來實現這一目標?根據你的經驗,這有什麼關係嗎?

在此先感謝。

回答

2

如果您發現Haskell簽名有用,您可能會發現這個point-free generatorsource)也有用。如果你想簡化的表達可以進入哈斯克爾相當於你的JS代碼:

filterEvensMap = \fn items -> map fn (filter isEven items) 

,它會給你一個免費點相當於:

filterEvensMap = (. filter isEven) . map 

然後翻譯回用Ramda JS來:

var filterEvensMap = R.curry(R.compose(R.compose(R.filter(isEven)), R.map)) 

在你的經驗,什麼關係呢?

我會去最可讀的表達式,在這種情況下,可能是原始表達式。無點是有趣的,可以在某些地方增加清晰度,但它也可以大大降低可讀性,或者至少可以理解。

+0

嗨,謝謝你的提示,pointfree.js看起來真的很有幫助。儘管在OP中的預期行爲與從無點Haskell表達式導出的Ramda表達式之間存在輕微的不匹配:過濾需要發生在原始的vals上,而不是映射的vals上。以下是顯示不同之處的鏈接:http://goo.gl/KVX4Kv。我對Haskell語法並不熟悉,所以我仍然試圖找出問題所在。 – Lopatin

+0

哦,我犯了一個錯誤,它應該是'compose(pipe(filter(f)),map)',但它不會在Ramda出於某種原因。我的猜測是,自動壓縮和可變數組合/管道混亂的事情,但你可以看到它在香草JS在這裏工作:https://jsfiddle.net/xs56h0vb/ – elclanrs

+0

再次感謝!我正在評價答案,因爲我擁有繼續編程所需的一切。我現在意識到,我在這個問題中提到的是一個名爲「pointfree」的概念,並且它並不總是有必要寫出一個無點表達式,只是因爲它是可能的。但是,當我想要獲得樂趣的時候,有一個pointfree.js – Lopatin