Lambda expressions: Dangerous Madness

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • raylopez99

    Lambda expressions: Dangerous Madness

    Took a look at all the fuss about "lambda expressions" from Jon
    Skeet's excellent book "C# in Depth". Jon has an example, reproduced
    below (excerpt) on lambda expressions.

    My n00b take: it's like SQL and those 'high level' languages that try
    to be too clever by half and pack a lot of syntax in as short a space
    as possible. Like Egyptian hieroglyphics, like Chinese, like those
    non-alphabet languages, it's just way too much information in too
    short a space. Sure, writing a program with this syntax will reduce
    your source code from 100 pages to 10, but at a cost of readability.

    But what do I know? I only have a couple months real experience in
    the language. Don't listen to me.

    RL

    "To try and outstrip each other in the arms race, or to expect to win
    a nuclear war, is dangerous madness." - Leonid Brezhnev

    this is equivalent: from C#1.0
    ArrayList products = Product.GetSamp leProducts(); //fills arraylist
    (fanciful example)

    foreach (Product X in products) {
    if (X.price 10m) { Console.WriteLi ne(X);} } [suffix m =
    decimal]

    now redo in C#2 mode:

    ArrayList products = Product.GetSamp leProducts(); //fills arraylist

    Predicate <Productproduct s test = delegate (Product p) {return
    p.Price 10m;} ;
    List<Productmat ches = products.FindAl l(test);

    Action<Productp rint = delegate(Produc t p) {Console.WriteL ine(p);};
    matches.ForEach (print);

    which is actually equivalent to (lambda expressions):
    ArrayList products = Product.GetSamp leProducts(); //fills, as before

    foreach (Product product in products.Where (p =>p.Price 10))
    {Console.WriteL ine(product);}

    //Jon humorously states "the combination of the lambda expression
    putting the test in just the right place and a well-named method means
    we can almost read the code out loud and understand it without even
    thinking" HA HA HA! Right. I guess beauty is in the eye of the
    beholder.

    RL

  • Jon Skeet [C# MVP]

    #2
    Re: Lambda expressions: Dangerous Madness

    raylopez99 <raylopez99@yah oo.comwrote:
    Took a look at all the fuss about "lambda expressions" from Jon
    Skeet's excellent book "C# in Depth". Jon has an example, reproduced
    below (excerpt) on lambda expressions.
    >
    My n00b take: it's like SQL and those 'high level' languages that try
    to be too clever by half and pack a lot of syntax in as short a space
    as possible. Like Egyptian hieroglyphics, like Chinese, like those
    non-alphabet languages, it's just way too much information in too
    short a space. Sure, writing a program with this syntax will reduce
    your source code from 100 pages to 10, but at a cost of readability.
    I'd say they greatly add to readability, actually. Yes, you need to get
    used to them first, but that's no reason to avoid them.

    I think there's actually a shock value in how much you're able to
    express in so little code - when you're used to verbose code, it can be
    alarming to see how compact it can really be when you have suitable
    language features. That's a perception issue though - not a
    maintainability issue.
    But what do I know? I only have a couple months real experience in
    the language. Don't listen to me.
    Many powerful features look too hard to start with. Give them a chance
    - when you're familiar with them, lambda expressions are *wonderful*.
    What would you rather write:

    products.OrderB y(product =product.Price)

    or

    products.OrderB y(PriceComparis on)

    .... later on in code (second version only) ...

    int PriceComparison (Product first, Product second)
    {
    return first.Price.Com pareTo(second.P rice);
    }

    ? I know which one *I* find clearer and easier to modify when
    necessary.
    //Jon humorously states "the combination of the lambda expression
    putting the test in just the right place and a well-named method means
    we can almost read the code out loud and understand it without even
    thinking" HA HA HA! Right. I guess beauty is in the eye of the
    beholder.
    I wasn't kidding. Read the code out loud - it does exactly what it
    says. That's great for readability.

    --
    Jon Skeet - <skeet@pobox.co m>
    Web site: http://www.pobox.com/~skeet
    Blog: http://www.msmvps.com/jon.skeet
    C# in Depth: http://csharpindepth.com

    Comment

    • Peter Morris

      #3
      Re: Lambda expressions: Dangerous Madness

      products.OrderB y(product =product.Price)

      or

      result.Rows.Sor t(
      delegate(StockL evelRow row1, StockLevelRow row2)
      {
      return row1.BrandName. CompareTo(row2. BrandName);
      }
      );


      No thanks, I'll take the lambda :-)

      Comment

      • Marc Gravell

        #4
        Re: Lambda expressions: Dangerous Madness

        For code maintenance, less is usually better... I completely agree with
        Jon that it makes the code much more transparent.

        As an example, for a side-project I'm working on some code that does a
        reasonable amount of work with delegates (and similar functionality) -
        but I also want the code to compile on C# 2. It is so, so hard going
        bacck to delegates; all that "delegate {ArgType x, ...}" etc truly
        interrupts my thought process. I'm not thinking "delegate ..." - I'm
        thinking about the interesting bit to the right. I've chosen to write
        the delegates using lambdas, and then when I have them working,
        back-port them to anon-methods (for C# 2compatibility) - this takes me a
        lot less time than working any other way.

        I've also done a lot of work with "expression s"; now, expressions are
        horribly complex beasts. If you've had to write them the long-hand way,
        you will understand both *why* they are so compilicated, but also how
        painful it is to do. Getting the compiler to do it for you from a very
        terse and easy to follow line is just breathtaking, and I am truly
        amazed at how well it works.

        Marc

        Comment

        • Christopher Ireland

          #5
          Re: Lambda expressions: Dangerous Madness

          Peter Morris wrote:
          No thanks, I'll take the lambda :-)
          Makes you wonder why on earth you'd want to implement anonymous delegates in
          a compiler without also implementing lambda expressions at the same time. I
          understand that's the way one language has gone recently .. what was it
          called .. del, delp ... nah, I can't remember <g>.

          --
          Thank you,

          Christopher Ireland

          "If a man who cannot count finds a four-leaf clover, is he lucky?"
          Stanislaw J. Lec

          Comment

          • raylopez99

            #6
            Re: Lambda expressions: Dangerous Madness

            On Aug 14, 3:12 am, "Peter Morris" <mrpmorri...@SP AMgmail.comwrot e:
            products.OrderB y(product =product.Price)
            >
            or
            >
               result.Rows.Sor t(
                 delegate(StockL evelRow row1, StockLevelRow row2)
                 {
                  return row1.BrandName. CompareTo(row2. BrandName);
                 }
                );
            >
            No thanks, I'll take the lambda :-)
            To each their own. I like the longer delegate version better. The
            "CompareTo" is a hoary feature that goes back to the days of Pascal (I
            recall seeing it in a programming book).

            And, as Jon points out in his book (I may be mistaken about this
            however, but I saw it briefly and I think I'm right), the second
            'verbose' version _actually_ does a sort, where as the first "lambda"
            version is a sort of "virtual sort" (no pun intended) where the actual
            data structure is not sorted after calling the lambda version. Now
            that may be exactly what you want, but, it may not be. So ultimately
            you might end up doing the verbose sort anyway.

            RL

            Comment

            • Pavel Minaev

              #7
              Re: Lambda expressions: Dangerous Madness

              On Aug 14, 8:52 pm, raylopez99 <raylope...@yah oo.comwrote:
              And, as Jon points out in his book (I may be mistaken about this
              however, but I saw it briefly and I think I'm right), the second
              'verbose' version _actually_ does a sort, where as the first "lambda"
              version is a sort of "virtual sort" (no pun intended) where the actual
              data structure is not sorted after calling the lambda version.  Now
              that may be exactly what you want, but, it may not be.  So ultimately
              you might end up doing the verbose sort anyway.
              As written, this is correct, but List<T>.Sort() is eager, and can be
              called with a lambda as well. And, of course, one can also explicitly
              work around LINQ deferred execution by using ToList() on the resulting
              IEnumerable.

              Personally, I find that I use lambdas whenever I'm dealing with pure
              single-expression functions, and anonymous delegates when my functions
              have side-effects (and the main purpose of them is those side-effects,
              not the value returned - typically, those are event handlers, or
              signalling callbacks). So I do this:

              list.Sort((x, y) =x - y);

              But I also do this:

              button.Click +=
              delegate(object sender, EventArgs e)
              {
              ...
              }

              stream.BeginRea d(
              buffer,
              offset,
              count,
              delegate(IAsync Result ar)
              {
              ...
              },
              null);

              So, functional style -lambdas & type inference, imperative style ->
              anonymous delegates & explicit types. I can't clearly formulate my
              reasoning for doing so, but it boils down to readability - I find
              expression lambdas with side-effects, especially when they return void
              (such as x =Console.WriteL ine(x)) concealing the side-effect-unfree
              nature of the code, and I don't like the syntax of statement lambdas
              at all.

              Comment

              • Jon Skeet [C# MVP]

                #8
                Re: Lambda expressions: Dangerous Madness

                raylopez99 <raylopez99@yah oo.comwrote:
                On Aug 14, 3:12 am, "Peter Morris" <mrpmorri...@SP AMgmail.comwrot e:
                products.OrderB y(product =product.Price)
                or

                   result.Rows.Sor t(
                     delegate(StockL evelRow row1, StockLevelRow row2)
                     {
                      return row1.BrandName. CompareTo(row2. BrandName);
                     }
                    );

                No thanks, I'll take the lambda :-)
                To each their own. I like the longer delegate version better. The
                "CompareTo" is a hoary feature that goes back to the days of Pascal (I
                recall seeing it in a programming book).

                And, as Jon points out in his book (I may be mistaken about this
                however, but I saw it briefly and I think I'm right), the second
                'verbose' version _actually_ does a sort, where as the first "lambda"
                version is a sort of "virtual sort" (no pun intended) where the actual
                data structure is not sorted after calling the lambda version. Now
                that may be exactly what you want, but, it may not be. So ultimately
                you might end up doing the verbose sort anyway.
                Well, there are alternatives there anyway. For instance, I have a class
                in MiscUtil which builds a Comparison<Tfro m a Func<T,TKey- which
                means you can still use a concise syntax even when sorting in place.

                --
                Jon Skeet - <skeet@pobox.co m>
                Web site: http://www.pobox.com/~skeet
                Blog: http://www.msmvps.com/jon.skeet
                C# in Depth: http://csharpindepth.com

                Comment

                • Barry Kelly

                  #9
                  Re: Lambda expressions: Dangerous Madness

                  Christopher Ireland wrote:
                  Peter Morris wrote:
                  >
                  No thanks, I'll take the lambda :-)
                  >
                  Makes you wonder why on earth you'd want to implement anonymous delegates in
                  a compiler without also implementing lambda expressions at the same time.
                  Lambda *expressions* in C# are just that, expressions. Lambda
                  statements, on the other hand, can have limitations in terms of type
                  inference. You can end up with something very similar to an anonymous
                  method, in the worst case:

                  (ParamType1 arg1, ParamType 2 arg2) =>
                  {
                  foo();
                  bar();
                  baz();
                  return frobnitz(arg1, arg2);
                  }

                  In this case, I don't think one has gained much by moving from the
                  anonymous delegate syntax to the lambda statement syntax.
                  I
                  understand that's the way one language has gone recently .. what was it
                  called .. del, delp ... nah, I can't remember <g>.
                  Yes, Delphi. I work on the Delphi compiler, and I've implemented
                  anonymous methods just recently. We didn't implement lambdas because:

                  (a) it's too much work for one release - our parser relies heavily on
                  full type information being available, and needs to be rejigged to be
                  more compatible with a type-inference approach, and

                  (b) the direction we want to go in for native code is using code blocks
                  as arguments for parallelism purposes, more than LINQ.

                  -- Barry

                  --

                  Comment

                  • Barry Kelly

                    #10
                    Re: Lambda expressions: Dangerous Madness

                    Pavel Minaev wrote:
                    signalling callbacks). So I do this:
                    >
                    list.Sort((x, y) =x - y);
                    Beware of overflow: this is not a good comparison function. E.g. see:

                    using System;
                    class App
                    {
                    static void Main()
                    {
                    int a = int.MaxValue - 3;
                    int b = int.MinValue + 3; // so a b, right?
                    Console.WriteLi ne("a = {0}, b = {1}, a b = {2}", a, b, a b);
                    Console.WriteLi ne(a - b); // so this is positive, right?
                    // a - b = -7 =oops!
                    }
                    }
                    stream.BeginRea d(
                    buffer,
                    offset,
                    count,
                    delegate(IAsync Result ar)
                    {
                    ...
                    },
                    null);
                    This manual continuation-passing style cries out for a machine
                    translation. I've still got this one on my todo list...

                    -- Barry

                    --

                    Comment

                    • Barry Kelly

                      #11
                      Re: Lambda expressions: Dangerous Madness

                      Marc Gravell wrote:
                      I've also done a lot of work with "expression s"; now, expressions are
                      horribly complex beasts. If you've had to write them the long-hand way,
                      you will understand both *why* they are so compilicated, but also how
                      painful it is to do. Getting the compiler to do it for you from a very
                      terse and easy to follow line is just breathtaking, and I am truly
                      amazed at how well it works.
                      I'm not. The compiler has already done the work of the code to tree
                      transformation for compilation purposes; converting that into an
                      equivalent object construction expression is trivial.

                      -- Barry

                      --

                      Comment

                      • Jon Skeet [C# MVP]

                        #12
                        Re: Lambda expressions: Dangerous Madness

                        On Aug 15, 2:59 am, Barry Kelly <barry.j.ke...@ gmail.comwrote:
                        This manual continuation-passing style cries out for a machine
                        translation. I've still got this one on my todo list...
                        Have a look at what the CCR team did with iterator blocks for CPS.
                        It's really neat...

                        Jon

                        Comment

                        • Pavel Minaev

                          #13
                          Re: Lambda expressions: Dangerous Madness

                          On Aug 15, 5:59 am, Barry Kelly <barry.j.ke...@ gmail.comwrote:
                            stream.BeginRea d(
                              buffer,
                              offset,
                              count,
                              delegate(IAsync Result ar)
                              {
                                ...
                              },
                              null);
                          >
                          This manual continuation-passing style cries out for a machine
                          translation. I've still got this one on my todo list...
                          What kind of translation do you mean here?

                          Comment

                          • Carlos

                            #14
                            Re: Lambda expressions: Dangerous Madness

                            The main problem I have with the main post is that RL is missing the point
                            of Lambda Expressions. If you want to maintain state while passing a
                            function pointer you clearly have to look at a functional style of
                            programming and lambda expressions are a clear sign of a (math) functional
                            programming language, just like true recursiveness and things like tuples
                            but I guess that would result in *dangerous madness* as well.

                            What frightens me is that people seem to have forgotten the roots of
                            programming with User Interfaces, the structure is simple, you have WM
                            Messages, we catch them in event handlers and do something with them. Then
                            you have your code, this code needs to be clean and correct, to test its
                            correctness you will need to have defined what goes in and what comes out.
                            Lambda expressions not only help readability, but they force you to use a
                            single method call *only* where you need it, no more *F12 - Go to definition
                            I hope I find the implementation in the right place*...Functi onal elements
                            in your declarative code are just, well, good practice.


                            Comment

                            • raylopez99

                              #15
                              Re: Lambda expressions: Dangerous Madness

                              On Aug 15, 12:39 am, "Carlos" <defa...@defaul t.defaultwrote:
                              The main problem I have with the main post is that RL is missing the point
                              of Lambda Expressions. If you want to maintain state while passing a
                              function pointer you clearly have to look at a functional style of
                              programming and lambda expressions are a clear sign of a (math) functional
                              programming language, just like true recursiveness and things like tuples
                              but I guess that would result in *dangerous madness* as well.
                              Well Carlos, bone up on these topics and get back to us with a summary
                              of what you lerned:



                              http://en.wikipedia.org/wiki/Continuation ("Continuati ons are the
                              functional expression of the GOTO statement, and the same caveats
                              apply. While many believe that they are a sensible option in some
                              special cases such as web programming, use of continuations can result
                              in code that is difficult to follow. In fact, the esoteric programming
                              language Unlambda includes call-with-current-continuation as one of
                              its features solely because of its resistance to understanding." )

                              and last but not least, showing great minds (like Ray Lopez's) think
                              alike, a blog entry from 2005 on why Lambda expressions in C# suck:


                              But don't let me dissuade you from using Lambda expressions (aka
                              glorified GOTO statements). As pointed out in the above, it gives
                              programmers a steeper learning curve, which means people already
                              familiar with lambda expressions will have a leg up on the competition
                              that doesn't understand how to read these expressions.

                              And that makes the programmer more powerful (to his employers). At
                              the cost of clarity and program efficiency of course, but since when
                              has that ever been a goal?

                              RL <1,2,3<--there's a tuple for you.

                              Comment

                              Working...