Friday, October 03, 2008

Who loves lamdas?

I finally started a project where I can use all the new fanciness. How would you process a list of names so that each name is printed out 'i' times?

int i = 5;
IEnumerable<string>() names = new List<string>() { "Alan" };
names.ForEach (n => i.Times().Apply(j => Console.WriteLine(n)));

All your lambdas are belong to us!

14 comments:

Anonymous said...

Please tell me you're not actually writing code like that. I'd hate to be the one who has to maintain it after you're gone.

Lambdas are great, but they should be used sparingly.

RednaxelaFX said...

Hi,

ForEach() would have been a good name, but if your wrote your own version that doesn't return void, it's not gonna keep the semantics of Array.ForEach<T>() and List<T>.ForEach(), both of which return void and thus stops method chaining.
That's why a few people who's done almost the same uses the name Process() or the like, which returns IEnumerable<T> to allow the calls to be further chained, like:

list.Process( i => Console.WriteLine( i ) )
    .Where( i => 0 == i % 2 );

But there's a pitfall if you're using IEnumerable<T> like this: the whole query doesn't execute until MoveNext() is called for the first time. So you'd have to force a query to execute with some other calls, like:

list.Process( i => Console.WriteLine( i ) )
    .ToList( )
    .Where( i => 0 == i % 2 );

Not pretty, though.

If you're interested in reading exotic lambda stuff, you might like this post I wrote a few days ago: http://rednaxelafx.javaeye.com/blog/248317
It's in Chinese, but the code says it all. The post is about emulating local variables and statements with lambdas, which would be possible to be converted into Expression trees. It's nothing near production code stuff, but I'm sure it's fun to push the limits of lambda.

- RednaxelaFX

Chris Howie said...

Honestly I would not use .ForEach there. Then again it took me about two minutes just to unwrap that one statement in my head. Try this:

foreach (var n in names)
i.Times().Apply(j => Console.WriteLine(n));

Much easier to read. Note that any use of delegates like this will result in a loop over a call to a function pointer. This operation cannot be easily or safely optimized.

What would be nicer is either a language construct "do ... n times" or an IEnumerable<object> that returns null for every element, but provides n elements:

static IEnumerable<object> Times(int n)
{
for (int i = 0; i < n; i++)
yield return null;
}

As well as a construct "for (x)" where x : IEnumerable, which would iterate and not even query the enumerable for a value, effectively discarding it. Then we have:

foreach (var n in names)
for (Times(i))
Console.WriteLine(n);

Which would you rather maintain?

David said...

In Haskell:

let i = 5
names = ["Alan"]
mapM_ (mapM putStrLn . replicate i) names

RednaxelaFX said...

@Chris

The method call syntax takes some getting used to, but if the maintainer knows other languages that allow functional style of programming, he/she would have no trouble with code like this. Anyone familiar with Ruby would be very familiar with such syntax, not to mentions real functional languages like Haskell and ML families.

With upcoming technologies like PLINQ, we might see more and more looping code written in method call syntax rather than for/foreach loop statements. It's more declarative, and give the runtime more freedom to do optimizations such as parallelization.

public static class System.Linq.ParallelEnumerable {
    public static void ForAll<T>(
        this IParallelEnumerable<T> source, Action<T> action);
    ... the other standard query operators ...
}

Amber said...

o me, the legibility problem is in the variable 'i'. Simply replace that with the literal 5, will you:)

I prefer to be verbose in cases like this. Howver, I *never in my life* have to write code that does f for any i:I repeated n times. The f will always be defined in a way just a little bit smarter than just do that 5 times. When does *that* come in handy?

Perhaps in printing the banner to your 19k2 Bulletin Board Server hahahahaha

Lennie De Villiers said...

Hi, Here is the ForEach method for C++:

http://codepad.org/v7oRd5jM

Alan said...

@Anonymous: Well, there's no reason why I shouldn't write code like this. It's less prone to error. I heard the same arguments when generics came out. "Don't abuse generics, it's too complex to maintain". Of course, you shouldn't look at any of my MonoTorrent code then. It's filled with anonymous delegates. Though personally i find it makes the code much easier to understand.

@Amber: Yeah, i could've used the literal '5', but I wanted to demonstrate a point that I could execute something an arbitrary number of times really easily.

@Chris: Well, since i'm only starting with lambdas, i want to do as much as possible in as few lines as possible ;) Yeah, the line is complicated, but it's AWESOME!

bart said...

It's funny to see people getting so excited about stuff which does exist for 50 years now!

(mapc #'(lambda(name)
(dotimes(i 5)
(format t "~A" name)))
names)

which could be translated into

mapc(names, (n =>
doTimes(5,
() => Console.WriteLine(n))));

or names.mapc ... if you want.
It's a pitty I can not put
(dotimes(5,Console.WriteLine(n))

Bart

Takis said...

Lennie De Villiers:

I found your for_each definition a bit weird, as your for_each wasn't doing the iterating. And, you limited the type of containers you can iterate over to vectors, while you can get it to work for other containers rather easily:

template <typename T>
void for_each(T &v, void (*apply)(typename T::value_type &))
{
for (typename T::iterator i = v.begin(); i!=v.end(); i++)
apply(*i);
}

Ofcourse, there's no real point in implementing this as it is already available in STL :-)

smallawei said...

免費視訊,煙火,煙火工廠,視訊,正妹視訊,真愛密碼,真愛密碼,煙火秀,煙火圖片,衣蝶,衣蝶,AV女優,AV女優,
煙火批發,小泉彩,小泉彩,情趣用品,鞭炮,live119論壇,蜂炮,視訊

酒店上班請找艾葳 said...

艾葳酒店經紀公司提供專業的酒店經紀, 酒店上班小姐,八大行業,酒店兼職,傳播妹,或者想要打工兼差打工,兼差,八大行業,酒店兼職,想去酒店上班, 日式酒店,便服店,制服酒店,ktv酒店,禮服店,整天穿得水水漂漂的,還是想去制服店日領上班小姐,水水們如果想要擁有打工工作、晚上兼差工作兼差打工假日兼職兼職工作酒店兼差兼差打工兼差日領工作晚上兼差工作酒店工作酒店上班酒店打工兼職兼差兼差工作酒店上班等,想了解酒店相關工作特種行業內容,想兼職工作日領假日兼職兼差打工、或晚班兼職想擁有鋼琴酒吧又有保障的工作嗎???又可以現領請找專業又有保障的艾葳酒店經紀公司!

艾葳酒店經紀是合法的公司工作環境高雅時尚,無業績壓力,無脫秀無喝酒壓力,高層次會員制客源,工作輕鬆,可日領現領
一般的酒店經紀只會在水水們第一次上班和領薪水時出現而已,對水水們的上班安全一點保障都沒有!艾葳酒店經紀公司的水水們上班時全程媽咪作陪,不需擔心!只提供最優質的酒店上班,酒店上班,酒店打工環境、上班條件給水水們。心動嗎!? 趕快來填寫你的酒店上班履歷表

水水們妳有缺現領、想要兼職、有缺錢的煩腦嗎?想到日本留學缺錢嗎?妳是傳播妹??想要擁有高時薪又輕鬆的賺錢,酒店和,假日打工,假日兼職賺錢的機會嗎??想實現夢想卻又缺錢沒錢嗎!??
艾葳酒店台北酒店經紀招兵買馬!!徵專業的酒店打工,想要去酒店的水水,想要短期日領,酒店日領,禮服酒店,制服店,酒店經紀,ktv酒店,便服店,酒店工作,禮服店,酒店小姐,酒店經紀人,
等相關服務 幫您快速的實現您的夢想~!!

gaohui said...

Have you noticed ed hardy Clothing that she is spending time with ed hardy sale one person in particular ed hardy and they seemed to come from ed hardy UK nowhere. When you ask how she ed hardy cheap knows them she becomes aloof and ed hardy Clothes disinterested. Is there someone's house ed hardy store she seems to be always going to? This edhardy.com could spell something is wrong with the christian audigier sale relationship. Is she taking trips, possibly day ed hardy dresses trips or small vacations without you? If ed hardy Polos she was doing this before you even ed hardy sandals got married or dated, then it may be okay, but if it is a recent ed hardy Jackets development then you may have problems.

marketing online valencia said...

This won't really have effect, I consider like this.

Hit Counter