mike-obrien.net Resume Blog Labs
Tuesday, February 05, 2008

There are much better explanations by people who really know about functional programming so the next few posts on F# are more an exercise for my brain than anything else. But maybe you will find them useful...

So I haven't heard of the tuple since watching boring educational videos on database theory 10 years ago. But alas the tuple appears again as I'm learning F# and also digging into some mathematical concepts again. It's actually been there all along as I declared a singleton or joined database tables. A tuple is basically a finite sequence of objects that are in a particular order and can contain the same object more than once. It is also immutable (Aka, cant be modified). An example of a tuple could be a first name, last name and age. In C# we may define it as a generic triple (a tuple with three items) class as follows:

public class Triple<A,B,C>
{
    private A value1;
    private B value2;
    private C value3;

    public Person(
        A value1,
        B value2,
        C value3)
    {
        this.value1 = value1;
        this.value2 = value2;
        this.value3 = value3;
    }

    public A Value1 { get { return this.value1; } }
    public B Value2 { get { return this.value2; } }
    public C Value3 { get { return this.value3; } }
}

Then define our person as this triple:

Triple<string, string, int> person = 
    new Triple<string, string, int>("Richard", "Nixon", 61);

We could then set other values to the contents of the triple if we wanted:

string firstName = person.ValueA;
string lastName = person.ValueB;
int age = person.ValueC;

Easy enough right? Well lets see how we could do the same thing in F#. First off we don't have to create or instantiate a tuple class (This is actually done under the covers as we will see in a moment). We simply set the variable equal to a comma separated list of objects as follows:

let person = "Richard", "Nixon", 61

And voila! We have a tuple (A triple to be precise)... Now to set the contents of the tuple to other variables we simply do the following:

let firstName, lastName, age = person

Here we just set the individual firstName, lastName and age variables to the corresponding values in the tuple. On the other hand if we just want the first name we can block out the last name and age with the underscore placeholder ("_") and just get the first name:

let firstName, _, _ = person

or we can just get the last name and the age by blocking out the first name. You get the point...

let _, lastName, age = person

F# uses "pattern matching" to match up the variables listed, with the values in the tuple. Now as mentioned before, under the covers F# does actually use generic tuple types as seen when working with a tuple from F#...

in C#...

image

In reflector we can see that there are tuple definitions for up to 7 items:

image

Edgar Sanchez has a nice blog entry on tuples here.

F#
Tuesday, February 05, 2008 2:46:15 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
Monday, January 28, 2008

Mike Jones has posted an analysis of an adaptation of the Concurrent Life app (That ships with the F# distro) here. I haven't gotten through the entire article yet but so far it is great. The sample app has a C# interface and consumes an F# library. He suggests that C#'ers not familiar with functional programming use F# imperatively to get comfortable with the language syntax then tackle the functional style.

Also, I came across these articles by Thomas Petricek that are proving very helpfull:

  • F# Overview (I.) - Introduction
  • F# Overview (II.) - Functional Programming
  • F# Overview (III.) - Object Oriented and Imperative Programming
  • F# Overview (IV.) - Language Oriented Programming
  • And also a nice intro by The Flying Frog Consultancy...

    C# | F#
    Monday, January 28, 2008 4:38:04 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 

    Most software, protocols and hardware are not compatible with their older versions, not to mention the fact that these versions change frequently. What if you had 50 year old hardware that was compatible with your brand new MacBook Pro? Well on this 50th anniversary of the patent for the original Lego brick we see compatibility at its best; the original Lego brick patented on January 28, 1958 is still compatible with bricks purchased today.

    Not surprisingly, years earlier and only 150 miles away in Copenhagen, Niels Bohr and his crew formulated many of the principles of Quantum Mechanics. This is appropriate as the connectivity of the Lego brick is in fact quantized...

    Monday, January 28, 2008 2:51:02 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
    Wednesday, January 09, 2008

    Factoring binomials raised to a particular power can be done easily when you follow a few patterns. We'll use the following binomial to demonstrate these patterns: (2a - b)3. I'm going to do this the long way to illustrate the mechanics.

    The first pattern has to do with the power the binomial is raised to. The factored form will first have the original terms multiplied by each other to form a new term. This new term will be added to itself the same number of times as the power of the unfactored binomial plus one; in this example it will be 4 (3 + 1). Since the operation in the unfactored binomial is subtraction the second term, b, will be negative.

    (2a)(-b) + (2a)(-b) + (2a)(-b) + (2a)(-b)

    The next pattern involves the coefficients. The coefficients for each term in the factored binomial match a row in Pascal's Triangle. The row number we want in Pascal's Triangle is the power the unfactored binomial was raised too (With the first row in the triangle being zero). So in this example the binomial is raised to the 3rd power and the coefficients will match the values in row 3 of Pascal's Triangle: 1, 3, 3 and 1 in that order.

    image

    1(2a)(-b) + 3(2a)(-b) + 3(2a)(-b) + 1(2a)(-b)

    The next pattern involves the powers of the terms. The first term in the original unfactored binomial, 2a, starts with the power of the original unfactored binomial and decreases by one, in the factored form. The second term in the original unfactored binomial, b, starts with a power of zero and increases by one, in the factored form.

    1(2a)3(-b)0 + 3(2a)2(-b)1 + 3(2a)1(-b)2 + 1(2a)0(-b)3

    Now the factored form can be reduced. First, if the terms in the unfactored binomial are subtracted, every other operation in the factored binomial will be subtraction. This occurs because the power determines the sign of the term. Negative terms raised to an even number will be positive (IE: -22 == -2 * -2 == 4) and negative terms raised to an odd power will remain negative (IE: -23 == -2 * -2 * -2 == -8). The pattern ends up being the first first operation is subtraction, the second is addition and so on.

    1(2a)3(b)0 - 3(2a)2(b)1 + 3(2a)1(b)2 - 1(2a)0(b)3

    Now reduce the terms:

    8a3 - 12a2b + 6ab2 - b3

    So a binomial raised to the third power, (a + b)3, will follow this pattern:

    a3 + 3a2b + 3ab2 + b3

    The following script will factor out binomials (at least to a certain degree):

    ( )  


    Unfactored
    Factored
    Reduced


    Wednesday, January 09, 2008 2:44:03 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
    Thursday, December 27, 2007

    The following is a step by step installation of Subversion over Apache and SSL authenticating through an Active Directory server or local server accounts. BTW, I'm by no means an Apache guru so please leave a comment if I'm missing anything. And thanks to a bunch of people who I cant remember who posted info on the web that helped in compiling these steps! :)

    1. Install the latest CollabNet Win32 distribution found here.
      1. Make sure that only the Apache (MOD_DAV_SVN) component is checked.
        image
      2. Set the Apache configuration. You can set an arbitrary http port for now; it will change when SSL is setup.  Also remember to check the “Install Apache … as a Windows Service” checkbox. The other two options should be set accordingly.
        image
    2. Create a test repository
      1. Open a command prompt and run the following command from the CollabNet installation folder (C:\Program Files\CollabNet Subversion Server\) to create a test repository:
        svnadmin create d:\temp\Repos\mysweetapp
    3. Test Connectivity
      1. Start the Apache service; it should be called Apache2.
      2. Browse to the test repository at http://localhost:1984/mysweetapp with a Subversion client and create a folder to verify that everything is setup correctly.
    4. Install and Configure the SSPI module
      1. Download the SSPI module from here. You will want to match the major and minor Apache build with the version number trailing the SSPI module version number. For example mod_auth_sspi-1.0.4-2.0.58.zip would be for Apache 2.0.x and mod_auth_sspi-1.0.4-2.2.2.zip would be for Apache 2.2.x (Thanks to Dan Switzer for pointing this out, I totally missed that!). After unzipping the contents if the zip, copy the mod_auth_sspi.so (In the bin folder) into the Apache modules folder (C:\Program Files\CollabNet Subversion Server\httpd\modules).
      2. Open the httpd.conf file in the Apache configuration folder (C:\Program Files\CollabNet Subversion Server\httpd\conf)
      3. Add the following line to (Or uncomment it in) the Apache configuration file (httpd.conf) in the LoadModule section:
        LoadModule sspi_auth_module modules/mod_auth_sspi.so
      4. Add the following settings, under “# Active Directory Auth”, to the location section. Be sure to specify the SSPIDomain which can be an AD domain or the local server name. If it is the local server name the local user accounts will be used to authenticate. You can use this option if there is no AD server.
             <Location />
                  DAV svn
                  SVNParentPath D:/Temp/Repos
         
                  # Active Directory Auth
                  AuthName "SVN Server"
                  AuthType SSPI
                  SSPIAuth On
                  SSPIAuthoritative On
                  SSPIDomain localhost
                  SSPIOfferBasic on
                  Require valid-user
             </Location>
      5. Restart the Apache2 service after the httpd.conf file has been saved.
      6. Perform the test noted in step #3 to test connectivity, this time logging in with a user from the domain specified above.
      7. Note that in TortoiseSVN  you can check the “Save Authentication” checkbox to avoid having to repeatedly enter your credentials:
        image
    5. Configure SSL
      1. Create the Certificate
        1. Create an OpenSSL configuration file under the Apache bin folder (C:\Program Files\CollabNet Subversion Server\httpd\bin) called openssl.conf and set its contents as follows:
               [ v3_ca ]
               subjectKeyIdentifier = hash
               authorityKeyIdentifier = keyid:always,issuer:always
               basicConstraints = CA:true
               [ req ]
               default_bits  = 1024
               default_keyfile  = svnserver.key
               distinguished_name = req_distinguished_name
               attributes  = req_attributes
               x509_extensions = v3_ca 
               string_mask  = nombstr
               [ req_distinguished_name ] 
               commonName  = Common Name
               commonName_default = My Server Name
               [ req_attributes ]
        2. Open up a command prompt in the Apache bin folder (C:\Program Files\CollabNet Subversion Server\httpd\bin).
        3. Run the following command to generate the private key and certificate request files. Be sure to enter the ip address or DNS name of the server when prompted for the common name. Also remember the pass phrase you entered as it will be required for the following step. This will create a svnserver.csr and svnserver.key file in the Apache bin folder.
                openssl req -config openssl.conf -new -out svnserver.csr
          image
        4. Remove the passphrase from the private key with the following command. Enter the passphrase you specified in the last step.
               openssl rsa -in svnserver.key -out svnserver.key
          image
        5. Create the self signed certificate with the following command. The following command sets the certificate expiration to 20 years.
               openssl x509 -in svnserver.csr -out svnserver.cert -req -signkey svnserver.key -days 7300
          image
        6. Delete the svnserver.csr in the Apache bin folder.
        7. Copy the svnserver.key and svnserver.cert from the Apache bin folder to the Apache conf folder.
      2. Open the httpd.conf file in the Apache configuration folder (C:\Program Files\CollabNet Subversion Server\httpd\conf).
      3. Change the listen port to 443:
             Listen 443
      4. Change the server name to include the SSL port, 443:
             ServerName localhost:443
      5. Uncomment or add the load module directive for mod_ssl:
             LoadModule ssl_module modules/mod_ssl.so
      6. Create or overwrite the following IfModule section so that it appears as follows:
             <IfModule mod_ssl.c>
                    SSLEngine on
         
                    SSLRandomSeed startup   builtin
                    SSLRandomSeed connect   builtin
                    SSLPassPhraseDialog     builtin
                    SSLSessionCache         dbm:logs/ssl_scache
                    SSLSessionCacheTimeout  300
                    SSLMutex                default
                    SSLCertificateFile      conf\svnserver.cert
                    SSLCertificateKeyFile   conf\svnserver.key 
              </IfModule>
      7. Restart the Apache2 service.
      8. Browse to https://localhost/mysweetapp and create a folder to test the configuration.
      9. Note that in TortoiseSVN you can permanently accept the certificate when this dialog appears. It is warning you that the issuer is not a trusted root authority.
        image
    Thursday, December 27, 2007 2:27:11 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
    Thursday, December 20, 2007

    You know what language I'll be coding in on Caturday? lolcode!

    kthxbye

    Thursday, December 20, 2007 2:20:38 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 

    MathTV is posting videos on YouTube (Teasers for their service). There are over 60 so far on a number of different topics. MathTV also has an online subscription for $35 a year which gives you access to hundreds of videos. I like that they are under 10 minutes each and the instructor does a great job of explaining the material.

    Thursday, December 20, 2007 3:15:46 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
    Tuesday, December 18, 2007

    The following JavaScript class enables you to get the expanded coefficients of a binomial raised to a particular power. Pass in the power and it will return an array of coefficients. For example, passing in a power of 6 returns {1, 6, 15, 20, 15, 6, 1}. This is also a row in Pascal's Triangle. It's using the following formula to calculate the coefficients, where n is the the power the binomial is raised to and k is the term position (0 to n).

    Here is the class (PascalsTriangle.js):

    function PascalsTriangle()
    {
        this.GetExpandedBinomialCoefficients = function(power)
        {
            var coefficients = new Array(power);

            for (var index = 0; index <= power; index++)
            {
                coefficients[index] = this.GetExpandedBinomialCoefficient(power, index);
            }

            return coefficients;
        }

        this.GetExpandedBinomialCoefficient = function(power, term)
        {
            return this.GetFactorial(power) / (this.GetFactorial(term) * this.GetFactorial(power - term));
        }

        this.GetFactorial = function(value)
        {
            if (value <= 1)
                return 1;
            else
                return value * this.GetFactorial(value - 1);
        }
    }

    The class can be used as follows:

    var pascalsTriangle = new PascalsTriangle();
    var coefficients = pascalsTriangle.GetExpandedBinomialCoefficients(6);
    alert(coefficients.join(' '));

    This video covers Pascal's Triangle...

    Tuesday, December 18, 2007 3:03:17 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
    Wednesday, December 05, 2007

    ...and your 100% sure your xpath is correct. It's probably that there is a namespace defined. All you need to do is define the namespace under the xmlpoke element and prefix your element names with the namespace prefix. Check it:

    web.config:

    <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
      <appSettings>
        <add key="SomeSetting" value="" />
      </appSettings>
    </configuration>

    NAnt:

    <project name="YadaYadaYada" default="default">
        <target name="default">
            <xmlpoke
                 file="D:\Temp\web.config"
                 xpath="/ns:configuration/ns:appSettings/ns:add[@key='SomeSetting']/@value"
                 value="SomeValue">
                      <namespaces>
                          <namespace prefix="ns" uri="
    http://schemas.microsoft.com/.NetConfiguration/v2.0" />
                      </namespaces>

             </xmlpoke>
       </target>
    </project>

    Wednesday, December 05, 2007 8:00:25 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
    Tuesday, November 27, 2007

    Testing for the existence of a folder with NAnt is pretty simple. The only caveat is that you reference parameters without the ${} qualifier. You can also concatenate strings, building the path dynamically...

    <property name="RootPath" value="D:\Temp" />
    <property name="RelativePath" value="SomeFolder" />

    <target name="default">

       <if test="${directory::exists(RootPath + '\' + SomeFolder)}">
          <echo message="${RootPath}\${SomeFolder} exists!"/>
       </if>

       <if test="${not(directory::exists(RootPath + '\' + SomeFolder))}">
          <echo message="${RootPath}\${SomeFolder} does not exist!"/>
       </if>

    </target>

    As a side note; if you plan on passing a path into an exec as a parameter remember to quote it with the &quot; HTML entity:

    <exec program="${Subversion}">
        <arg value="update &quot;${RootPath}\${SomeFolder}&quot;" />
    </exec>
     

    Tuesday, November 27, 2007 5:43:06 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 

    NAnt scripts can get cluttered with configuration values. One way to clean this up is to create properties that are used throughout the script. Although, you could take this a step further and store NAnt script configuration values in an Xml file. I like this approach because it creates a clear separation between the script and modifiable parameters. For example lets say we have an Xml configuration file called Build.config that contains paths:

    <?xml version="1.0"?>
    <buildConfiguration>
        <paths>
            <path name="SubversionPath" value="C:\Program Files\CollabNet Subversion Server\svn.exe" />
        </paths>
    </buildConfiguration>

    Our NAnt script could then load these paths into parameters in an "init" target. All other targets could then depend on this "init" target.

    <?xml version="1.0"?>
    <project name="Build" default="default">

        <property name="SubversionPath" value="" />
        <target name="init">
            <xmlpeek

                  file="Build.config"
                  xpath="/buildConfiguration/paths/path[@name = 'SubversionPath']/@value"
                  property="SubversionPath"/>
         </target>

         <target name="default" depends="init">
             <echo message="${SubversionPath}" />

         </target>
    </project>

    image

    Tuesday, November 27, 2007 5:09:38 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 

    If you don't appreciate the Automatic Update service automatically rebooting your box after new updates are installed (Who would??), then simply run gpedit.msc to start the Group Policy editor and modify the following policies :

    image

    Tuesday, November 27, 2007 4:11:14 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |