Kết hợp K (C #, Scala)
Tôi sử dụng bộ kết hợp K trong Ruby khá thường xuyên, chủ yếu là các nếp gấp khi thao tác gấp được thực hiện thông qua hiệu ứng phụ thay vì giá trị trả về, như trong ví dụ này:
some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1 }
Điều này tính tần suất mỗi phần tử xảy ra trong some_collection
. Thật không may, nó không thực sự hoạt động, vì khối phải trả về giá trị mới của bộ tích lũy ở mỗi lần lặp, nhưng trong các bài tập Ruby đánh giá giá trị được gán.
Vì vậy, bạn phải hoàn toàn trả về giá trị mới của bộ tích lũy như thế này:
some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1; acc }
Nhưng tôi thấy trình tự rõ ràng như vậy xấu xí trong phong cách chức năng này bằng cách sử dụng các nếp gấp. Người kết hợp K (được gọi Object#tap
trong Ruby) để giải cứu:
some_collection.reduce(Hash.new(0)) {|acc, el| acc.tap { acc[el] += 1 }}
Tôi đã bỏ lỡ nó một vài lần trong C # (chủ yếu là vì một số lý do đột biến bộ sưu tập như List.Add
trở lại void
thay vì this
) và Scala, vì vậy tôi mang theo điều này:
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;
}
}
}
và ở 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) }
Chức năng nhận dạng (Ruby)
Một cái gì đó tôi đang thiếu trong Ruby, là một cách được đặt tên độc đáo để truy cập chức năng nhận dạng. Haskell cung cấp chức năng nhận dạng dưới tên của id
, Scala dưới tên của identity
. Điều này cho phép một người viết mã như:
someCollection.groupBy(identity)
Tương đương trong Ruby là
some_collection.group_by {|x| x }
Không chính xác lăn lưỡi, phải không?
Cách khắc phục là
IDENTITY = -> x { x }
some_collection.group_by(&IDENTITY)
ForEach (.NET)
Một phương pháp cực kỳ thiếu khác trong 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);
}
}
}