Alois Kraus

blog

  Home  |   Contact  |   Syndication    |   Login
  106 Posts | 8 Stories | 294 Comments | 162 Trackbacks

News



Article Categories

Archives

Post Categories

Image Galleries

Programming

After all this hype around C# 3.0 where we will get LINQ, lambda expressions and many other thing I thought that it would be useful to have a deeper look at functional programming languages like F#. At Microsoft quite many people are fond of the  Functional Programming style which did influence the design of C# 3.0. Many language architects there have  Haskell background which could explain the renaissance of these "old" concepts. So what's the deal with the functional approach? It does basically force you to think in a twisted way where the problem is straight solved by calling a function which does call another function and so on. Lets assume that you want to get the list of all members of all types which are contained in the assemblies that are currently loaded into your AppDomain (to look at the problem this way is the twisted part) you could write for example in F# simply:

// Assign allMembers the result of our "calculation"
let allMembers = System.AppDomain.CurrentDomain.GetAssemblies()
|> Array.to_list |> List.map (fun a -> a.GetTypes()) |> Array.concat
|> Array.to_list |> List.map (fun ty -> ty.GetMembers()) |> Array.concat
// Print them out
do Array.foreach allMembers ( fun memberInfo -> printf "\n%s" memberInfo.Name)

If you want to understand what this little code fragment really does and how it can be rewritten I recommend the post from Robert. A more comprehensible version in C# code would look like this:

        public List<MemberInfo> GetAllMembers()

        {

            Assembly [] allAssemblies = AppDomain.CurrentDomain.GetAssemblies();

            List<Type> allTypes = new List<Type>();

 

            foreach(Assembly assembly in allAssemblies)

            {

                allTypes.AddRange(assembly.GetTypes());

            }

 

            List<MemberInfo> allMembers = new List<MemberInfo>();

            foreach( Type t in allTypes )

            {

                allMembers.AddRange( t.GetMembers() );

            }

 

            return allMembers;

        }

You see much more lines to write but in a way that (most) people can understand in shorter time. Let's rewrite it in a more functional way with C# 2.0, it does already provide some functional features (anonymous delegates, iterators, coroutines = yield) today:

        public List<MemberInfo> GetFunctionMembers()

        {

            List<MemberInfo> allMembers = new List<MemberInfo>();

 

            Array.ForEach(AppDomain.CurrentDomain.GetAssemblies(), delegate(Assembly assembly)

            {

                Array.ForEach(assembly.GetTypes(), delegate(Type type)

                {

                    allMembers.AddRange(type.GetMembers());

                });

            });

 

            return allMembers;

        }

Anonymous delegates and the new static Array functions are very nifty features in .NET 2.0  that allow a compact functional style programming already today. The same ForEach, .. constructs are also available for generic Lists as instance functions.

New Array (generic list) Helper Functions Of .NET 2.0

The following table does contain the new static array helper functions which are also available as instance functions of generic lists.

Array Function/Delegate Explanation F# Counterpart
delegate void Action<T>( T obj )
Action delegate used by some Array helper functions. Does not return anything. -
delegate bool Predicate<T>( T obj )
Predicate delegate which is used by some array helper functions. Does return true if the input element does match something. -
delegate int Comparison<T>(T x, T y)
Comparison delegate which is used by Array.Sort.
Return
negative  if  x < y
         0   if x = y
positive  if x > y
-
ReadOnlyCollection<T> AsReadOnly<T> 
(T[] array)
Returns a read only collection wrapper of the input collection. -
ConstrainedCopy (
sourceArray,
sourceIndex,
destinationArray,
destinationIndex,
length
)
Generic copy where you can copy only parts of an array to another location inside another array. -
TOutput[] ConvertAll<TInput,TOutput> (
TInput[] array,
<TInput,TOutput> converter
)
Apply a conversion function to all members of the input array and return the converted array values as new array. Array.map
bool Exists<T> (
T[] array,
Predicate<T> match
)
Return true if the called Predicate delegate did return true for an array element. Array.exists
T Find<T> (
T[] array,
Predicate<T> match
)
Return the first matching element when the Predicate delegate does return true for an array element. Array.find
T[] FindAll<T> (
T[] array,
Predicate<T> match
)
Return an array with all matching elements for which the Predicate delegate did return true. Array.filter
T FindLast<T> (
T[] array,
Predicate<T> match
)
Return the last matching element for which the Predicate delegate did return true. -
void ForEach<T> (
T[] array,
Action<T> action
)
Execute the Action delegate for every element of the array. Array.map
void Resize<T> (
ref T[] array,
int newSize
)
Finally you can resize an array! But keep in mind that a new array of the specified size is created and the elements are copied into the new one. -
void Sort<T> (
T[] array,
Comparison<T> comparison
)
Sort the array according to the comparison results of the supplied Comparison delegate. Array.sort
bool TrueForAll<T> (
T[] array,
Predicate<T> match
)
Return true if for all array elements the Predicate delegate does return true. Array.for_all

As you can see you do not have to wait until C# 3.0 to program (nearly) functional style with .NET 2.0. Of course F# has many more functions to offer but the list of C# is growing.

C# Function/Delegate Call Performance
This functional thing C# with delegates and anonymous methods is nice. But how does it perform?
I did some measurements which did compare how much one integer add operation (+one integer array access) is slowed down when we take into account the function calling overhead. I did take the numbers from my P4 with 3,0 GHz.

Function Call Performance

The blue bars of this diagram is the time needed for our work (integer add) and the red part is the associated overhead. As we can see here the delegate call is only 20% slower than a normal (not inlined) function call which is quite impressive. This is what I would expect after reading Eric Gunnersons very good article about this topic. What is surprising is that there is no difference of a virtual function call compared to a not inlined function call. The penalty we pay here is that the JITer is not able to inline a virtual function call whereas my "normal" function would have been inlined if I did not prevent it by adding the 

[MethodImpl(MethodImplOptions.NoInlining)]

attribute above the function. By the way the generated IL code for a "normal" function call and a virtual function call is the same: "callvirt" instruction. Why is for every function call a virtual function call IL opcode emitted by the C# compiler? Answer: Runtime safety. The C# team did decide to use callvirt for every function call because it does add an additional null check if the object we are calling into is null. If it is null a NullReferenceException is thrown. We could use a normal "call" then no exception would be thrown but we will break somewhere inside the function when the (still null) this pointer is needed to dereference e.g. a member variable. 


Caching The C#  Way

A very practical example of  caching is the following scenario. Suppose you have a function that is costly and does generate from some input value/s an an output value which takes a long time to calculate/create (e.g. a database connection when the connection string is the input). You want to speed up things for some colleagues which do open the database connection at every database server access just because it is so easy to do. To make caching happen a wrapper around the costly function is needed which does return the already created database connection when it was opened already. Since I am dealing in my blog very often with the Enterprise Library I use here the Caching Application Block of course ;-).

To cache a function of the form SqlConnection CreateConnection(string connString) you need to write only one additional line of code:

            Function<string, SqlConnection> CachedConnection = FunctionCacher.EntlibFuncCacher<string, SqlConnection>(CreateConnection);

            SqlConnection cachedConn = CachedConnection("connection String");



 

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.Practices.EnterpriseLibrary.Caching;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;


 

        public static Function<TParam, TReturn> EntlibFuncCacher<TParam, TReturn>(Function<TParam, TReturn> func)

        {

            CacheManagerFactory factory = new CacheManagerFactory(ConfigurationSourceFactory.Create());

            CacheManager cache = factory.CreateDefault();

 

            return delegate(TParam arg)

            {

                TReturn result = default(TReturn);

 

                string key = arg.GetHashCode().ToString();

 

                if( cache.Contains(key) )

                {

                    result = (TReturn) cache.GetData(key);

                }

                else

                {

                    result = func(arg);

                    cache.Add(key, result);

                }

                return result;

            };

        }

The code above does wrap the original delegate into a new one which does first check if the result of the function has been computed before. If yes the cached value is returned otherwise the costly operation is performed, the result put into the cache and returned to the caller. This caching function was inspired by Sriram Krishan very good article: Lisp is sin. Sriram does use in his function a simple hash table which is very fast but will sooner or later overflow your memory. The Enterprise Library Caching Application Block allows us to upgrade to a real caching solution.

Caching the F# Way

Let's see if the F# version can do it better:

#r @"<YourPathToit>\Microsoft.Practices.EnterpriseLibrary.Common.dll";;
#r @"
<YourPathToit>\Microsoft.Practices.EnterpriseLibrary.Caching.dll";;
open System
open Microsoft.Practices.EnterpriseLibrary.Common.Configuration
open Microsoft.Practices.EnterpriseLibrary.Caching

let CacheFunction f =
   let source = ConfigurationSourceFactory.Create()   in // Get configuration
   let CacheFactory = new CacheManagerFactory(source) in // Create Cache Factory
   let Cache = CacheFactory.CreateDefault()           in // Get configured default cache from Entlib

   // define a new function that takes an arbitrary type as input argument
   fun (x) ->
   (  
       let strKey = sprintf "%d" (hash x) in // get (hopefully) unique hash value
       if( Cache.Contains( strKey )) then    // check if the cache does already contain it
       (
         unbox(Cache.GetData(strKey))        // unbox (static cast to return type of f(x)) and return the cached object
       )
       else                                  // otherwise calculate result of original function and store it in cache
       (
         let result = f x in                 // do lengthy calculation
         Cache.Add(strKey,result);           // store result in cache
         result                              // return calculated result
       )
   )

////////////////////////////
// Usage of CacheFunction
////////////////////////////
let TestFunc (x:string) = String.Format("New Value: {0}",x) // This is our function we want to cache
let CachedFunc = CacheFunction TestFunc                     
// create cached function               

The F# version is a bit shorter and contains more comments than the F# version. Apart from this it does look similar except for the nicer anonymous function definition which does not result in the creation of an anonymous delegate. It is educational to see what Reflector thinks about our F# version when he does translate it back to C# code.

The CacheFunction does create the local variables as expected and passes it to the F# version of an anonymous delegate class which does not derive from MultiCastDelegate.

public static FastFunc<A, B> CacheFunction<A, B>(FastFunc<A, B> f)
{
IConfigurationSource source1 = ConfigurationSourceFactory.Create();
CacheManager manager1 = new CacheManagerFactory(source1).CreateDefault();
return new File1.CacheFunction@14<A, B>(f, manager1);
}

Each F# delegate receives the local variables via reference so he can access the variables of the outer function.
public CacheFunction@14(FastFunc<A, B> f0, CacheManager Cache0)
{
this.f0 = f0;
this.Cache0 = Cache0;
}

The Invoke method does contain our actual caching logic which we did write inside our anonymous function.
public override B Invoke(A x)
{
// calculate hash code of x and stringify it
string text1 = Pervasives.sprintf<FastFunc<int, string>>((PrintfPrimitives.Format4<FastFunc<int, string>, Unit, string, string>)
new
PrintfPrimitives.Format4<FastFunc<int, string>, Unit, string, string>("%d", (FastFunc<object, FastFunc<int, string>>)
new
File1.strKey@16())).Invoke(Pervasives.hash<A>(x));
if (this.Cache0.Contains(text1))
{
return Pervasives.unbox<B>(this.Cache0.GetData(text1)); // return cached value
}
B local1 = this.f0.Invoke(x); // call original function
this.Cache0.Add(text1, (object) local1); // add it to the cache
return local1; // return calculated result
}

What I found interesting is that the F# unbox command is nothing else than our good old static cast. Things are falling into places at last.
public static A Microsoft.FSharp.MLLib.Pervasives.unbox<A>(object x)
{
return (A) x;
}


Curried Functions F# / C#

In functional languages it is common to create for a function f(x,y,z,...) some helper functions g(x=0,y,z,...) which do call f with some default argument (x=0 in the case of g). This feature does remind me quite strong to default function arguments in C++. Of course there is more to it since in a functional language the parameter itself can be a function which is exchanged at runtime to support e.g. different sorting algorithms quite easy. 

In F# it is easy to define a function calc which does add the input arguments (thanks for the comments DeeJ, I am still learning). The trick is that the argument can be anything even another function which does return the correct type. You can try this code sample with fsi.exe the F# interpreter.

>let calc x y = x + y;;
Now we can curry the List.map function with our calc function which does add to every element 2.
>let List.map (calc 2) [1;2;3];;
If we execute the curried function we will get the desired result:
val it : int list = [3; 4; 5]

Another example of function currying the the Array.map function which is the same as the Array.ConvertAll function. Let's compare the two:

Expected Output: 
SOME
LOWERCASE
WORDS

F# version:

let someArray = [|"some"; "lowercase"; "words"|]
let ToUpperArray(inArr) = inArr |> Array.map (fun y -> y.ToUpper())
let bigArray = ToUpperArray(someArray)
do bigArray |> Array.foreach (fun x -> printf "\n%s" x)

Lists are immutable in F# and defined by ["aaa";bb"]. This notation is rather confusing for beginners since I expect this definition to be the definition of an array. Mutable arrays are defined by using the [| |] notation which allows us to use them in the old fashioned way. Thanks for Don pointing this out. To declare an anonymous(unnamed) function we can use the fun keyword to supply a conversion function for the array. In the next line we call our ToUpperFunction which does execute on all element's of the array the anonymous functions. After that we are ready to print the converted array to the console.

C# version: 

        static public string[] ToUpperArray(string[] arr)

        {

            return Array.ConvertAll<string, string>(arr, delegate(string input)

            {

                return input.ToUpper();

            });

        }

 

        static public void DoArrayStuff()

        {

            string [] someArray = { "some", "lowercase", "words" };

            string[] upperCaseArray = ToUpperArray(someArray);

 

            // print them out

            Array.ForEach<string>(upperCaseArray,delegate(string input)

            {

                Console.WriteLine("{0}",input);

            });

        }

Even with the anonymous delegates syntax we have much more overhead when we need to define a new function in C#. This time the F# version does win the price for the shorter and more concise (aka) readable code. Speed is another thing I did not yet measure because it is not fair to compare a released product against a research language. Please note that anonymous delegates do create a new delegate instance inside your method where you define them. If e.g. the ToUpperArray method is called very often with small arrays the cost for the creation of the delegate instance must be considered. Normally it is a better idea to create the delegate the old fashioned way as a member variable of your class instance.

Coroutines in C#

This extension of the traditional function is in its most general form perhaps a bit too much for most programmers since it does violate nearly every programming principle like encapsulation and information hiding. C# 2.0 does provide this feature by adding the yield keyword, although in a very limited form as enumerator. Note: You must use yield return xxx; in C# since this way no pre C# 2.0 code was broken if somebody did use the reserved yield keyword despite better knowledge. In a foreach loop the following things happen:

  1. Get the Enumerator via the IEnumerable<T> interface of the the input object.
  2. Call MoveNext on the enumerator and store the current value of T in a local variable.
  3. The code inside the foreach loop can use the populated local variable now.
  4. Call Dispose on the enumerator.

The following sample does illustrate this behavior:
Expected Output:
Int: 1
Int: 2
Int: 3

        public IEnumerable<int> EnumInt()

        {

            yield return 1;

            yield return 2;

            yield return 3;

        }

 

        public void IterateWithForEach()

        {

            foreach (int i in EnumInt())

            {

                Console.WriteLine("Int: {0}", i);

            }

        }

 

        public void IterateByHand()

        {

            IEnumerator<int> iterator = EnumInt().GetEnumerator();

 

            int i;

            while (iterator.MoveNext())

            {

                i = iterator.Current;

                Console.WriteLine("Int: {0}", i);

            }

            iterator.Dispose();

        }

The yield return statement is executed n-times where the function is entered in the same state as it was left of the previous yield return statement. This powerful feature does allow you to write goto's in a much nicer way ;-). You can do anything in your function you would like to. The most useful things I can imagine are

  • Smart collections where you supply helper enumerators that enumerate e.g. in alphabetical order plus a filter over you string array.
  • Start asynchronous operations on each element of a collection and return the delegate that will finish its work later.
  • Usage in algorithms 
  • ...

Coroutines C# Example

Google has created a small but powerful web service called Google API  where you can query for search results for check phrases for spelling errors. This is an excellent opportunity to put our new knowledge about coroutines at work. The scenario is for example a word editor where you underline the wrong words with red color. Since spell checking is expensive we want to do it asynchronously so the user can continue with his work without any interruption.

  • Put an array of phrases into a spell checker
  • Get the corrected phrases back not necessarily in the order they were given.

To achieve this "not necessarily in the order they were given"  part we use asynchronous I/O with delegates to call the Google web service for each phrase and collect the responses asynchronously. Each corrected phrase is then put along with the original phrase into an array that can be queried by an external call in a synchronous way. We do only block as long as one response from Google is collected and return it immediately.

The consumer of our SpellChecker can call us synchronously:

        public void Spellchecker()

        {

            string [] phrases = { "seperate pece", "no hype", "micosoft" };

            foreach(KeyValuePair<string,string> result in GetCorrectedPhrases(phrases) )

            {

                Console.WriteLine("Phrase: {0} becomes {1}",result.Key,result.Value);

            }

        }

Expected Output:
Phrase: no hype becomes no hype
Phrase: seperate pece becomes separate peace
Phrase: micosoft becomes microsoft

The infrastructure behind this real world example is a little longer

        GoogleSearchService myGoogle = new GoogleSearchService(); // .NET powered by Google ;-)

        public KeyValuePair<string,string> GetCorrectSpelling(string phrase)

        {

            // do the Google spell check synchronously

            string newphrase = myGoogle.doSpellingSuggestion(licenseKey, phrase);

            if( String.IsNullOrEmpty(newphrase))

                newphrase = phrase;

 

            // Key is the original phrase, Value is the googled phrase

            KeyValuePair<string, string> ret = new KeyValuePair<string, string>(phrase, newphrase);

            return ret;

        }

 

        delegate KeyValuePair<string, string> SpellingCheck(string phrase);

        IEnumerable<KeyValuePair<string, string> > GetCorrectedPhrases(string[] phrases)

        {

            SpellingCheck checker = GetCorrectSpelling; // Create delegate instance

            int PendingSpells = 0; // +1 for each request, -1 for each completed request

            // Results are collected as pairs where key is the old phrase and value the checked one

            List<KeyValuePair<string,string>> results = new List<KeyValuePair<string,string>>();

 

            foreach (string phrase in phrases) // Start spell checking for all phrases at once -> very scalable

            {

                System.Threading.Interlocked.Increment(ref PendingSpells);

                // Invoke Spell checker delegate asynchronously

                checker.BeginInvoke(phrase, delegate(IAsyncResult ar) // put callback into our function too

                {

                    // Retrieve the delegate.

                    SpellingCheck caller = (SpellingCheck) ar.AsyncState;

 

                    // Call EndInvoke to retrieve the results.

                    lock(checker)

                    {

                        results.Add(caller.EndInvoke(ar));

                    }

                    System.Threading.Interlocked.Decrement(ref PendingSpells);

                },checker);

            }

 

            // collect data from asynchronously called delegates in the order they finish

            while(PendingSpells != 0 || results.Count != 0 )

            {

                if( results.Count > 0 )

                {

                    // the delegates delegates modify the collection from another thread

                    // we must synchronize here

                    lock(checker)

                    {

                        foreach (KeyValuePair<string, string> result in results)

                        {

                            yield return result;  // return available result

                        }

                        results.Clear(); // remove returned results

                    }

                }

                System.Threading.Thread.Sleep(50); // wait until the next phrase comes from google

            }

        }

This little example shows the true power of anonymous delegates in combination with asynchronous I/O and the resulting scalable solution which can be found in true Enterprise Applications which use the .NET platform. I hope Microsoft will forgive me when I used the Google API web service for this demo ;-).

Conclusions

Many concepts originated from functional programming languages are already alive in C# 2.0 which enables a feature rich way of programming. F# has some interesting ideas (type inference, increased thread safety, ...) which will soon be available to all sharper's in the future, I hope. Not all concepts of functional languages should be explored by Mort and Elvis since most of them are fairly complex to understand because functional languages are very picky (just like unix) who will become be their friend and who not. If Einstein does write a F# program then only a true Einstein can maintain it. When the outsourced Mort and Elvis do change his code I am sure they will screw it up. My first steps with F# (I am still a beginner) have been a little frustrating since the F# compiler does not give me useful compiler error messages. But once I was more into the syntax it did become easier. I hope you did enjoy this C# biased introduction into the world of functional programming languages.

posted on Sunday, May 28, 2006 6:27 PM

Feedback

# re: Functional Programming with C#/F# 5/28/2006 10:41 PM Don
Great article - would be nice to see more F# versions, since the C# versions are, well....

For the F# code I would have used the following:

let someArray = [|"some"; "lowercase"; "words"|]

let ToUpperArray(inArr) = inArr |> Array.map (fun y -> y.ToUpper())

let bigArray = ToUpperArray(someArray)

do bigArray |> Array.iter(fun x -> printf "\n%s" x)

You say "arrays in F# are immutable except if you use the [| |] notation to mark them as .NET arrays." This is not quite right - functional lists are immutable but arrays are always mutable. See the description at http://www.strangelights.com/fsharp/Wiki/default.aspx/FSharpWiki.ListsAndArrays.





# A few corrections 5/28/2006 10:57 PM DeeJay
"Arrays in F# are immutable except if you use the [| |] notation to mark them as .NET arrays."

... uhh I think you may be confusing arrays with lists. List are denoted [1;2;3] and are linked lists, so yeah immutable. [|1;2;3|] are *the* arrays in F# and are exactly the same as arrays in other .net based languages.



"In F# it is easy to define a function calc which does add the input arguments.

let calc(x,y) = x + y;;
Now we can define a curried function which supplies for x always -1 as input argument to calc:
let subMinusOne(y) = calc(-1,y);;
If we execute the curried function we will get the desired result:
> subMinusOne(0);;
val it : int = -1"

those aren't curried functions... here's how the example should look

let calc x y = x + y;;
let subMinusOne = calc -1;;
> subMinusOne 0;;
val it : int = -1

calc has the type
int -> int -> int
and is a curried function
your calc has the type
int * int -> int
which takes a pair of integers and returns an int.
my calc takes an integer and returns a function that takes an integer and returns and integer.

calc 3 4;; would be the application of all the arguments, returning 7
calc 3;; is a function that adds 3 to another integer.

In your very first example I would argue that the F# version is much clearer. Shorter, more terse and concise, less cruft/excess syntax to wade through, no types stated multiple times, and ultimately more declarative (tells you whats going on - short and sweet). But hey maybe that's just me ;). I'd encourage you to keep up with the time investment and maybe you'll soon agree.

Anyway, a good read, thanks.

# Re: Corrections 5/29/2006 7:56 AM DeeJay
Thanks for the update however the curried function still isn't quite right... :)

"let calc x y = x + y;;
Now we can define a curried function which supplies for x always -1 as input argument to calc:
let subMinusOne y = calc -1;;
If we execute the curried function we will get the desired result:
> subMinusOne 0;;
val it : int = -1"

calc is correct and is the curried function, not subMinusOne.
But what is the 'y' parameter doing on the definition of subMinusOne. It's not being used on the right hand side.

let subMinusOne = calc -1;; defines subMinusOne to be the application of the curried function calc to only one of it's arguments... hence subMinusOne being a function.
let subMinusOne y = calc -1 y;; would be valid... however is redudant, and if you want to use it like that, it's essentially no different to the version with tupled arguments.

The power of using curried functions is when you start passing round partial applications of them.

map (calc 2) [1;2;3;4];; which adds 2 to every number in the list. A trivial example, but a very powerful concept in general.

# re: Functional Programming with C#/F# 5/29/2006 10:03 PM Robert Pickering
Hi,

I made my response here: http://strangelights.com/blog/archive/2006/05/29/1304.aspx

It is ment to be a healthy discustion, rather than a flame so I hope you take no office by it.

Thanks,

Rob


# F# - Combining the efficiency, scripting, strong typing and productivity of ML with the stability, libraries, cross-language working and tools of .NET. 7/18/2006 1:11 PM Dave Cooper
From the F# Site at http://research.microsoft.com/fsharp/fsharp.aspx
F# is a programming language that...

# re: Functional Programming with C#/F# 9/8/2006 7:21 AM ikus724
Hi,

Great article especially section "Caching The C# Way". My question is, if I have 2 functions:

public Double Multiply(Double num1, Double num2);
public Double MuliplyBy5(Double num);

then I would need 2 version of EntlibFuncCachers, right?

public static Function<TParam, TReturn> EntlibFuncCacher<TParam, TReturn>(Function<TParam, TReturn> func)

public static Function<TParam1, TParam2, TReturn> EntlibFuncCacher<TParam1, TParam2 TReturn>(Function<TParam1, TParam2, TReturn> func)

Is there any way of doing this with one generic delegate that can handle functions with different signature?

Thanks in advance!

# re: Functional Programming with C#/F# 9/10/2006 8:42 PM Alois Kraus
Yes you need two different delegates to get it working with C# 2.0. But with C# 3.0 and the new type inference features you won't need to declare it all over and over again.

Yours,
Alois Kraus

# re: Functional Programming with C#/F# 11/12/2006 9:12 AM Jon Harrop
Google for "memoize" and you'll find more elegant ML code that does the same thing, like this:

let memoize f =
let m = Hashtbl.create 0 in
fun x ->
try Hashtbl.find m x with Not_found ->
let f_x = f x in
Hashtbl.add f x f_x;
f_x

You can even <a href="http://caml.inria.fr/pub/ml-archives/caml-list/2006/10/6cac2b55f7af5d1010451a522d4befec.fr.html">memoize the recursive calls within a function</a>.

If you only want to memoize one value then you want to look at the Lazy module.


# re: Functional Programming with C#/F# 12/3/2006 2:51 PM anonymous
Hello
This may be corrected :
"The F# version is a bit shorter and contains more comments than the F# version."

# re: Functional Programming with C#/F# 12/20/2006 1:39 AM AMMAR NAJJAR
hi, really nice topic. actually i need hlp.. im kinda into functional programming in C#. n can we do it in VB.net as well ?!!! can u hlp me with books or links or Tutorials, thanks.

I wanna participate in this code:
namespace GeneralDBClass
{
/// <summary>
/// Summary description for GeneralDB.
/// </summary>
public abstract class GeneralDB
{
//#############################################################################################
private static string dbConnStr = ConfigurationSettings.AppSettings.Get("ConnectionString");
//#############################################################################################
/// <summary>
/// Create Database Connection
/// </summary>
/// <returns></returns>
public static SqlConnection CreateConnection()
{
SqlConnection dbConn = new SqlConnection (dbConnStr);
return dbConn;
}
//###########################################################################################
/// <summary>
/// Get The Max number in a table
/// "Serial numner"
/// </summary>
/// <param name="TableName">String Table Name</param>
/// <param name="FieldName">String Field Name to get the max of</param>
/// <returns>integer Value</returns>
public static int GetMaxNumber(string TableName , string FieldName)
{
string sSQL;
sSQL = "SELECT MAX("+FieldName+")+1 AS MAXNUM FROM " + TableName;

SqlConnection dbConn = CreateConnection();
SqlCommand dbCommand = new SqlCommand(sSQL,dbConn);

dbConn.Open();
SqlDataReader result = dbCommand.ExecuteReader(CommandBehavior.CloseConnection);
dbConn = null;
result.Read();
if (result.IsDBNull(0))
{
return 1;
}
else
return Convert.ToInt16(result.GetValue(0).ToString());
}
//#################################################################################
public static int GetCountNumber(string TableName , string FieldName, string Condition)
{
string sSQL;
sSQL = "SELECT COUNT("+FieldName+")+1 AS MAXNUM FROM " + TableName + " " + Condition;

SqlConnection dbConn = CreateConnection();
SqlCommand dbCommand = new SqlCommand(sSQL,dbConn);

dbConn.Open();
SqlDataReader result = dbCommand.ExecuteReader(CommandBehavior.CloseConnection);
dbConn = null;
result.Read();
if (result.IsDBNull(0))
{
return 1;
}
else
return Convert.ToInt16(result.GetValue(0).ToString());
}
}
}

# re: Functional Programming with C#/F# 12/21/2006 12:00 AM Alois Kraus
Hi Ammar,

I think the easiest way would be to visit: http://www.kamalpatel.net/ConvertCSharp2VB.aspx where you can simply paste your C# code and get the VB.NET (well more or less) back.

Yours,

Alois Kraus



# re: Functional Programming with C#/F# 7/13/2008 11:27 AM avatarlar
Yes you need two different delegates to get it working with C# 2.0. But with C# 3.0 and the new type inference features you won't need to declare it all over and over again.



# re: Functional Programming with C#/F# 11/14/2008 4:06 AM Whitter
Using the array conversion example, can F# use combined functions at all, c.f. C#s multicast delegates?


string[] someArray = { "some", "lowercase", "words" };
Converter<string, string> ToUpper = delegate(string s) { return s.ToUpper(); };
Converter<string, string> Trim = delegate(string s) { return s.Trim(); };
Converter<string, string> NewFormat = Trim + ToUpper;
string[] upperCaseArray = Array.ConvertAll(someArray, NewFormat);

or alternatively, combine functions on the fly if we won't be using them often:
string[] upperCaseArray = Array.ConvertAll(someArray, Trim + ToUpper);


# re: Functional Programming with C#/F# 10/21/2009 5:19 AM Thanigainathan
Hi,

A very good article. I wourld like to use this languages.
Thanks,
Thani

# re: Functional Programming with C#/F# 3/1/2010 10:37 PM ieshanie
f# is better than c#.............:)

Post A Comment
Title:
Name:
Email:
Comment:
Verification: