Archive | Exception RSS for this section

Making C++ Exceptions Less Terrible

If you’re a fan of doingmyprogramming, you’ve likely heard me opine on the subject of exceptions. If you’re new around here, I’ll spare you a link to some required reading and just let you know: they’re poop. With the exception of Java and it’s checked exceptions, they just represent secret ways that a function can crash your whole program. Just about nobody gets it right, not C++, not C#, and the worst offender is probably my beloved Haskell where you can’t even catch them unless you’re in the IO monad.

C++ used to have an annotation (throw()), where you could specify what exceptions a function throws, and if none are specified then the function cannot throw. This was considered poor form and deprecated long before I came on the scene. It turns out that there is good news though; throw() wasn’t forgotten! It was replaced by noexcept, and that is what we’ll be talking about today.

What is noexcept?

noexcept is an annotation that basically says “this function will never throw an exception”. You can think of it as being like const. If you some class method:

void myClass::isPure() const;

… then you know that, whatever it does, the state of the object will not be mutated. Similarly, if you see some function:

void neverThrows() noexcept;

… then you know that, whatever it does, the function will never throw an exception. Optimization implications aside, this is great because if you see a function declared noexcept, then you know for sure that you don’t have to put it in a try/catch block. If we ever start living in a world where people use this annotation, then a function not marked noexcept is a function that likely throws, and we can act accordingly without having to read through mountains of likely incorrect or incomplete documentation!

Specifically, the meaning of noexcept (according to Microsoft) is:

noexcept ( and its synonym noexcept(true)) specify that the function will never throw an exception or allow an exception to be propagated from any other function that it invokes either directly or indirectly. More specifically, noexcept means the function is noexcept only if all the functions that it calls are also noexcept or const, and there are no potentially evaluated dynamic casts that require a run-time check, typeid expressions applied to a glvalue expression whose type is a polymorphic class type, or throw expressions.

The Burning Quetion

So I read that blurb, and thought to myself: “…only if all the functions it calls are noexcept? So, I can’t catch all possible exceptions and be noexcept?”. I felt despair wash over me as C++ got something wrong yet again. Then I thought “there’s no way that’s correct… To the Googler!”

Of course, the Googler didn’t help my case. I decided to give it a shot. First, let’s consider two functions: one that throws and one that is noexcept:

static void doesThrow() noexcept(false) { std::cerr << "Entering doesThrow..." << std::endl; throw 42; std::cerr << "Still in doesThrow. Up is down, cats and dogs living together!" << std::endl; } static void catchesAll() noexcept(true) { std::cerr << "About to enter the try/catch..." << std::endl; try { doesThrow(); } catch (...) { std::cerr << "Caught the exception..." << std::endl; } std::cerr << "Exited the try/catch..." << std::endl; }

doesThrow is annotated noexcept(false), which is the same as saying “This function can throw an exception.” And sure enough, it throws in 100% of its code paths.

catchesAll is annotated noexcept(true), which is just the long form of noexcept. noexcept accepts arguments that evalutate to bool, and compile-time magic happens to allow conditional noexcept-ness. noexcept(expr) can also be used in an if/then/else to conditionally do something based on if some expr is noexcept.

In catchesAll, we have a try/catch block that prevents the exception thrown by doesThrow() from propagating out of catchesAll(). Does this work? Let’s write a test harness and see:

int main(int argc, char ** argv) { std::cerr << "About to call catchesAll..." << std::endl; catchesAll(); std::cerr << "Managed to not die!" << std::endl; }

… if we compile it with gcc (with -std=c++11) and run it, we see that all is well!

About to call catchesAll... About to enter the try/catch... Entering doesThrow... Caught the exception... Exited the try/catch... Managed to not die!

You may be wondering what happens if we don’t catch the exception. Let’s find out! If we remove the try/catch, but leave everything else the same:

About to call catchesAll... About to enter the try/catch... Entering doesThrow... terminate called after throwing an instance of 'int' Aborted (core dumped)

We see that the exception propagated out of catchesAll() and caused a core dump. This is the expected behavior. In fact, there’s no way we could have prevented this. If some function marked noexcept throws, then that function has a bug. If you wrote it, you have to fix it. If somebody else wrote it, then they have to fix it. There’s no band-aid that will keep it from crashing your program. If you find this happening often, then you should consider finding an alternative library that does what the broken dependency claims to do, since they clearly don’t know what they’re doing…

Of Semicolons and Sadness

Lately, I’ve been writing a lot of Haskell. If you’ve been following the blog, you likely are aware of this. However, I’ve been feeling the itch to try something different. I’ve been dabbling in things here and there, but for some reason I just can’t settle into a groove. It seems that Haskell has ruined programming for me.

Why? Is it the functional purity of Haskell? Is it the way that lazy evaluation changes the way you think about programming? Is it the sublime type system that catches whole classes of bugs at compile time? No, I’m afraid not. My issue is much more basic; semicolons and angle brackets.

Your Mission

…should you choose to accept it: write a function fun that does the following: takes an integer argument acc, and two arguments of the same generic type. This function should enforce that the two generic arguments cannot be changed. This function calls another function given that takes two arguments of the same generic type, that also cannot be changed. given does something, then returns an integer as a result. given can fail!

After calling given, if it failed, return acc - 1, if it succeeded, return its result + acc.

In C

C is a pretty simple language. I like simplicity (it’s the whole premise of this post, right?) but C’s simplicity turns into overly verbose code in the face of the requirements of fun. Here is the signature of given

// please ensure that lhs and rhs have the same type int given(int * result, void const * const lhs, void const * const rhs)

So, what’s going on here? In C, the dominant idiom for indicating success or failure is to return an error code, thus we return an int. However, this isn’t our return value! We use the out parameter result instead. Finally, we have lhs and rhs, which have the confusing types void const * const. These read as “constant pointer to constant void”, and ensures that neither the where the pointer points, or the value of what it points to can change. (thus documenting the requirement that it not change its arguments!) Finally, we have our comment asking the caller to pretty please, ensure lhs and rhs have the same type. There is no way in C to ensure two void * are actually the same type, so this is the best we can do… Now, let’s see my implementation of fun:

// please ensure that lhs and rhs have the same type int fun(int acc, void const * const lhs, void const * const rhs) { int res = 0; if (given(&res, lhs, rhs)) { return acc + res; } else { return acc - 1; } }

We have the same confusing sort of signature, except here the return value is our actual return value, and acc is not an out parameter. (which is really obvious, right?)

Inside of this function, we allocate res on the stack and initialize it to 0. Then we call given with the address of res, and lhs and rhs. Taking the address of a something requires a special symbol. This function is called within an if block because given returns 0 on failure and something on success.

Some of this noise can be reduced, but overall it’s pretty minimal. The use of void pointers and our type checking comment are troubling, but that’s not really the point of this post. However, the many semicolons, curly braces, and commas add a lot of clutter.

Noise level: Moderate
Strangeness: High
Confidence that there are no bugs in my implementation: Very Low

In C++

Next, let’s check out some C++. Here is the signature of given:

// throws an std::exception on failure! template <typename T> int given(const T & lhs, const T & rhs)

To me, this is kind of a wash from the C implementation. On one hand, we have this template <typename T> silliness, on the other hand we don’t have an out parameter, we only have one const per argument, and the compiler can actually enforce that lhs is of the same type as rhs. Next, the implementation:

template <typename T> int fun(int acc, const T & lhs, const T & rhs) { try { return acc + given<T>(lhs, rhs); } catch (std::exception & e) { return acc - 1; } }

Here we have that same yucky sort of signature, and we have these try and catch blocks. Personally, I don’t care for exceptions. However, they are a tried and true strategy accepted by the majority of the programming community, and who am I to dispute that? However, what I don’t like is the fact that we have no indication that given can throw. We had to read a comment. Additional weirdness here is the call to given: given<T>(lhs, rhs). Why do I have to do <T>?

The usual complaints about curly braces and semicolons apply here as well.

Noise Level: High
Strangeness: Low
Confidence that there are no bugs in my implementation: Low

In Rust

A newcomer to the scene is Rust. Rust is a low level systems programming language that has a very strong emphasis on safety. Excellent, right? Let’s see the signature of given:

fn given<T>(lhs: &T, rhs: &T) -> Option<i64>

… eew. We have twice as many angle brackets as the C++ implementation did, which is unfortunate. We’ve also added some colons. On the plus side, we have option types in rust, so no icky exceptions! Let’s see my implementation of fun:

fn fun<T>(acc: i64, lhs: &T, rhs: &T) -> i64 { let res = given(&lhs, &rhs); let ret = match res { Some(x) => acc + x, None => acc - 1, }; ret }

… and things get strange. Let’s go through this line by line:

fn fun<T>(acc: i64, lhs: &T, rhs: &T) -> i64: A bit noisier than I’d like, but perfectly reasonable.

let res = given(&lhs, &rhs);: Here we call given, and for some reason I have to put an & in front of lhs and rhs. At least rustc inferred the type for us!

let ret = match res {};: Yay, Rust has pattern matching! It’s a bit unfortunate about all those curly braces and semicolons though…

Some(x) => acc + x,: Nothing wrong here, in a world where commas and such are a thing…

None => acc - 1,: And here we have the last pattern of this match block. Why is there a comma there?! For reasons that science will never explain, in Rust, you have to put commas after the last entry in things like this! This oddity extends to structs and enums as well…

ret: Finally, we return. No, ret isn’t a keyword, it’s a variable that I bound in my pattern match. Notice the lack of a semicolon. In Rust, the last line in a function is the return value, and does not have a semicolon! However, rust has a return statement for early returns, and this does take a semicolon. Yes, you can use a return statement here, but according to the docs doing this makes you a bad person.

Noise Level: Very High
Strangeness: High
Confidence that there are no bugs in my implementation: Reasonable

In Haskell

Finally, let’s take a look at what I consider to be a reasonable syntax: Haskell. The signature of given is as follows:

given :: a -> a -> Maybe Int

Once you learn to read Haskell, you’ll see how simple this is. given is a function that takes an a, another a, and returns a Maybe Int. Next, let’s see my implementation of fun:

fun :: Int -> a -> a -> Int fun acc lhs rhs = case given lhs rhs of Just res -> acc + res _ -> acc - 1

Not counting the optional function signature, this is 3 lines. The first is our pattern match, which calls given. The second line handles success, and the third handles failure. There is no return statement here, the result of the expression is the return value. And unlike Rust, there’s no special case that breaks the mold.

Noise Level: Low
Strangeness: Low (If your definition of strange isn’t “doesn’t look like C”)
Confidence that there are no bugs in my implementation: High

Which Brings Me To My Point

Honestly, I believe that the reason for all of this is: “We’ll make our language look like C so that we don’t scare people away!” Personally, I believe that this is a sad state of affairs.

Strictly speaking, I do mean to criticize. C, C++, and Rust are all fine languages. They do what they set out to do, and do it well. Many people successfully use these languages every day! They are all languages worth knowing and languages worth using. However, there is no reason for all these glyphs and extra keywords!

My top feature for the new version of C++: Get rid of all uses of the angle bracket!

My top feature for the new version of Rust: Get rid of those trailing commas and the return statement!

Of course this will never happen, and for good reason: It will cause massive breakages in everybody’s codebases. But a man can dream…

Checking Our Heads With Liquid Haskell

Consider this function:

headInTail :: [a] -> [a] headInTail l = (tail l) ++ [head l]

Pretty straightforward, right? It takes a list, extracts the head and sticks it in the tail. Surely you’ve written something like this before. It should be fine, right?

*Main> headInTail [1,2,3] [2,3,1]

…checks out. Let’s try a few more:

*Main> headInTail "hello" "elloh" *Main> headInTail ["cat"] ["cat"]

…good. And the moment we’ve all been waiting for:

*Main> headInTail [] *** Exception: Prelude.tail: empty list

Oh yeah, head and tail don’t work for empty lists… Normally, we have some choices on how to proceed here. We could wrap the function in a Maybe:

maybeHeadInTail :: [a] -> Maybe [a] maybeHeadInTail [] = Nothing maybeHeadInTail l = Just $ headInTail l

…which introduces an annoying Maybe to deal with just to stick our heads in our tails. Or, we could just do something with the empty list:

headInTail :: [a] -> [a] headInTail [] = [] headInTail l = (tail l) ++ [head l]

…but what if returning the empty list isn’t the correct thing to do?

Another choice is to document this behavior (as head and tail do), and just never call headInTail []. But how can we guarantee that we never attempt to call this function on an empty list? Shouldn’t this be the type system’s problem?

Unfortunately, not all is roses and puppies. Sometimes the type system cannot help us. Sometimes somebody thought it’d be a good idea to use Haskell’s Evil exception system. Whatever the case, there are tools to help us.

Liquid Haskell

Liquid Haskell is a static code analysis tool that is used to catch just these sorts of problems. Liquid Haskell allows us to define invariants which will be enforced by the tool. Liquid Haskell is a research project that is still in development. As such, it has some rough spots, however it’s still very much capable of helping us with our problem here. But before we begin, we need to get the tool installed.

To install the tool, execute:

cabal install liquidhaskell

…simple right? Unfortunately, we’re not quite done. We need to install an SMT solver. This tool is used by Liquid Haskell. Currently, the tool defaults to Z3. I’m not sure how to use a different solver (and Z3 works just fine), so I suggest you you Z3. You’ll have to build Z3, and place the binary somewhere on the PATH. After this is done, and assuming your .cabal/bin directory is also on the PATH, testing your source file is a simple as:

liquid [FILE].hs

Let’s Have A Look

Create a haskell source file that contains the following:

headInTail :: [a] -> [a] headInTail l = (tail l) ++ [head l]

After that’s done, let Liquid Haskell analyze your file:

liquid [YOUR_FILE].hs

A bunch of stuff should scroll by, then in a second you’ll see something similar to the following:

**** UNSAFE ********************************************* Doop.hs:5:22: Error: Liquid Type Mismatch Inferred type VV : [a] | VV == l && len VV >= 0 not a subtype of Required type VV : [a] | len VV > 0 In Context VV : [a] | VV == l && len VV >= 0 l : [a] | len l >= 0

If you go to the line and column indicated, you’ll find the argument to tail. Conveniently, it seems that Liquid Haskell comes pre-loaded with definitions for some library functions. Normally, you’ll have to define those yourself. In fact, let’s do just that.

The next logical step here is to write a specification for our function. This specification is a statement about what sorts of values the function can take. Add the following to your source file, in the line above the signature for headInTail:

{-@ headInTail :: {l:[a] | len l > 0} -> [a] @-}

If you re-run liquid on your source file, you’ll see that the warning went away, and the program now indicates that your source is “SAFE”. So, what does this refinement mean?

Basically, these refinements are machine-checked comments. They have no impact on the program, they exist for Liquid Haskell. Think of it as being like an enhanced type signature. Like a normal type signature, we start with the name of the function, then two colons. This part, however:

{l:[a] | len l > 0}

…should be new. Basically, this part says that the list should not be empty. You should read it as “l is a [a] such that len l is greater than zero.” A lot of the notation used by Liquid Haskell comes from formal logic. Let’s break this down some more:

l:[a]

Here we bind a symbol, l, to the first list argument. At any point to the right of this symbol until the end of the scope defined by {}, we can reference this symbol.

{... | ...}

The pipe symbol indicates that we are going to make some statement about the type on the left hand side.

len l > 0

Here we state that the length of l must be greater than 0. It looks like we are calling a function, and we sort of are; len is a measure which is a special function that is used in specifications. However, the subject of measures is a post for another day.

You may now be thinking: “Well this is all well and good, but what’s to stop me from calling this function on an empty list?” To answer that, let’s implement main:

main = do i <- getLine putStrLn $ headInTail i

Add this to your source file, and then run liquid [YOUR_FILE].hs and you’ll notice that Liquid Haskell has a problem with your attempt to call headInTail:

**** UNSAFE ********************************************* Doop.hs:3:29: Error: Liquid Type Mismatch Inferred type VV : [Char] | VV == i && len VV >= 0 not a subtype of Required type VV : [Char] | len VV > 0 In Context VV : [Char] | VV == i && len VV >= 0 i : [Char] | len i >= 0

Liquid Haskell is telling you that it can’t prove that the length of i is greater than 0. If you execute your main function, you should see that it works as expected. Type in a string, and it’ll do the right thing. Push enter right away and you’ll get an exception.

*Main> main hello elloh *Main> main *** Exception: Prelude.tail: empty list

…ick… Let’s fix this:

main = do i <- getLine case i of [] -> putStrLn "Get your head checked." _ -> putStrLn $ headInTail i

Now if you analyze your file, Liquid Haskell should be happy. Honestly, you should be happy too: the tool caught this problem for you. It didn’t go to testing messed up, and the bug certainly didn’t escape testing unfound. Your program is now objectively better:

*Main> main isn't that neat? sn't that neat?i *Main> main Get your head checked.

Happstack’s “Helpful” Exception Handler: A Better Solution

Recently I wrote about Happstack’s mismanagement of exceptions. I offered up a solution thab basically amounted to swallowing the exception and returning mzero. As a follow-up to that post, I’d like to offer a better solution.

I believe Happstack is on the right track. An uncaught exception does in fact represent an internal server error, not a file not found, however Happstack misses the mark in a few ways. First, it prints the exception message, which for reasons I went into last week, is bad. And second, it doesn’t provide a mechanism to override this behavior.

It was suggested to me that I could place a monad on top of the ServerPartT transformer stack that re-implements fail. This represents a few issues for me. If I were to do this, I wouldn’t be able to use the basic ServerPart monad, greatly complicating my code as this locks me out of all library functions that take this type. Secondly, it’s an unnessesary level of indirection. Why should I add a monad to the stack that does nothing except re-implement fail? Why can’t I configure Happstack to use a custom exception response?

So, What Are You Going To Do About It?

Good question. I’ve come up with a solution that I’m fairly satisfied with. At the heart of this issue are IO actions that throw exceptions. To perform an IO action inside of a ServerPart, you must lift ServerPart‘s IO monad. This is done like so:

foo <- liftIO $ bar

This snippet executes the IO action bar and binds its result to foo. Since, typically speaking, only IO actions throw, this represents a good place to start working. We can insert a call to try here, but this can get tedious given enough IO actions. Why don’t we create a function?

tryIO :: Maybe (SomeException -> ServerPart Response) -> IO a -> ServerPart a tryIO mf io = do result <- liftIO $ try io case (result) of Right good -> return good Left exception -> handle exception mf where handle exception (Just handler) = escape $ handler exception handle _ Nothing = mzero

Meet my tryIO function. This function wraps liftIO and try into one nice and neat function. It even takes an optional response generator. Let’s take a look at this bit-by-bit.

tryIO :: Maybe (SomeException -> ServerPart Response) -> IO a -> ServerPart a

This function takes a function that takes a SomeException, and returns a ServerPart Response. This function is wrapped in a Maybe. The function also takes an IO action, and returns a ServerPart a. Basically, this works like a specialized version of liftIO. Unlike a vanilla liftIO, it can take an optional exception handler.

tryIO mf io = do result <- liftIO $ try io case (result) of Right good -> return good Left exception -> handle exception mf

Here we have the meat of this function. First, the IO action is wrapped in a call to try. Next this is promoted to a ServerPart via the call to liftIO. The result of this will be Either a SomeException, or a valid result. We use a case statement to examine the result, and either return the good result, or call handle and pass it the exception and the exception handler.

where handle exception (Just handler) = escape $ handler exception handle _ Nothing = mzero

Finally, we handle the exception. If an exception handler was passed in, it’s called, and then the response is returned to Happstack via escape. If no handler was passed in, the function returns mzero.

The function escape is very useful here. This function is basically like returning mzero, only instead of the response handler failing, it returns a ServerPart Response immediately. This allows you to break out of a deeply nested function easily without having to manually return from each function.

The result

The result of this new function is that I can use tryIO as I would have used liftIO in a ServerPart function. I can either call…

foo <- tryIO Nothing bar

…and have my response handler fail with mzero if an exception is thrown, or I can call…

foo <- tryIO (Just baz) bar

…and have my response handler fail and return the result of baz. baz could even do some cleanup and try to call the initial response handler over again if it wanted to! Currently, when an IO action fails in my application, users see this lovely error message:

none_of_your_business

Much better. Unless you’re a hacker!

Happstack’s “Helpful” Exception Handler

Lately I’ve been messing around with web development in Haskell using Happstack. I believe that web development is something that a pure functional language excels in. Web apps are inherently stateless, so it stands to reason that a stateless programming language would be a good fit.

Happstack provides many of the nice features one would expect of a web framework. Among these things is a top-level exception handler to prevent exceptions from bringing down the server. Suppose you try to call head on an empty list:

willThrow :: ServerPart Response willThrow = ok $ head []

This will of course throw an exception. Happstack “helpfully” catches it and produces this output:

bad_throw_1

Why the air quotes? Notice how Happstack prints the exception message? While this might seem somewhat benign with a simple empty list exception (maybe even helpful if you’re troubleshooting), imagine you’re doing something a little less contrived:

maliciousThrow :: ServerPart Response maliciousThrow = do dirs <- liftIO $ getDirectoryContents "/bar" ok $ toResponse $ show $ dirs

Once again Happstack airs out your dirty laundry.

bad_throw_2

In this case, it prints the fact that /bar doesn’t exist for the whole world to see. Great

I spent some time searching around for the proper way to deal with exceptions in Happstack. There doesn’t seem to be much other than “handle them”. Personally, I feel that if an unhandled exception is thrown, Happstack should treat it as mzero.

This can be accomplished pretty simply:

noThrow :: ServerPart Response noThrow = do dirs <- liftIO $ tryGDC "/bar" case (dirs) of Right d -> ok $ toResponse $ show $ d Left _ -> mzero where tryGDC :: String -> IO (Either SomeException [FilePath]) tryGDC a = try $ getDirectoryContents a

This function is similar to the previous maliciousThrow, except for the tryGDC function. This function uses the try function found within Control.Exception. Try attempts to perform some IO action, and returns Either an exception or a result, wrapped within an IO.

It is necessary to give tryGDC a function signature. Since functions can throw multiple exception types, the type checker cannot infer which is correct. In this case I’ve used the top-level exception class SomeException.

After trying, I check the result. On Right I return a ServerPart Response, on Left, I return mzero. Now when I attempt to access the page using this new version of maliciousThrow, I get this:

no_throw

As it should be. It’s nobody’s business what went wrong.

Best Practices

It should be noted that the function noThrow is equivalent in quality to the following snippet of Java:

public static ThingDoer newThingDoer () { try { return ThingDoerFactory.constructThingDoer(); } catch (Exception ex) { return null; } }

If you wrote that in a real application, you would be a Bad Person. Similarly, noThrow discards all info about what went wrong. You really should do something with it. Don’t show it to the user, but log it somewhere.

Update: I’ve posted a follow-up to this article, which can be found here!

DMP Photo Booth 1.0

Well, the day has come and gone. DMP Photo Booth’s final test on June 21st went off without issue, and DMP Photo Booth has left Beta and is now considered “production ready”. The initial 1.0 release can be found on GitHub.

The significance of June 21st is the very reason DMP Photo Booth was created; the 21st is the day of my wedding. My wife wanted a photo booth for the reception. We looked into renting a photo booth, but it turns out that they run around $1,000. I turned to open source. Some quick googling turned up some options, but they were all personal projects or out of date. Sure I could get somebody else’s project working, but what’s the fun in that? I decided that we didn’t need to rent one, or download one, I could build it!

In late 2013, I set to work in earnest. I had a couple of months of downtime in school, and since I’m not currently working it was the perfect time. I decided I had three main objectives for this project: get some arduino experience, get some GTK+ experience, and do this all as portably as possible. I had initially decided to mostly ignore GLib and focus on GTK, but slowly I grew to appreciate GLib for what it is: the standard library that C never had. First I used GModule to handle shared libraries in a portable manner. Next I decided to use GLib primitives to keep from having to deal with cross-platform type wonkiness. Next, having grown tired of dealing with return codes, I refactored the project to use GLib’s exception replacement: GError.

Lessons Learned

It’s not all roses and puppies though. There are certainly things I’d do differently. DMP Photo Booth is developed in an Object Oriented style, passing opaque structs with “method” functions that operate on them. Each component of the program are organized into their own source file with file scoped globals scattered throughout. Said globals are protected by mutexes to create a semblance of thread safety. That said, threading issues have been a major thorn in my side. Long story short: I regret this design choice. While I still feel that this is the correct way to structure C code, and that if globals are required, this is the correct way to handle them; I feel that I should have made more of an effort to limit side effects. Recently, I’ve spent some time doing functional programming, and if I could do it again I’d try to write in a more functional style. Fortunately for me, this is something that a little refactoring could help with.

Additionally, one thing I thought would be a major help is something that began to be a major thorn in my side: NetBeans. As the size of the project grew, NetBeans got slower and slower. It seemed that I spent more time fiddling with IDE settings than actually coding. Even worse is that the IDE-generated makefile is so convoluted that it’s extremely difficult to modify by hand in a satisfying way. I’ve always coded with and IDE so I wouldn’t have even considered not using one, but then I spent some time with Haskell. One of Haskell’s “problems” is that it doesn’t have good IDE support. It doesn’t seem like any IDE really handles it well, so most people use Emacs. Personally, I haven’t really warmed up to Emacs, but GEdit has syntax highlighting for Haskell and a built-in terminal for GHCI. GEdit also has syntax highlighting for C. Next time, I will seriously consider using a lighter-weight text editor for a C project. All this said, I think NetBeans for Java remains the way to go.

What’s Next

Like any program, version 1.0 is just one of many versions. There certainly remains a lot of work to do with DMP Photo Booth. Some major items you are likely to see whenever I get around to working on DMP Photo Booth some more:

Options Dialog

I think anybody who has seen it will agree: the options dialog in DMP Photo Booth is bad. It’s poorly organized, and kind of wonky. Personally, I modify settings using the .rc file, which is telling. This is certainly a high-priority improvement.

Functional Refactor

Like I said above, the code could use a pass to limit side effects. Funtions need to have their side effects limited, and globals need to be eliminated unless absolutely necessary. However, C is not a functional language. While one could argue that function pointers enable functional programming in C, this is a very pedantic argument. I won’t be going crazy with functional programming techniques. There will be no Monads, or for loops being turned into mappings of function pointers.

Optional Module API

An idea I’ve had on the back burner for a while is an optional module API. This would be used for very specific quality-of-life things. For instance, a module could provide a GTK widget to be shown in the options dialog. Any module that doesn’t want to implement any or all of the optional API can just ignore it. The module loading function will gracefully handle the dlsym failure, just treating it as it is: declining to implement the API. I have no plans to change the current existing API, so all you module developers can rest easy!

User Interface Module

It occurred to me that it might be good to have a UI module. This would provide the UI, and wouldn’t be tied to the trigger/printer/camera module start/stop system. This module would be loaded at startup and unloaded on shutdown. This would allow the Photo Booth to use different widget toolkits: QT, Curses, Cocoa, WinForms, or whatever else. Under this scheme, the current GTK+ interface would be abstracted into the reference UI Module.

Particularly Vexing Exceptions

If you’re a developer and you’ve been around the internet for a while, you may have read Eric Lippert’s Vexing Exceptions. If you haven’t, you should go do that, it’s a good read.

Back? Ok then. In the article, the author talks about a situation with C#’s Int32.Parse method. Apparently in C#, the method to parse a string to an int throws an exception upon failure. Because this was so ‘vexing’, the language team later implemented Int32.TryParse that returns a boolean upon success or failure, and has an out parameter to return the actual parsed int.

Personally, given those two options, I prefer the original parse function that can throw. I don’t like out parameters, and checking the boolean is just as irritating as catching a parse exception. However, C# is a language without the Maybe monad.

Unfortunately for us, Haskell’s read function also throws an exception instead of returning Maybe a. Unlike the C# example, this is actually vexing because in Haskell, you can only catch exceptions in the IO monad. So what to do?

After some searching online, I found the answer. There is a function in Text.Read:

readMaybe :: Read a => String -> Maybe a

As it’s name would imply, readMaybe attempts to parse a string into some other type, and wraps it in a Just upon success, or returning Nothing.

%d bloggers like this: