K Combinator (C#, Scala)
I use the K combinator in Ruby quite often, mostly in folds when the folding operation is performed through a side effect rather than a return value, like in this example:
some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1 }
This counts how often each element occurs in some_collection
. Unfortunately, it doesn't actually work, since the block has to return the new value of the accumulator at each iteration, but in Ruby assignments evaluate to the assigned value.
So, you have to ecplicitly return the new value of the accumulator like this:
some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1; acc }
But I find such explicit sequencing ugly in this functional-ish style using folds. The K combinator (called Object#tap
in Ruby) to the rescue:
some_collection.reduce(Hash.new(0)) {|acc, el| acc.tap { acc[el] += 1 }}
I have already missed it a couple of times in C# (mostly because for some reason collection mutators such as List.Add
return void
instead of this
) and Scala, so I carry around this:
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;
}
}
}
and in 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) }
Identity Function (Ruby)
Something I am missing in Ruby, is a nicely named way to access the identity function. Haskell provides the identity function under the name of id
, Scala under the name of identity
. This allows one to write code like:
someCollection.groupBy(identity)
The equivalent in Ruby is
some_collection.group_by {|x| x }
Doesn't exactly roll off the tongue, does it?
The fix is
IDENTITY = -> x { x }
some_collection.group_by(&IDENTITY)
ForEach (.NET)
Another sorely missing method in 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);
}
}
}