Quantcast

Maximum PC

It is currently Sat Oct 25, 2014 6:03 pm

All times are UTC - 8 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Delegation Delegating Delegates
PostPosted: Fri Jul 06, 2012 12:53 am 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
Since I recently posted that I wasn't very fond of static classes and static constructors in C#, I wanted to even out my C# programming karma by mentioning a language feature in C# that I find fairly interesting. C# includes a language feature known as delegation. Although I haven't used this language feature much myself, I have seen it used on a number of occasions in a fairly wide range of circumstances. The most common usage has been event handling associated with GUI components. This Sun Develop Network (SDN) whitepaper discusses why inner classes were chosen in favor of delegation in the Java language. While this is an interesting whitepaper and topic, I don't really want to get into the GUI component aspects.

I do like both the Wikipedia and MS examples of how to do multicast delegation in C#. Below is the example code from Wikipedia (Note -- I removed some of the whitespace).
Code:
void HowAreYou(string sender) {   Console.WriteLine("How are you, " + sender + '?'); }
void HowAreYouToday(string sender) {  Console.WriteLine("How are you today, " + sender + '?'); }

Notifier greetMe;
greetMe = new Notifier(HowAreYou);
greetMe += new Notifier(HowAreYouToday);

greetMe("Alfred");                      // "How are you, Alfred?"
                                        // "How are you today, Alfred?"

greetMe -= new Notifier(HowAreYou);
greetMe("Anastasia");                   // "How are you today, Anastasia?"


I can see this language feature being used in a number of interesting ways. For example, I might want to know the properties of a sequence of numbers. I could easily make a delegate with functions that inform me if a number is prime, relatively prime, perfect, Karprekar or any number of interesting things. Adding and removing functions can be handled at runtime; Modifying the delegate is as simple as += and -=. The possibilities seem to be fairly broad.

The one thing that I've noticed in the examples is that delegation seems to be most useful when you're working for side-effects (eg GUI, I/O, etc). I don't want anyone to think that this is function composition in which the result of one function is passed as input to another function. This is simply a convenient method of chaining together function/method calls.

As with many language features that I find interesting, I decided to see if I could implement a useful example in Common Lisp. I wrote a macro that creates three functions: one for calling the delegate, one for adding functions to the delegate, and one for removing old functions from the delegate. A closure is used to keep the delegate functions in a list. The delegate function simply iterates through the list calling each function in turn. I chose a macro implementation over a normal function implementation so that the functions are placed in the function namespace [Don't worry about that last statement if you're not a Lisp, Scheme, Ruby, Clojure type who understands the difference between a Lisp-1 and Lisp-2]. The CL macro code is also more general than the C# code. For example, you can have delegates that take one parameter, multiple parameters, a combination of parameters, and even parameters of different types (assuming the functions handle these calls properly).

Code:
;;Note - name, add-name and rem-name are the names of the functions that are created
;;(ie name would be equivalent to the delegate variable in C#, add-name to += and rem-name to -=)
;;Note2 - I could have written the macro so that add-name and rem-name done automatically (eg foo, add-foo, rem-foo),
;;but this would have complicated the macro code and I wanted it to be accessible to someone interested in learning macros
(defmacro make-delegate (name add-name rem-name &rest fns)
  `(let ((fn-list (list ,@fns)))                  ;The list closure
     (defun ,name (&rest params)                  ;The delegate
       (dolist (fn fn-list) (apply fn params)))
     (defun ,add-name (&rest fns)                 ;The += function
       (setf fn-list (append fn-list fns)))
     (defun ,rem-name (&rest fns)                 ;The -= function
       (setf fn-list (set-difference fn-list fns)))))

;;Single numeric parameter
(defun sine (n) (format t "sin(~d) = ~d~%" n (sin n)))
(defun cosine (n) (format t "cos(~d) = ~d~%" n (cos n)))
(defun tangent (n) (format t "tan(~d) = ~d~%" n (tan n)))
;;Mulitple numeric parameters
(defun add (&rest vals) (format t "Adds to ~d~%" (apply #'+ vals)))
(defun sub (&rest vals) (format t "Subs to ~d~%" (apply #'- vals)))

;;Example...
CL-USER> (make-delegate foo add-foo rem-foo #'sine #'cosine #'tangent)
CL-USER> (foo 1)
sin(1) = 0.84147096
cos(1) = 0.5403023
tan(1) = 1.5574077
CL-USER> (rem-foo #'tangent)
CL-USER> (foo 1)
sin(1) = 0.84147096
cos(1) = 0.5403023
CL-USER> (rem-foo #'cosine #'sine)
CL-USER> (add-foo #'add #'sub)
CL-USER> (foo 10 5 1)
Adds to 16
Subs to 4

Pretty cool stuff... =)
I'll add another post tomorrow on some uses of delegates in C# that I don't find very appealing.


Top
  Profile  
 
 Post subject: Re: Delegation Delegating Delegates
PostPosted: Fri Jul 06, 2012 12:46 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
In the domain of functional programming, C# programmers have used delegates to mimic some language features found in functional programming languages. This task from Rosetta Code illustrates the use of delegates to demonstrate a languages ability to pass a function as a function parameter (ie Higher-order function calls). This is an example of delegation that I DO NOT LIKE (Note - I condensed the number of lines below).
Code:
using System;  delegate int Func2(int a, int b);
class Program {
    static int Add(int a, int b)     {        return a + b;    }
    static int Mul(int a, int b)    {        return a * b;    }
    static int Div(int a, int b)    {        return a / b;    }
    static int Call(Func2 f, int a, int b)     {        return f(a, b);    }

    static void Main()    {
        int a = 6;        int b = 2;
        Func2 add = new Func2(Add);         Func2 mul = new Func2(Mul);         Func2 div = new Func2(Div);
        Console.WriteLine("f=Add, f({0}, {1}) = {2}", a, b, Call(add, a, b));
        Console.WriteLine("f=Mul, f({0}, {1}) = {2}", a, b, Call(mul, a, b));
        Console.WriteLine("f=Div, f({0}, {1}) = {2}", a, b, Call(div, a, b));
    }
}

First, I think this is a nearly perfect example of the over-use of syntax in an imperative languages. This is far too much code for something as trivial as passing a function. I can't imagine anyone writing code like this at work, on a meaningful project or for use with a library. It just isn't practical. Second, this technique suffers from a lack of generality. For example, I can't use this with any of the trig functions or concatenate two strings because the delegate Func2 only works with two parameters of type int and must return an int [Granted, this is bordering on a dynamic vs static typing issue, but let's just say Haskell is also statically typed w/o these problems (and not that this C# code couldn't be improved, I just choose it as an example that I didn't like)]. Third, and perhaps most importantly, I shouldn't have to use a delegate in order to pass a function -- that's backasswardsness. There is nothing in the Wikipedia article on delegation that mentions, "BTW, this is also a means for passing functions," because it stinks in this regard! I was going to add a Haskell or CL example, but it isn't even worth the additional space -- You simply pass the function as you would any other argument [ie (foo fn)]. From what I have seen delegation can be a useful technique for creating side-effects, but lacks the generality for doing functional programming (which isn't that surprising considering C# is a imperative language). </end rant>


Top
  Profile  
 
 Post subject: Re: Delegation Delegating Delegates
PostPosted: Fri Jul 06, 2012 12:58 pm 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5397
Because if you can find an easier, more concise way of doing something, you should just do it that way. :P

Anyway, there is only one time I ever use delegates: cross thread data access. However, you can't just call the delegate, you actually have to call Invoke(). If you try calling the delegate by itself, you'll just get a cross-thread exception.

I don't see a use for what MSDN describes the usage for delegates otherwise.

Then again most of my C# programs were basically "do some serial comms"


Top
  Profile  
 
 Post subject: Re: Delegation Delegating Delegates
PostPosted: Mon Jul 09, 2012 2:18 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
LatiosXT wrote:
Because if you can find an easier, more concise way of doing something, you should just do it that way. :P
In an ideal world, the best developers (based on merit) would determine the appropriate technologies to use for a given task. However, we both know that we don't live in that world. In my experience, it is either an administrative manager or some I've read two chapters of a software engineering book type that makes those calls. I was on several teams at Boeing and most of them made inappropriate language and tool choices were made for various half-baked reasons. Probably the worst offender was when the tech lead of the sat test sim team who decided to write half-ass XML parser in C instead of using Java to parse database delivery files. The reason... he simply didn't know any other languages, so _everything_ was done in C. Amazingly, he was such a bad C programmer that he probably wouldn't have been able to use a 3rd party library to do the job (Big company ideals... sit on your ass here long enough and we'll eventually promote you... you're a _senior developer_ now). His implementation was so bad that I secretly created my own xml parser using elisp inside of Emacs.

LatiosXT wrote:
Anyway, there is only one time I ever use delegates: cross thread data access. However, you can't just call the delegate, you actually have to call Invoke(). If you try calling the delegate by itself, you'll just get a cross-thread exception.
That's an interesting idea; I probably would never have considered using delegates with multiple threads. I'll take a look into this when I start playing with threads in C# in a few days. Is this related to what you were doing?

http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx


Top
  Profile  
 
 Post subject: Re: Delegation Delegating Delegates
PostPosted: Mon Jul 09, 2012 3:15 pm 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5397
I just use Invoke. To be honest, it's to make .NET not give me cross-thread exceptions since the only one I seem to encounter is when SerialPort.dataReceived gets called. When that happens, you're on the SerialPort thread, not the WindowsForm thread, so do anything in a WindowsForm object throws an exception. And actually looking at another project I did, you can also use delegates to make custom events.


Top
  Profile  
 
 Post subject: Re: Delegation Delegating Delegates
PostPosted: Tue Oct 23, 2012 1:09 pm 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
C# 4 and C# 5 really expounds on the notion of delegates. In fact, they really went above and beyond with Func<T1,T2,...TResult> and Action<T> types:

Code:
void mySelectMethod(Expression<Func<T, bool>> predicate) {
   // Use expression to build an expression tree or do some fun stuff
}


Have you played around with it? I'm a web developer so I don't really use delegates that much these days (I did back in the WebForms days), but Expession and Func are still widely used for me as I use them to build pretty generalized repository/service contexts.


Top
  Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

© 2014 Future US, Inc. All rights reserved.