Writing a simple function in C#

J

Jon Harrop

I am trying to learn C# and .NET programming in general but I am finding it
very hard going. To start with, I'd like to translate some trivial
functions from other languages that I am familiar with into C#.

Here is a simple function in OCaml that nests "n" applications of "f"
around "x", with "n" defaulting to "n=2":

let rec nest ?(n=2) f x = if n=0 then x else nest ~n:(n-1) f (f x)

For example, "nest f x" gives "f(f(x))" and "nest ~n:3 f x"
gives "f(f(f(x)))".

I am unable to write this elegantly in C#. This is the best I've come up
with and it doesn't even support partial application (currying):

class Program
{
abstract class Nest<T>
{
int n;

public Nest()
{
n = 2;
}

public abstract T f(T x);

public T Apply(T x)
{
while (n > 0)
{
x = f(x);
--n;
}

return x;
}

public int N
{
get
{
return n;
}

set
{
n = value;
}
}
}

class NestTwice : Nest<int>
{
public override int f(int x)
{
return 2 * x;
}
}

static void Main(string[] args)
{
NestTwice nestTwice = new NestTwice();
nestTwice.N = 3;
System.Console.WriteLine(nestTwice.Apply(2));
}
}

So I've implemented the higher-order function "nest" as an abstract base
class "Nest" that you must derive from and override the "f" member
function. The optional argument "n" in the OCaml is implemented as a
mutable property "N" with its default value set to 2 by the constructor.

The "NestTwice" class derives from the "Nest" class, specialized to the
type "T=int", and implements the "f" member such that it doubles its
integer argument.

The main program then constructs an object of the class "NestTwice", sets
its property "N" to 3, overriding its default value of 2, and calls
the "Apply" method to compute the equivalent of "nest n f".

Needless to say, there are many aspects of this that I am not happy with!

1. Can the handling of the function argument "f" be written more elegantly
(but still generically) in terms of delegates? I'd like to replace my
C++-style abstract "Nest" class with something like:

public static T nest<T>(int n, Delegate<T, T> f, x) {
while (n>0) { x=f(x); --n; }
return x;
}

2. My handling of optional arguments is hideous. Can this be done without
mutation, i.e. without first setting the option to its default and then
altering it to the specified value?

3. Is there a simpler way of getting the return value of a function with
optional arguments than making up a "standard" member called "Apply" and
giving it the non-optional arguments after the optional ones have settled
to their true values?

4. Can the "Nest" class be derived from a statically-typed delegate class?

5. Did I miss something fundamental in C#: can any of this be written more
succinctly or elegantly in C#?

6. Are there any tools that can help by autogenerating code like this? Are
there any .NET languages that can do this as elegantly as OCaml?

My motivation is largely to write better F# code rather than C# but both
languages have the same implementation of optional arguments, so the F#
equivalent of the OCaml one-liner also entails a page of classes, mutation
etc.
 
J

Jon Skeet [C# MVP]

<snip>

Rather than answer each of the questions in turn, here's how I'd
implement it:

delegate T Mutator<T>(T t);

static T Mutate<T>(Mutator<T> mutator, T initial, int times)
{
for (int i=0; i < times; i++)
{
initial = mutator(initial);
}
return initial;
}

static T Mutate<T>(Mutator<T> mutator, T initial)
{
return Mutate(mutator, initial, 2);
}

Points to note:
1) Use a generic delegate instead of overriding. Apart from
anything else, this makes life a lot simpler when anonymous methods
are available
2) There's no real need for a separate class with state
3) Use overloading to provide optional parameters
4) Use a for loop instead of while to be idiomatic
5) Boy is it shorter ;)


Your complete program (which doesn't use the default number of
iterations) becomes:

delegate T Mutator<T>(T t);

class Test
{
static T Mutate<T>(Mutator<T> mutator, T initial, int times)
{
for (int i=0; i < times; i++)
{
initial = mutator(initial);
}
return initial;
}

static void Main()
{
int result = Mutate(delegate(int x) { return x*2; }, 2, 3);
System.Console.WriteLine (result);
}
}
 
F

Fred Mellender

Something like:

namespace Foo

{

public partial class Foo : Form

{

public delegate T Funct<T>(T x);



private void startButton_Click(object sender, EventArgs e)

{

int s = apply(delegate(int x) { return x +5; },

1, 4);

}



public T apply<T>(Funct<T> funct, T arg, uint timesApply)

{

if (timesApply <= 1)

return funct(arg);

else return (apply(funct,

apply(funct, arg, timesApply-1), 1));

}

}

}



wherein the function of adding 5 to an argument is applied 4 times, to the
argument 1, in the method startButton_Click.



However, this does not address optional parameters, which I do not
understand. If the intent is to to default the timesApply to (say 2), you
could define another apply with only 2 parameters, which just invokes the
one with 3 parameters, passing "2" as the third argument. If the intent is
to have the delegate, Funct, have optional arguments, but of differing types
then I don't see that you can do this since C# is strongly typed. You could
define the delegate to take a list of parameters, all of the same type
(possibly Object), I suppose. I don't understand point 3. Perhaps I
addressed points 4 and 5 to some extent. As for point 6, C# does not have a
macro feature, so cannot generate code. Some, but not nearly all, of this
functionality can be duplicated at runtime via generics.



Since all functions in C# must be in some class, it does not map to a purely
functional language. However, the class Foo is arbitrary, and I don't see
that you need to subclass it (but it probably this has something to do with
optional parameters, which I don't understand). Note that Foo itself is not
a generic class. That would give you another level of genericness, but I
don't see what purpose it would serve.



Perhaps this helps; sorry if I have missed some of your points.







Jon Harrop said:
I am trying to learn C# and .NET programming in general but I am finding
it
very hard going. To start with, I'd like to translate some trivial
functions from other languages that I am familiar with into C#.

Here is a simple function in OCaml that nests "n" applications of "f"
around "x", with "n" defaulting to "n=2":

let rec nest ?(n=2) f x = if n=0 then x else nest ~n:(n-1) f (f x)

For example, "nest f x" gives "f(f(x))" and "nest ~n:3 f x"
gives "f(f(f(x)))".

I am unable to write this elegantly in C#. This is the best I've come up
with and it doesn't even support partial application (currying):

class Program
{
abstract class Nest<T>
{
int n;

public Nest()
{
n = 2;
}

public abstract T f(T x);

public T Apply(T x)
{
while (n > 0)
{
x = f(x);
--n;
}

return x;
}

public int N
{
get
{
return n;
}

set
{
n = value;
}
}
}

class NestTwice : Nest<int>
{
public override int f(int x)
{
return 2 * x;
}
}

static void Main(string[] args)
{
NestTwice nestTwice = new NestTwice();
nestTwice.N = 3;
System.Console.WriteLine(nestTwice.Apply(2));
}
}

So I've implemented the higher-order function "nest" as an abstract base
class "Nest" that you must derive from and override the "f" member
function. The optional argument "n" in the OCaml is implemented as a
mutable property "N" with its default value set to 2 by the constructor.

The "NestTwice" class derives from the "Nest" class, specialized to the
type "T=int", and implements the "f" member such that it doubles its
integer argument.

The main program then constructs an object of the class "NestTwice", sets
its property "N" to 3, overriding its default value of 2, and calls
the "Apply" method to compute the equivalent of "nest n f".

Needless to say, there are many aspects of this that I am not happy with!

1. Can the handling of the function argument "f" be written more elegantly
(but still generically) in terms of delegates? I'd like to replace my
C++-style abstract "Nest" class with something like:

public static T nest<T>(int n, Delegate<T, T> f, x) {
while (n>0) { x=f(x); --n; }
return x;
}

2. My handling of optional arguments is hideous. Can this be done without
mutation, i.e. without first setting the option to its default and then
altering it to the specified value?

3. Is there a simpler way of getting the return value of a function with
optional arguments than making up a "standard" member called "Apply" and
giving it the non-optional arguments after the optional ones have settled
to their true values?

4. Can the "Nest" class be derived from a statically-typed delegate class?

5. Did I miss something fundamental in C#: can any of this be written more
succinctly or elegantly in C#?

6. Are there any tools that can help by autogenerating code like this? Are
there any .NET languages that can do this as elegantly as OCaml?

My motivation is largely to write better F# code rather than C# but both
languages have the same implementation of optional arguments, so the F#
equivalent of the OCaml one-liner also entails a page of classes, mutation
etc.
 
J

Jon Harrop

Jon said:
Points to note:
1) Use a generic delegate instead of overriding. Apart from
anything else, this makes life a lot simpler when anonymous methods
are available
Ingenious.

2) There's no real need for a separate class with state

Yes. That was a C++ism.
3) Use overloading to provide optional parameters

I'm concerned that this doesn't scale to having more optional arguments.
4) Use a for loop instead of while to be idiomatic
Right.

5) Boy is it shorter ;)

Wonderful. Thanks for the help!
 
M

Moty Michaely

Can you elaborate on this?

I've read this description of the pattern:

http://www.exciton.cs.rice.edu/JAvaResources/DesignPatterns/command.htm

and I can't see how it is relevant. Is this for when you have a set of
optional arguments that are common to several different functions?

Hi,

When you need to pass common arguments (not necessarily optional) you
can encapsulate the arguments with a class and implement a function in
that class..

For example (very simple one, you can always elevate it to much more
complex one):

To copy a file we can do this:
void CopyFile(string src, string dest)

Or we can encapsulate the CopyFile operation to a FileOperation class:

class FileOperationContext
{
string source;
string destination;

public FileOperationContext(string source, string destination)
{
this.source = source;
this.destination = destination;
}

}

abstract class FileOperation {
FileOperationContext context;

public FileOperation(FileOperationContext context)
{
this.context = context;
}

void Operate();
}

class FileCopy : FileOperation
{
public FileCopy (FileOperationContext context) : base(context)
{ }

override Operate() {
System.IO.File.Copy(context.source, context.destination);
}
}

You can of course not implement methods and just use the class as an
argument list..
for example:

void CopyFile(FileOperationContext context) {
System.IO.File.Copy(context.source, context.destination);
}

void MoveFile(FileOperationContext context) {
System.IO.File.Move(context.source, context.destination);
}

etc....

Hope this clears things up.. =)

Moty
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top