K Combinator (C #, Scala)
Saya menggunakan K combinator di Ruby cukup sering, sebagian besar dalam lipatan ketika operasi lipat dilakukan melalui efek samping daripada nilai kembali, seperti dalam contoh ini:
some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1 }
Ini menghitung seberapa sering setiap elemen muncul di some_collection. Sayangnya, itu tidak benar-benar berfungsi, karena blok harus mengembalikan nilai baru akumulator pada setiap iterasi, tetapi dalam tugas Ruby mengevaluasi nilai yang diberikan.
Jadi, Anda harus mengembalikan nilai akumulator baru seperti ini:
some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1; acc }
Tetapi saya menemukan urutan eksplisit yang jelek dalam gaya fungsional-ish ini menggunakan lipatan. Combinator K (dipanggil Object#tapdalam Ruby) untuk menyelamatkan:
some_collection.reduce(Hash.new(0)) {|acc, el| acc.tap { acc[el] += 1 }}
Saya sudah melewatkannya beberapa kali di C # (kebanyakan karena beberapa alasan mutator pengumpul seperti List.Addreturn voidbukan this) dan Scala, jadi saya membawa sekitar ini:
namespace GenericExtensions
{
public static class GenericExtensions
{
public static T Tap<T>(this T o, Action<T> f)
{
Contract.Requires(o != null);
Contract.Requires(f != null);
f(o);
return o;
}
public static T Tap<T>(this T o, Action f)
{
Contract.Requires(o != null);
Contract.Requires(f != null);
f();
return o;
}
}
}
dan di Scala:
class Tap[T](o: T) {
def tap(f: T => Unit) = { f(o); o }
def tap(f: => Unit) = { f; o }
}
object Implicits { implicit def any2Tap[T](o: T) = new Tap(o) }
Fungsi Identitas (Ruby)
Sesuatu yang saya lewatkan di Ruby, adalah cara yang disebut dengan baik untuk mengakses fungsi identitas. Haskell menyediakan fungsi identitas dengan nama id, Scala dengan nama identity. Ini memungkinkan seseorang untuk menulis kode seperti:
someCollection.groupBy(identity)
Setara dalam Ruby adalah
some_collection.group_by {|x| x }
Tidak benar-benar menggulung lidah, bukan?
Cara mengatasinya adalah
IDENTITY = -> x { x }
some_collection.group_by(&IDENTITY)
ForEach (.NET)
Metode lain yang sangat hilang dalam C #:
namespace IEnumerableExtensions
{
public static class IEnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> xs, Action<T> f)
{
Contract.Requires(xs != null);
Contract.Requires(f != null);
foreach (var x in xs) f(x);
}
}
}