Ever since reading Joel’s Can Your Programming Language Do This?, I’ve been obsessed with Functional Programming, and with my shiny new hammer, everything looks like a nail. A few months ago, I got it into my head that it’d be a good idea to implement Map, Filter, and Reduce in .NET 1.1. It was actually simple enough to do, albeit in no way type-safe, and still vulnerable to side effects. Naturally, I named the library QAFP (Quarter-Assed Functional Programming), since it was half-half-assed. As an example, here was my Map function:

public delegate object MapFunction(object obj);

public static IList Map(IList list, MapFunction func)
{
    if (null == list || null == func)
    {
        return null;
    }

    IList mappedList = new ArrayList(list.Count);

    foreach (object o in list)
    {
        mappedList.Add(func(o));
    }

    return mappedList;
}

public object Square(object obj)
{
    int i = (int) obj;

    return i * i;
}

public void MapTest()
{
    IList numbers = new ArrayList(5);

    for(int i = 1; i <= 5; i++)
    {
        numbers.Add(i);
    }

    numbers = Map(numbers, Square);
    // list should now contain [1,4,9,16,25]
}

It was ugly, but it worked. Pass it a list of mixed items and forget to do your type checking, and you’re boned. It wound up being very useful, and cut down on some of our development time, until we finally moved up to .NET 2.0. I know all of this stuff is old news to those of you using .NET 3.5 and LINQ, but given that we’ve just updated to 2.0, 3.5 is a long way off for us, so bear with me. If you’re stuck using .NET 2.0, you may enjoy this.

The upgrade to half-assed functional programming came with generics and anonymous delegates. Since side-effects are still possible, it’s not pure functional programming, but it’s close enough to be very useful, as long as you’re careful with it. The new code doesn’t look all that different, but it’s much safer, and any type errors should be caught by the compiler. Here’s the new Map function:

public delegate TOutput MapFunction<tinput, TOutput>(TInput obj);

public static void Map<tinput, TOutput>(List<tinput> inputList, MapFunction<tinput, TOutput> func, out List<toutput> outputList)
{
    outputList = new List<toutput>();

    if (null == inputList || null == func)
    {
        return;
    }

    outputList.Capacity = inputList.Count;

    foreach (TInput obj in inputList)
    {
        outputList.Add(func(obj));
    }
}

public int Square(int i)
{
    return i * i;
}

public void MapTest()
{
    List<int> numbers = new List<int>(5);
    List<int> squaredNumbers;

    for(int i = 1; i <= 5; i++)
    {
        numbers.Add(i);
    }

    Map(numbers, Square, out squaredNumbers);
    // list should now contain [1,4,9,16,25]
}

Filtering a list is also needed quite a bit, and the generic List<T> in .NET 2.0 already has this covered, through the use of Predicates. A Predicate is basically a function that takes an object of type T, and returns true or false if it matches some criteria. Combine that with List<T>’s FindAll function, and it’s easy to return a list of Ts matching that criteria. I still wrapped everything in a filter function, just to ensure no empty lists or missing predicates. As an example, to strip out all odd numbers from a list:

public static List<tinput> Filter<tinput>(List<tinput> inputList, Predicate<tinput> func)
{
    if (null == inputList || null == func)
    {
        return null;
    }

    return inputList.FindAll(func);
}

public List<int> GetEvenNumbers(List<int> numbers)
{
    return Filter(numbers, delegate(int i){ return (i % 2) == 1; });
}

Last, but certainly not least, is Reduce, also known as foldr to those of you who speak with a LISP. For those not in the know, it performs an operation on each item in the list and the total (or aggregate) of every item before it, starting with an initial value for the total. The way this total is implemented is completely up to you, as you can see below:

public delegate TAggregate ReduceFunction<tinput, TAggregate>(TAggregate aggregate, TInput obj);

public static TAggregate Reduce<tinput, TAggregate>(List<tinput> inputList, ReduceFunction<tinput, TAggregate> func, TAggregate initialValue)
{
    TAggregate aggregate = initialValue;

    inputList.ForEach(delegate(TInput input) {
        aggregate = func(aggregate, input);
    });

    return aggregate;
}

public int Sum(int total, int i)
{
    return total + i;
}

public int Product(int total, int i)
{
    return total * i;
}

public StringBuilder Concatenate(StringBuilder sb, string s)
{
    return sb.AppendFormat("{0}", s);
}

public void TestReduce()
{
    List<int> numbers = new List<int>(5);

    for(int i = 1; i <= 5; i++)
    {
        numbers.Add(i);
    }

    int sum = Reduce(numbers, Sum, 0);
    int product = Reduce(numbers, Product, 1);

    List<string> strings = GetListOfStringsToConcatenate();

    StringBuilder sb = new StringBuilder();

    sb = Reduce(strings, Concatenate, sb);
}

Now, where and why would you use this? Functional Programming is usually used for math-intensive applications, but like I said, everything looks like a nail. To improve network performance, when making remote function calls, we don’t send entire objects if we only need their ID number. So, given a list of patients, let’s say we want to find those with fatal allergies, to keep them from falling into our strategically placed peanut, grass, and pet dander bins (let’s also say we’re witch doctors).

public List<int> GetAllergiesForPatientsAboveSeverity(List<int> patientIDs, Severity severity)
{
    List<patient> patients;
    List<int> allergyIDs;

    Map(patientIDs, GetPatientObjectFromID, out patients);

    List<allergy> allergies =
        GetAllAllergiesForPatients(patients)
        .Filter(delegate(Allergy allergy) {
            return allergy.Severity >= severity;
        });

    Map(allergies, GetAllergyIDFromObject, out allergyIDs);

    return allergyIDs;
}

public List<allergy> GetAllAllergiesForPatients(List<patient> patients)
{
    // Grab the allergies for the given patients…
}

public Patient GetPatientObjectFromID(int patientID)
{
    return PatientCache.Find(delegate(Patient p) { return p.ID == patientID; };
}

public int GetAllergyIDFromObject(Allergy allergy)
{
    return allergy.ID;
}

We’d end up only sending a few ints to the server, and getting a few ints in return. Why is this important? Hell if I know, I just think it’s elegant code, if a contrived example. So, if you’re stuck with .NET 2.0 for the moment, like I am, and you’re into Functional Programming, give this a shot. I’m sure you’ll find all sorts of nails you never noticed before.

Affiliator 0.1.2 released

April 8th, 2008

This is just a maxVersion bump to allow Affiliator to work with the Firefox nightly builds. There are no new features, so if you’re happy with 0.1.1, stick with it.

I won’t bother to host it here since it’s such a small change, so you can grab it at the Mozilla Addons Directory here: Affiliator 0.1.2.

Affiliator 0.1.1 released

April 6th, 2008

Ann Zeise over at the Amazon Associates discussion boards pointed out to me that the link format I was using was outdated, and the preferred format is:

http://www.amazon.com/dp/ASIN/?tag=YourID

I’ve updated the addon to not only reflect the proper link format, but also to add it as a preference, so if Amazon changes the preferred format, you can update the string yourself until I get a fix out. Currently, it defaults to:

http://www.amazon.com/dp/#{ASIN}/?tag=#{AFFILIATE_CODE}

All you have to do is update the URL, and put the #{ASIN} and #{AFFILIATE_CODE} markers in the proper place, and it’ll work like it should.

I also added the ability to click on any product link on Amazon and have it generate the affiliate link. You no longer have to be on the actual product page. From what I’ve found, Amazon provides three link formats on their pages:

  • http://www.amazon.com/gp/product/#{ASIN}/blah
  • http://www.amazon.com/#{PRODUCT_TITLE}/dp/#{ASIN}/blah
  • http://www.amazon.com/dp/#{ASIN}/blah

If the link clicked doesn’t contain the product title, it will attempt to get it from the link text, unless the link is an image, in which case you will be prompted for the product name. If it does contain the product title, it will use that for the product name. All of these cases, of course, depend on you having set Affiliator to automatically wrap your link in an HTML tag. If you’re just generating the link, it skips this whole process.

I’m going to continue to use this blog for Affiliator update notifications, and you can always find the latest news here:

http://www.theantichris.dreamhosters.com/category/firefox-addons/affiliator/

I’ve also submitted Affiliator to the Mozilla Addons Directory, but it won’t be public until a few people have submitted reviews, so if you like it, head over there and submit a review. The benefit to that is, whenever Affiliator is updated, Firefox will notify you automatically.

Until then, you can get Affiliator 0.1.1 here:

Affiliator 0.1.1
Mozilla Addons Directory page for Affiliator

I’ve always found it a bit of a pain to generate Amazon affiliate links. Once you’ve found the page you want to link to, you have to go to the affiliate site, log in, pick what type of link you want, enter the address and what you want the link to say. Then, after all that, you get a page with your link and a tracker image. The whole process usually takes me about a minute per link, sometimes less depending on how the network’s behaving.

Like any decent 20-percenter, I’ll gladly spend a day building a tool to save myself minutes. It’ll pay itself off in a few thousand links. Anyway, the current method of generating affiliate links has two problems:

  • The generated link is long and cumbersome, filled with GET parameters.
  • It’s slow.

The first problem has been solved by a variety of people, but I first saw it on Coding Horror. You can greatly shorten the URLs, from this:

http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F
2Fwww.amazon.com %2FSamsung-SyncMaster-226BW-LCD-Monitor
%2Fdp%2FB000NBBWNU%3Fie%3DUTF8%26s%3Delectronics%26qid%3D1207233586%26sr
%3D8-1&tag=doggettc-20&linkCode=ur2 &camp=1789&creative=9325

to this:

http://www.amazon.com/exec/obidos/ASIN/B000NBBWNU/doggettc-20

All you need is the ASIN (Amazon Standard Item Number) and your affiliate code, which make up the last two segments of the URL.

First problem solved, but you still have to hunt through the page for the ASIN. I hunted around, and found that nobody had made a Firefox addon to build affiliate links, so I took on the task myself. The result is Affiliator, a one-click solution. OK, three clicks.

All you need to do now is find the product you want to link to, right-click the page, and:

Affiliator screenshot

The affiliate link is generated and copied to the clipboard. If you’re super lazy, like myself, you can choose to have your links automatically wrapped in an HTML anchor tag with the title of the item on the page. With three quick clicks, the item I showed above becomes this:

Samsung SyncMaster 226BW 22″ LCD Monitor
(A great monitor that has unfortunately gone back up in price since I bought it a year ago.)

Hopefully someone will find it useful. If not, it’ll be worth my time after 1,439 more links.

In case you missed the link above, you can download the addon here:

Affiliator 0.1