Sunday, July 22, 2012

Desktop Deleted in Ubuntu 12.04

While trying to save files to ~/Desktop yesterday, I had the misfortune of saving a file as ~/Desktop. I wasn't actually aware at the time, and went about my usual business for several days. Then I restarted my computer and my desktop was loaded up with all the documents and directories located in my home directory. In addition to the items I expected to see in my home directory was a PDF named Desktop. Deleting this file and restarting one's computer is not enough to fix this problem. The fix: 1. Open up ~/.config/user-dirs.dirs 2. Modify the line XDG_DESKTOP_DIR to say XDG_DESKTOP_DIR="$HOME/Desktop" 3. Save and close that file. 4. Open up a terminal 5. `killall nautilus` Voila! Far easier than I anticipated. Note that if you're one of those people who stores non-temporary files in ~/Desktop, you will not recover those files using this method.

Monday, July 2, 2012

Why I've Grown To Love C#

I admit, I'm somewhat of a Linux programming snob. Why? Mostly ease, somewhat because it was how I was taught in school, and partially because I love the idea of FOSS.

But times change quickly, and I was thrown onto a C# project with a bunch of folks who were quite used to a Windows environment. Despite the obvious hassle of having to use Windows and deal with Visual Studio, .NET has some pretty cool things to offer.

Take the example where I have a class of students; my goal is to find their averages and get the student with the highest grade so I can single them out to the rest of the class. Let's first do this in vanilla C++:

Vector<Student> Students; // contains a short int array of test scores called Tests
...
short highestGrade = -1;
Student teachersPet;

for (int i=0; i<Students.Size(); i++)
{
    unsigned int sum = 0;
    for (int j=0; j<Students[i].Tests.Size(); j++)
    {
        sum += Students[i].Tests[j];
    }
    sum /= Students[i].Tests.Size();
    if (sum > highestGrade)
    {
        highestGrade = sum;
        teachersPet = Students[i];
    }
}

That's a mouthful. Not including intialization code, there are 7 lines of "useful" code, 5 auxiliary variables, 1 division, and a bit of array indexing. Let's perform a literal translation to C#:

List<Student> Students;
...

Student teachersPet;
short highestGrade = -1;
foreach (student in Students)
{
    int avg = 0;
    foreach (score in student.Tests)
    {
        avg += score;
    }
    avg /= student.Tests.Count();
    if (avg > highestGrade)
    {
        highestGrade = avg;
        teachersPet = student;
    }
}
</code></pre>

Pretty much the same code. We are utilizing the foreach operator, which lets us get away without any array indexing. Still 7 lines of "useful" code, still 3 auxiliary variables. Assuming the Tests property in the Student class is a array of ints, we can find the average in a much more succinct fashion:

foreach (student in Students)
{
    if (student.Tests.Average() > highestGrade)
    {
        teachersPet = student;
        highestGrade = student.Tests.Average();
    }
}
Four lines of functional code, two auxiliary variables. Why stop there? Using a LINQ-based approach and adding an Average property to the Student class, we can get rid of all auxiliary variables and find the max using the average in one line of code:

var teachersPet = Students.ForEach(x => x.Average = x.Tests.Average()).MaxBy(x => x.Average);

The same functionality in a single contiguous line of code! Not to mention these Average, ForEach, and Max functions can be better optimized by our compiler than what we had before. But is that as far down as we can squish it? What if we dropped the entire ForEach statement and just compared the averages:

var teachersPet = Students.MaxBy(x => x.Tests.Average());

And that's why I've grown attached to C#. LINQ is probably my favorite thing to ever come out of Microsoft