Wednesday, July 1, 2009

Passing a function as a parameter to another function

You may have wanted to do this. Its actually very important and useful.

We use to pass variables to functions, but passing functions to functions is really a purely object oriented mechanism and really saves you a lot of work.

I'm going to write this example in VB.NET

The Example
Lets say you have a function that somehow loops through all your devices in your house.

You want to create a function that turns off all devices.
Another function that turns on all devices
Perhaps a function that will maintain your devices.

If you want to do that, you'll properly end up duplicating the loop code in all the three functions.


So here is the solution.

Lets first create our mother function, the one which loops through the devices.

Public Sub LoopThroughDevices()
Dim pDevice As IDevice
For Each pDevice In Home.Devices
'---Do Something
Next
End Sub


Now we will create the 3 function, a function that turn a device off, on and maintain

Public Sub Deviceoff(ByVal pDevice As IDevice)
pDevice.off()
End Sub

Public Sub DeviceOn(ByVal pDevice As IDevice)
pDevice.on()
End Sub

Public Sub MaintainDevice(ByVal pDevice As IDevice)
pDevice.Maintain()
End Sub


If we can now pass each function to our LoopThroughDevices function the problem is solved.

We can do this by declaring a Delegate that have the same signature as our 3 functions

Private Delegate Sub DoActiononDevice(ByVal pDevice As IDevice)


Then we will modify our LoopThroughDevices function

'Notice I declared a variable of type DoActiononDevice which is technically a function
Public Sub LoopThroughDevices(ActionFunction as DoActiononDevice)
Dim pDevice As IDevice
For Each pDevice In Home.Devices
'---Call the function
ActionFunction (pDevice)
Next
End Sub



We're done, we just need to call the functions

'To Turn all devices off
LoopThroughDevices (AddressOf Deviceoff)


'To Turn all devices on
LoopThroughDevices (AddressOf Deviceon)


'To Maintain all devices
LoopThroughDevices (AddressOf MaintainDevice)


We used the AddressOf keyword to send-in the function as a variable, it will get a pointer of the address of the function for the LoopThroughDevices to execute it.

Enjoy.


6 comments:

  1. This is a lot easier in more dynamic languages like JavaScript and Perl. It's even used commonly in their standard libraries.

    See JavaScript's setInterval, which takes either a function name or an actual function object.

    See Perl's map, grep and sort, which all take anonymous functions (though many users of these functions don't even realize they are passing functions).

    ReplyDelete
  2. @While1dan
    Thanks for dropping by,
    exactly, this is much more easier in Javascript as I know, i didn't use perl (i hope i will learn it soon)

    thanks for the great addition and valuable comment ...

    VB.NET isn't the language i suppose to use to describe this example i guess, I just used it for simplicty...

    Adding a perl example on how to do this i will be great ;) so readers can get the most benefit out of this post


    Thanks friend

    ReplyDelete
  3. map is a good example. It goes through an array, passes each item to a function you provide and returns a new array containing the results.

    @original = (1, 34, 2, 25, 13, 3);
    @doubles = map({ return $_ * 2 }, @original);

    Once this has run, @doubles will contain (2, 68, 4, 50, 26, 6).

    The first parameter to map is a function, the second is an array. Each item of the array is passed to the function as the parameter $_.

    By the way, the parentheses, comma, and return are unnecessary:

    @doubles = map { $_ * 2 } @original;

    Because of that, many programmers think it's just a weird language construct and don't realize they are passing a function to another function.

    ReplyDelete
  4. @I loved that language ! its simple man
    This is perl?

    Thanks alot man for your great example..

    do you have any good tutorials

    ReplyDelete
  5. Perlmonks is a great website for Perl help. I haven't looked at their tutorials, but they're probably pretty good. http://perlmonks.org/?node=Tutorials

    I have learned a lot from perldoc http://perldoc.perl.org/

    ReplyDelete
  6. Thanks @while1dan for the great references..

    ReplyDelete

Share your thoughts