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#tap
dalam 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.Add
return void
bukan 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);
}
}
}