Dec 20, 2010

Git finally

After using Git for a few months with GitHub, I am finally loving it and setup Git server using IIS 7 and git-dot-aspx. I finally feel the force is with me now.


Source control is more important and more complicated I thought many years ago. Over the years of programming, I understand more about it. I used cvs, vss, svn, tfs and now finally Git. I have seen many other people's discussions of version control, I also have many discussion with other people. But the views are so different, it is like for a Christian to convince an atheist to believe there is a god. How can you explain someone who love single checkout in vss that multi checkout is better in vss, how can you explain someone who love vss that svn is better, and how can you explain to someone who love svn that Git is the best. I have seen a IT manager said that "I never seen enterprise software can been successfully implemented without exclusive checkout". It is not worthy for such kind of discussion. But semantics remains the same, we just try to get a tool to satisfy our need, make our work more productive, make us in control. But if we don't have that kind of need, or we don't know there is such kind need, or we don't have time to need, it is very hard to accept some new concept. Git is specially designed to make you feel less intelligent than you think you were. Learn it.

Dec 7, 2010

"this" in javascript

If you don't know javascript is a functional language and you do lots of object oriented programming, the follow code must be very confusing for you.

var name = "Jerry";

var x = { name : "Tom",
          sayName1 : function () {
              alert(this.name);
           },
          sayName2 : function () {
             sayName3();
           },
           sayName4 : function () {
            sayName3.call(this); 
          }
        };

var sayName3 = x.sayName1;  

x.sayName1(); //show Tom //line a
sayName3();   //show Tom? no, it is Jerry //line b 
x.sayName2(); //show Tom? no, it is still Jerry!! //line c
x.sayName4();  //now it is Tom //line d

In OO language like C#, java, instance method belongs to an instance(object). The method knows "this" is referring the instance it belongs to. So if you use this concept to apply to javascript, you will think the behavior line a make sense. Line b will be confusing, and line c and line d is even confusing. In javascript, object can reference function, however functions don't belong to any object, and a function does not know what "this" is, until is called in one of the following case. Let's read the follow code


var x = new ConstructorFunction();
var y = simpleCallFunction();
var z = o.memberCallFunction();
var a = usingapplyCallFunction.apply(o, [p1, p2]);
var b = usingcallCallFunction.call(o, p1, p2);

In line y, the "this" in simpleCallFunction always refer to global object. In line a,b, they are basically the same,except the syntax, which specify the object that "this" is referred to. In line z, we can rationalize at as " var temp = o.membershipCallFunction; temp.call(o); " or just "o.membershipCallFunction.call(o);". Line x is constructor call, the "this" is the object being created.


What the global object is depends on the engine. In browser, it refers the window object. But there are other environment too. Here is how window object is passed in? When a page is loading, javascript engine convert the string in <script /> block to a function, let's say, x, then call x.call(window). That is why all your code in the block knows that "this" is window. In line y, you can rationalize it as " simpleCallFunction.call(window) ". The only special case is line x, which use function as a constructor. So what happens to native javascript object, for example, array. If you want to use push method of an array for a non array method, can you? Yes, you can, in fact, that is why jQuery object works like an array even though it is not an array. Here is trick.


var fQuery = { push: [].push }
fQuery.push("item1");
//it works like an array!!
//push method does not belong to array, you can apply it to any object
alert(fQuery [0]);
alert(fQuery.length);

In conclusion, javascript function does not belong to any object, "this" is parameter passed in implicitly or explicitly during the function is called, "this" is just the same as other parameter. However, the language just provide some misleading syntax (but it is also good syntax) to pass the parameter into a function.

mutable binding and ref type

We all know that in F#, once you bind a value to an identifier, that the value can not be changed. What does this means? It means the your identifier will be like a read only property, the property return a value that is determined at the time of binding. After binding, the identifier looks like a constant. Mutable makes identifier more like a variable. But actually, it is a property with both getter and setter. Let's look at the following code.

let testMutable =
    //let mutable temp = 1
    let temp = 1
    let innerFunction() = 
        printfn "%i" temp
        ()
    innerFunction

let t1 = testMutable
t1()

This code compiles, but if we use mutable temp, then it shows an error like,



The mutable variable 'temp' is used in an invalid way. Mutable variables cannot be captured by closures. Consider eliminating this use of mutation or using a heap-allocated mutable reference cell via 'ref' and '!'.


So why? Identifier defined as mutable are limited in that they can not be used within a inner function like above. But still why? So let's decompile into c# and see that is going on?


public static void main@()
{
    int temp = 1; //because temp cannot be property
    FSharpFunc<Unit, Unit> innerFunction = new Program.innerFunction@161(temp);
    FSharpFunc<Unit, Unit> testMutable = testMutable@158 = innerFunction;
    FSharpFunc<Unit, Unit> t1 = t1@165 = Program.testMutable;
    Program.t1.Invoke(null);
}

[CompilationMapping(SourceConstructFlags.Value)]
public static FSharpFunc<Unit, Unit> testMutable
{
    get
    {
        return $Program.testMutable@158;
    }
} 

[Serializable]
internal class innerFunction@161 : FSharpFunc<Unit, Unit>
{
    // Fields
    public int temp;

    // Methods
    internal innerFunction@161(int temp) //innefunction accept value from parent function as constructor parameter
//it looks like a read/write property is not sufficient enough to support the 
// closure capture, 
    {
        this.temp = temp;
    }

 public override Unit Invoke(Unit unitVar0)
 {
        FSharpFunc<int, Unit> func = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<int, Unit>>(new PrintfFormat<FSharpFunc<int, Unit>, TextWriter, Unit, Unit, int>("%i"));
        int temp = this.temp; //copy the member to local variable
        func.Invoke(temp);
        return null;
    }
}

Let's change it to ref, as the error message suggested, and let's add some code to change the value of identifier because we can, then decompile it.


let testMutable =
    let temp = ref 1
    let innerFunction() = 
        temp := !temp  + 1
        printfn "%i" !temp
        ()
    innerFunction

let t1 = testMutable
t1() //print 2
t1() //print 3

public static void main@()
{
    FSharpFunc<Unit, Unit> innerFunction = new Program.innerFunction@161(Operators.Ref<int>(1));
    FSharpFunc<Unit, Unit> testMutable = testMutable@158 = innerFunction;
    FSharpFunc<Unit, Unit> t1 = t1@166 = Program.testMutable;
    Program.t1.Invoke(null);
    Program.t1.Invoke(null);
}

[CompilationMapping(SourceConstructFlags.Value)]
public static FSharpFunc<Unit, Unit> testMutable
{
    get
    {
        return $Program.testMutable@158;
    }
}
 
[Serializable]
internal class innerFunction@161 : FSharpFunc<Unit, Unit>
{
    // Fields
    public FSharpRef<int> temp;

    // Methods
    internal innerFunction@161(FSharpRef<int> temp)
    {
        this.temp = temp;
    }

    public override Unit Invoke(Unit unitVar0)
    {
//we can change the value, because it is ref Type(f#),

        Operators.op_ColonEquals<int>(this.temp, Operators.op_Dereference<int>(this.temp) + 1);

        FSharpFunc<int, Unit> func = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<int, Unit>>(new PrintfFormat<FSharpFunc<int, Unit>, TextWriter, Unit, Unit, int>("%i"));
//get the value from ref Object using op_Dereference operator       
int num = Operators.op_Dereference<int>(this.temp); 
        func.Invoke(num);
        return null;
    }
}

We can say to implement the closure feature (inner function can memorize mutable value from parent function), simple mutable value is not robust enough to support that. We need a ref Type. The ref type here is not the reference type we talk about in CLR or C#. The ref Type is generic record type. We can mimic ref implementation as follow, here we rename ref as wrapper.


type wrapper<'a> = { mutable innerValue: 'a }

let testref =
    let x = { innerValue = 1 }
    let innerFunction() =
        x.innerValue <- x.innerValue + 1
        printfn "%i" x.innerValue
    innerFunction

let f = testref
f()
f()

//decompiled into 
public static void main@()
{
    Program.wrapper<int> x = new Program.wrapper<int>(1);
    FSharpFunc<Unit, Unit> innerFunction = new Program.innerFunction@138(x);
    FSharpFunc<Unit, Unit> testref = testref@135 = innerFunction;
    FSharpFunc<Unit, Unit> f = f@142 = Program.testref;
    Program.f.Invoke(null);
    Program.f.Invoke(null);
}

[Serializable, CompilationMapping(SourceConstructFlags.RecordType)]
public sealed class wrapper<a> : IEquatable<Program.wrapper<a>>, IStructuralEquatable, IComparable<Program.wrapper<a>>, IComparable, IStructuralComparable
{
    // Fields
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public a innerValue@;

    // Methods
    public wrapper(a innerValue);
    [CompilerGenerated]
    public sealed override int CompareTo(Program.wrapper<a> obj);
    [CompilerGenerated]
    public sealed override int CompareTo(object obj);
    [CompilerGenerated]
    public sealed override int CompareTo(object obj, IComparer comp);
    [CompilerGenerated]
    public sealed override bool Equals(Program.wrapper<a> obj);
    [CompilerGenerated]
    public sealed override bool Equals(object obj);
    [CompilerGenerated]
    public sealed override bool Equals(object obj, IEqualityComparer comp);
    [CompilerGenerated]
    public sealed override int GetHashCode();
    [CompilerGenerated]
    public sealed override int GetHashCode(IEqualityComparer comp);

    // Properties
    [CompilationMapping(SourceConstructFlags.Field, 0)]
    public a innerValue { get; set; }
}

 
[Serializable]
internal class innerFunction@138 : FSharpFunc<Unit, Unit>
{
    // Fields
    public Program.wrapper<int> x;

    // Methods
    internal innerFunction@138(Program.wrapper<int> x)
    {
        this.x = x;
    }

    public override Unit Invoke(Unit unitVar0)
    {
        this.x.innerValue = this.x.innerValue@ + 1;
        FSharpFunc<int, Unit> func = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<int, Unit>>(new PrintfFormat<FSharpFunc<int, Unit>, TextWriter, Unit, Unit, int>("%i"));
        int num = this.x.innerValue@;
        return func.Invoke(num);
    }
}

Of course, ref provide "!" operator instead of v.innerValue, and ":=" operator in place of "v.innerValue <- x", it is much more elegant. Once we understand ref, we can use it to create function using closure, which is really really powerful.

How Binding in f# is like in CLR

In c# or clr philosophy, everything is object, object is the horsepower. In f# philosophy, everything is value, function is the horsepower. However f# is implemented in CLR, I am just curious how F# is implement in CLR, so I use reflector to decompile the generated code. However, I don't think reflector is not very accurate here. To really understand , it is better is use ILDASM.exe.

let m1 = 1 // convert to readonly property
//public static int m1
//{
//    [CompilerGenerated, DebuggerNonUserCode]
//    get
//    {
//        return 1;
//    }
//}

let mutable m2 = 1 //get and set property
//[CompilationMapping(SourceConstructFlags.Value)]
//public static int m2
//{
//    get
//    {
//        return $Program.m2@174;
//    }
//    set
//    {
//        $Program.m2@174 = value;
//    }
//}
 
 
let m3() = 1 //method return 1
//public static int m3()
//{
//    return 1;
//}
 

let m4 x = x + 1  //method accept one parameter
//public static int m4(int x)
//{
//    return (x + 1);
//}

 
let m5 (x) = x + 1 //method accept one parameter, same as m5
//public static int m5(int x)
//{
//    return (x + 1);
//}

let m6 x y = x + y + 1 //a method that accept two parameter x, y, but with a attribute CompilationArguementCounts
//[CompilationArgumentCounts(new int[] { 1, 1 })]
//public static int m6(int x, int y)
//{
//    return ((x + y) + 1);
//}


let m7 (x, y) = x + y + 1 //a method that accept one parameter, which is a turple, compiled into normal function
//public static int m7(int x, int y)
//{
//    return ((x + y) + 1);
//}

let m8 = m6 1 //partial function, compiled to property that returns a delegate, which is type of FSharpFunc<int, int>
//CompilationMapping(SourceConstructFlags.Value)]
//public static FSharpFunc<int, int> m8
//{
//    get
//    {
//        return $Program.m8@180;
//    }
//}

//[Serializable]
//internal class m8@180 : FSharpFunc<int, int>
//{
//    // Fields
//    [DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated, DebuggerNonUserCode]
//    public int x;
//
//    // Methods
//    internal m8@180(int x)
//    {
//        this.x = x;
//    }
//
//    public override int Invoke(int y)
//    {
//        return Program.m6(this.x, y);
//    }
//}


let m9 y = m7 (1, y) //compiled to a method, that call a m7 with 1 and y
//public static int m9(int y)
//{
//    return m7(1, y);
//}

let turple1 = (1, 2)
//[CompilationMapping(SourceConstructFlags.Value)]
//public static Tuple<int, int> turple1
//{
//    get
//    {
//        return $Program.turple1@268;
//    }
//}
 
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
//internal static Tuple<int, int> turple1@268;
//

 
let m10 = m7 turple1 
//[CompilationMapping(SourceConstructFlags.Value)]
//public static int m10
//{
//    get
//    {
//        return $Program.m10@281;
//    }
//}
// 
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
//internal static int m10@281;
//