This guide covering closures in Ruby by Paul Cantrell is very insightful. It's written as a Ruby script to be both executed and read. Thanks to Ruby Inside for linking to it.
Blog Archive
Labels
- csharp
- ruby
- visual studio
Tuesday, July 18
Thursday, June 22
Ruby's Enumerable mixin again
On the topic of Ruby's Enumerable mixin, it might be interesting to
compare them to C# 2.0's Array/List<T> methods—static for Array, instance for List<T>—and 3.0's Standard Query
Operators (System.Query namespace).
In the cases where C# does not support the method, I'd recommend following the link to the ruby docs. There are some rather interesting methods, and a lot can be learned from looking at what other languages support. In fact, some of these methods (each_slice, each_with_index) might be worth implementing as extension methods in C# (a trivial excercise left to the reader).
| Ruby Enumerable | C# 2.0 Array/List<T> methods* | C# 3.0 System.Query |
|---|---|---|
all?all?
{ |obj| block } |
bool TrueForAll(Predicate<T> match) |
bool All<T>(this IEnumerable<T> source,
Func<T, bool> predicate) |
any?any?
{ |obj| block } |
bool Exists(Predicate<T> match) |
bool Any<T>(this IEnumerable<T> source,
Func<T, bool> predicate) |
collect
{ |obj| block }map
{ |obj| block} |
List<TOutput> ConvertAll<TOutput>(Converter<T,
TOutput> converter) |
IEnumerable<S> Select<T, S>(this
IEnumerable<T> source, Func<T, S> selector) |
detect(ifnone
= nil) { |obj| block }find(ifnone
= nil) { |obj| block } |
T Find(Predicate<T> match) |
T First<T>(this IEnumerable<T> source, Func<T,
bool> predicate)T FirstOrDefault<T>(this IEnumerable<T> source,
Func<T, bool> predicate) |
each_cons(n)
{...} |
||
each_slice(n)
{...} |
||
each_with_index
{ |obj, index| block } |
||
to_aentries |
T[] ToArray<T>(this IEnumerable<T>
source)List<T> ToList<T>(this IEnumerable<T>
source) |
|
find_all
{ |obj| block }select
{ |obj| block } |
List<T> FindAll(Predicate<T> match) |
IEnumerable<T> Where(this IEnumerable<T> source,
Func<T, bool> predicate) |
grep(pattern) |
FindAll could certainly specify a predicate that
applied a regular expression against each item of the collection. |
same for Where. |
include?(obj) |
bool Contains(T item) |
|
inject(initial)
{ |memo, obj| block } |
U Aggregate<T, U>(this IEnumerable<T> source, U
seed, Func<U, T, U> func) |
|
max
/ minmax
/ min
{ |a, b| block } |
T Max/Min<T>(this IEnumerable<T> source),
etc. Note that while there are a few overloads for this method, it
looks like the delegates passed in merely provide value extraction. I
don't see an overload where you can provide your own
IComparer<T> (which is what the second Ruby method
does) |
|
partition
{ |obj| block } |
||
reject
{ |obj| block } merely returns the collection of the
inverse of find_all
/ select |
||
sortsort
{ |a, b | block }sort_by
{ |obj| block } |
Sort()Sort(IComparer<T> comparison) |
OrderedSequence<T, K>
OrderBy/OrderByDescending/ThenBy/ThenByDescending(OrderedSequence<T>
OrderBy/OrderByDescending/ThenBy/ThenByDescending( |
to_set |
||
zip(arg,
...)zip(arg,
...) { |arr| block } |
Enumerable mixin
I really like Ruby's Enumerable mixin. Methods like each_slice and each_with_index can inspire some really straightforward, elegant solutions.
Porting such a library to C# is trivial, but having to use the 2.0's verbose delegate syntax detracts from the coolness a bit. Using 3.0's lambda expressions on the other hand…
Ruby and C#
Ruby
numbers = [1, 2, 3, 4, 5]
is_even = proc { |n| (n.modulo 2).zero? }
(numbers.map {|n| "#{n} #{is_even[n] ? 'is' : 'is not'} even"}).each {|summary| puts summary}
C# 3.0
int[] numbers = {1, 2, 3, 4, 5};
Predicate<int> isEven = n => n % 2 == 0;
Array.ForEach(numbers, n => Console.WriteLine("{0} {1} even", n, isEven(n) ? "is" : "is not"));
or if you prefer...
Array.ForEach(numbers, n => Console.WriteLine("{0} {1} even", n, isEven(n) ? "is" : "is not"));numbers.Each(n => Console.WriteLine("{0} {1} even", n, isEven(n) ? "is" : "is not")); // elsewhere public static class EnumerableExtensions { public static void Each<T>(this IEnumerable<T> collection, Action<T> action) { foreach (T item in collection) action(item); } }
C# and Ruby
Searching Google for C# Ruby sure yields some interesting articles. I hope to add to the mix in the coming weeks as I play around with the C# 3.0/LINQ May CTP.
Stay tuned…