HERE'S HOW YOU CAN USE SWITCH CASES IN LUA
       
 (IMG) iillustration-9.png
       
       Kidding! You can't! Lua doesn't have a `switch' operator. Instead, it
       has tables. And tables are actually much more interesting, and far
       easier to work into a routine that requires evaluating statements
       based on conditions. Don't believe me? Here's an example of how I've
       put tables to use.
       
       The context: I'm building a RSS reader for KOReader. Sometimes the RSS
       reader needs to fetch a web page, which it then parses, deconstructs,
       and re-builds as an EPUB. To re-build the web page into an EPUB, I
       create objects for each of the website's components, like the HTML
       document and any images it contains. I call these "items". Different
       types of items have different private methods, but they all share the
       same two data points: `path' and `content'. Because all items share
       these two data points, I've decided to make a common interface for
       their construction: `ItemFactory'.  Supplying the `makeItem' method
       within `ItemFactory' with the item's `path' and `content' will
       "automatically" construct the item with the appropriate constructor.
       
       How? First: a file extension is derived from the item's `path.' This
       value is matched against the `ITEM_TYPES' table. The keys of this
       table represent the supported item types. The values for each key
       represent the item type's supported file formats (given as
       extensions). When a match is found, the table key is stored in a
       variable. Next, (and this is the exciting part) that variable's value
       is used as an index into the `ITEM_CONSTRUCTORS' table, which contains
       constructors for each supported item type. The indexed constructor is
       returned and then supplied with the `path' and `content' data that was
       passed to the factory.
       
       Cool, right? What I love so much about this no-switch switch-like
       logic is that the `makeItem' method basically reads like a unit
       test. It stays focused on returning errors when conditions aren't
       met. The actually divining of what code gets evaluated, and what that
       code does/looks like gets tucked away into a table. Extending the code
       is simple, maintaining the code is clear. It's bliss!
       
       ,----
       | local ItemFactory = {
       | 
       | }
       | 
       | ItemFactory.ITEM_TYPES = {
       |    xhtml = XHtmlItem.SUPPORTED_FORMATS,
       |    image = Image.SUPPORTED_FORMATS
       | }
       | 
       | ItemFactory.ITEM_CONSTRUCTORS = {
       |    xhtml = function(path, content)
       |       return XHtmlItem:new{
       |          path = path,
       |          content = content,
       |       }
       |    end,
       |    image = function(path, content)
       |       return Image:new{
       |          path = path,
       |          content = content
       |       }
       |    end
       | }
       | 
       | function ItemFactory:makeItem(path, content)
       |    local suffix = util.getFileNameSuffix(
       |       string.lower(path)
       |    )
       | 
       |    local matched_type = ItemFactory:getItemTypeFromFileNameSuffix(suffix)
       |    if not matched_type
       |    then
       |       return false, EpubError.ITEMFACTORY_UNSUPPORTED_TYPE
       |    end
       | 
       |    local item_constructor = ItemFactory.ITEM_CONSTRUCTORS[matched_type]
       |    if not item_constructor
       |    then
       |       return false, EpubError.ITEMFACTORY_NONEXISTENT_CONSTRUCTOR
       |    end
       | 
       |    return item_constructor(path, content)
       | end
       | 
       | function ItemFactory:getItemTypeFromFileNameSuffix(suffix)
       |    local matched_item_type = nil
       |    for item_type, supported_formats in pairs(ItemFactory.ITEM_TYPES) do
       |       if supported_formats[suffix]
       |       then
       |          matched_item_type = item_type
       |          break
       |       end
       |    end
       |    return matched_item_type
       | end
       | 
       | return ItemFactory
       `----