static void Main(string[] args)

{

    var list = new[] { 1, 9, 5, 3, 7, 2 };

    list.WriteLine();

    list.QuickSort().WriteLine();

}


오랜만에 코딩이 들어간 포스팅 이네요
.
잘 모르고 있었는데 C# Functional Feature가 많이 들어 갔더군요
.
그래서 간단히 공부겸 테스트겸 가볍게 코드를 만들어 보고, 이를 공유 합니다
.

만들어본 코드는 Quicksort이며, Main함수의 내용은 위와 같고
,
실행한 결과는 아래와 같습니다.

{ 1, 9, 5, 3, 7, 2 }
{ 1, 2, 3, 5, 7, 9 }


먼저 첫 줄, 별 생각 없이 봐도 integer의 리스트를 만들었다는 것을 알 수 있습니다.

var list = new[] { 1, 9, 5, 3, 7, 2 };

 

다만, 자세히 보면 type이 전혀 선언되지 않았다는 것을 알 수 있습니다.
C# 3.0
에서는 Implicitly typed local variables을 지원해서

javascript
스러운 var a = 3 같은 문법을 지원합니다
.
자세한 것은 문서를 참조 하시고,,,

 

list.WriteLine();

list.QuickSort().WriteLine();

 

두 번째부터 세 번째 줄을 살펴보면 list Object MethodWriteLine() QuickSort()를 호출한 것을 볼 수 있습니다. 여기서 눈 여겨 볼 것은 QuickSort()Writeline()은 원래 있는 Method가 아니라 사용자가 만든 확장 Method라는 겁니다. 여기서 list variable Type Explicit하게 정의 하지 않았지만 C#에서 Type inference를 통해 Type이 결정되는데 여기에서는 int[]로 결정이 되겠지요. , C#에서도 다른 Dynamic Language같이 기존에 존재하는 Type에도 확장 함수(Extension Methods)를 추가할 수 있다는 것 입니다.

 

 

실제 Sort부분의 코드를 보면

 

public static IEnumerable<int> QuickSort(this IEnumerable<int> Ts)

{

    return Ts.Case(

        () => Ts,

        (head, tail) =>

            QuickSort(tail.Where(t => t < head))

            .Concat(new[] { head })

            .Concat(QuickSort(tail.Where(t => t >= head)))

            );

}

 

 

여기서 headtype int, tailtype int[]라는 것을 잘 봐야 합니다. C# 2.0에도 anonymous method가 있었는데 C# 3.0에서는 lambda expressions로 더욱 강화 되었습니다. Type inference feature가 추가 되면서 일일이 Parameters type을 적을 필요가 없게 된 것이 매우 큰 변화라 할 수 있을 것 같습니다. Javascript 등과 비교했을 때도, function(x) { return x; } 라고 지저분하게 적었어야 했는데, 이를 (x) => x 라고 적으면 된다니 코드를 작성하는 입장에서는 매우 반가운 일 입니다.

 

 

아무튼 나머지 코드는.


public static void WriteLine<T>(this IEnumerable<T> Ts)

{

    Debug.Write("{ " + Ts.Head());

    foreach (T t in Ts.Tail())

        Debug.Write(", " + Convert.ToString(t));

    Debug.WriteLine(" }");

}


public static T Head<T>(this IEnumerable<T> Ts)

{

    foreach (T t in Ts)

        return t;

    throw new ArgumentException();

}

 

public static IEnumerable<T> Tail<T>(this IEnumerable<T> Ts)

{

    bool head = true;

    foreach (T t in Ts)

    {

        if (head) head = false;

        else yield return t;

    }

}

 

public static IEnumerable<T> Case<T>(this IEnumerable<T> Ts, Func<IEnumerable<T>> CaseEmpty, Func<T, IEnumerable<T>, IEnumerable<T>> CaseNotEmpty)

{

    if (Ts.Count() > 0)

        return CaseNotEmpty(Ts.Head(), Ts.Tail());

    return CaseEmpty();

}

 

 

참조한 곳은..

C# is a functional programming language

Overview of C# 3.0, C# Version 3.0 Specification

 

------------

 Methods를 좀 뒤져 봤는데.
 Head() 는 First()로
 Tail()은 Skip(1)로 대체할 수 있을 것 같네요.

 

Posted by U∙Seung