Results 1 to 12 of 12

Thread: Question about Lamda Expression

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2007
    Posts
    544

    Question about Lamda Expression

    vb.net Code:
    1. Sub Test()
    2.     Dim y As Integer = 10
    3.     Dim Lambda As Func(Of Integer, Integer) = Function(ByVal x) x + y
    4.     y = 20
    5.     Console.WriteLine(Lambda(5))
    6. End Sub

    So the method vb.net use to generate lamda expression is similar to C++ functor.

    So far so good.

    What value is displayed when you execute this function? If you said 25, you were spot on. Why 25? Well, the compiler captures and rewrites all of the free variables y to the closure's copy, like so:
    vb.net Code:
    1. Sub Test()
    2.     Dim Closure As New $CLOSURE_Compiler_Generated_Name$
    3.     Closure.y = 10
    4.     Dim Lambda = AddressOf Closure.Lambda_1
    5.     Closure.y = 20
    6.     Console.WriteLine(Lambda(5))
    7. End Function
    I still do not understand why Microsoft decide to change the second y=20 into closure.y=20?

    The first closure.y=10 make sense. In fact, if I were microsoft, a more normal way to generate the code will be to have a variable would be to do

    vb.net Code:
    1. Sub Test()
    2.     Dim Closure As New $CLOSURE_Compiler_Generated_Name$
    3.     y=10
    4.     Closure.y = y
    5.     Dim Lambda = AddressOf Closure.Lambda_1
    6.     'Closure.y = 20 Remove this line.
    7.     Console.WriteLine(Lambda(5))
    8. End Function

    Why Microsoft do it the microsoft way instead of the way that make more sense? The microsoft way is when y change value then the Lambda variable also change. It becomes a different function. Also what are the rules where microsoft will change y=10 into Closure.y=10?



    vb.net Code:
    1. Sub Test()
    2.     For I = 1 To 5
    3.         StartThread(Function() I + 10)
    4.     Next
    5. End Function

    Won't work properly because I keeps changing. What I think would happen is that thread may actually be started sometimes latter, say during doevents or latter.

    At that time I would have became 5 or 6 and all threads will simply print 15. Wouldn't happen if Microsoft do things the normal my way.

    http://msdn.microsoft.com/en-us/magazine/cc163362.aspx
    vb.net Code:
    1. Sub Test()
    2.     For I = 1 To 5
    3.         Dim x = I
    4.         StartThread(Function() x + 10)
    5.     Next
    6. End Function

    How the hell doing Dim x=i change anything?

    Microsoft compiler change all occurrence of I=1,2,3,4,5 into Closure.I=1,2,3,4,5

    Why microsoft don't do the same for x?
    Last edited by teguh123; Mar 2nd, 2011 at 02:57 AM.

  2. #2
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,714

    Re: Question about Lamda Expression

    With all this said, what exactly are you getting at in regards to a problem in your coding? If Lambda did not exists how would you tackle your problem?

    Also wonder what this is
    Dim Closure As New $CLOSURE_Compiler_Generated_Name$

  3. #3
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: Question about Lamda Expression

    Yea, you're splitting hairs. VB.NET isn't LISP.

    To answer your only question though, Dim x = i creates a new variable with i's value to pass onward to the Lambda. You're correct, there is the very real possibility that a function doesn't happen until the computer decides to start it because it's delegated and being invoked by another thread. It's in delegation until Windows decides to give it the process time to happen. It DOESN'T evaluate the Lambda until that delegate gets invoked though; it's still meta-code. If that Lambda were using the memory position of "I", then it runs the risk of "I" changing before the Lambda gets evaluated. Once the function gets invoked, only THEN is the Lambda evaluated.

    The necessity for this is when dealing with multi-threaded processing.
    Last edited by Jenner; Mar 2nd, 2011 at 09:37 AM.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  4. #4
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Question about Lamda Expression

    What you're stumbling upon is a powerful language feature called closures. To remove it would be to take much computational power out of lambda expressions. In this case, closures cause confusion and get in the way but this is but a simple example.

    I think John Skeet makes a good case for closures in this blog article. It concerns C# but VB .NET's support for lambdas is finally equivalent. It doesn't get exciting until the end:
    A different sort of combination comes when you feed the result of one delegate into another, or curry one delegate to create a new one. All sorts of options become available when you start thinking of the logic as just another type of data.
    I'd like to make a reasonable explanation for why closures need to exist, but I'm not quite experienced enough with functional programming to make the strongest case. Here's my attempt.

    Here's the first code snippet:
    Code:
    Sub Test()
        For I = 1 To 5
            StartThread(Function() I + 10)
        Next
    End Function
    This is a case where closures hurt because it's not what they were designed for. The value of I is enclosed, so all 5 threads return 15. Let's look at the second example and how it changes things:
    Code:
    Sub Test()
        For I = 1 To 5
            Dim x = I
            StartThread(Function() x + 10)
        Next
    End Function
    In this case, each lambda is enclosing x. Since x is scoped to the loop, each thread gets a *different* x. So in this case you'd get 11, 12, 13, etc. It's not the act of assigning a value to a variable that brings this about, it's the act of assigning unique variables. If you were to make a subtle change to that snippet, you'd be right back to getting 15 from all threads:
    Code:
    Sub Test()
        Dim x = 0
        For I = 1 To 5
            x = I
            StartThread(Function() x + 10)
        Next
    End Function
    In this case, there's only one x variable since it's not created each loop iteration. It behaves as if you used I in the lambda.

    That's a case where it's not useful; there's a case where it helps. It's the case where closures help that I'm not good at constructing; so far the examples I've come up with are quite complicated. I think that's the deal though: closures are powerful in complicated cases and it would be wrong to limit the power of lambda expressions to make smaller tasks easier.

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2007
    Posts
    544

    Re: Question about Lamda Expression

    Yap. I realized why putting dim x=i in the loop works.

    I was told a long time ago that in VB6, no matter where you put the dim statement, variables are always allocated at the beginning of the function. Not so in vb.net

    That's my first question actually.

    The way closure works is vb.net will make a special class and all local variables will be a member of that class. Which I think is quite an inefficient way to do so. I think a member of that closure class should change only when the delegate is created or assigned.

    So my second question is the design choice. Why Microsoft decided to change the member closure class every time the local variable change? Why not just once?

  6. #6
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: Question about Lamda Expression

    I don't really understand what you're trying to ask. Variables are defined by scope. A variable defined in a loop will be disposed upon next loop cycle. Sure there's a lot of allocation and deallocation of memory, but that's just the way a managed memory model works. It takes the drudgery out of having to worry about memory allocation and recovery.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2007
    Posts
    544

    Re: Question about Lamda Expression

    Not in vb6

    Anyway I think I understand what's going on.

  8. #8
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: Question about Lamda Expression

    Right, because VB6 isn't an object oriented language, nor a managed language.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  9. #9
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Question about Lamda Expression

    Quote Originally Posted by teguh123 View Post
    The way closure works is vb.net will make a special class and all local variables will be a member of that class. Which I think is quite an inefficient way to do so. I think a member of that closure class should change only when the delegate is created or assigned.

    So my second question is the design choice. Why Microsoft decided to change the member closure class every time the local variable change? Why not just once?
    Err, because if they did it the way you describe as an alternative, it wouldn't be a closure.

  10. #10
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Question about Lamda Expression

    Also, you're missing the trick that when the lambda expression changes the value, the local variable also get changed... it's a two way street.

    (Well, it's a no-way non-street because they're the same variable, but since we're talking about a mental model of two copies that get kept in sync...)

  11. #11
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Question about Lamda Expression

    Quote Originally Posted by teguh123 View Post
    The way closure works is vb.net will make a special class and all local variables will be a member of that class.
    Further, since you do actually seem interested in going into details, only local variables that are referenced in the lambda get made into fields of the generated class.

  12. #12
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Question about Lamda Expression

    If you're really interested in the nitty-gritty details, I highly recommend Jon Skeet's CLR via C#, particularly the 2nd edition. It devotes 2 or 3 full chapters to lambda delegates, espression trees, and their implementations and implications.

    All I can really say without summarizing that book is lambdas and closures work the way they do because if they worked any different they would not be able to do some very advanced things. F# is a great functional language but its adoption has been relatively slow because the C# compiler's (and likewise the VB .NET compiler's) implementation of lambdas brings many of the desirable features of functional programming to the table. It's true that lambdas sometimes make simple things harder, but I believe it's right to pick the correct tool for the job. You wouldn't use a drill press to punch holes in paper: you'd use a hole punch. So don't use lambdas for things they make harder.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width