I have written some Swift for the first time, being competent enough in Javascript and having some experience in Ruby and Python. For my education, I've written a function that parses a roman numeral string and returns its integer representation, first in Javascript (ES2015+):
const dict = [ ['CM', 900], ['M', 1000], ['CD', 400], ['D', 500], ['XC', 90], ['C', 100], ['XL', 40], ['L', 50], ['IX', 9], ['X', 10], ['IV', 4], ['V', 5], ['I', 1], ] function romanToInt (original) { let temp = original let int = 0 while (temp.length > 0) { let found = false for (const [glyph, quantity] of dict) { if (temp.startsWith(glyph)) { int += quantity temp = temp.slice(glyph.length) found = true break } } if (!found) { // e.g. Error parsing roman numeral "MDCCLXXVI," at "," throw new Error(`Error parsing roman numeral "${original}" at "${temp}"`) } } return int } try { romanToInt('MMXIV') // => 2014 } catch (err) { console.error(err) }
and then ported it to Swift 4:
let dict: [( glyph: String, quantity: Int )] = [
("CM", 900), ("M", 1000), ("CD", 400), ("D", 500),
("XC", 90), ("C", 100), ("XL", 40), ("L", 50),
("IX", 9), ("X", 10), ("IV", 4), ("V", 5),
("I", 1)
]
enum RomanNumericError: Error {
case badInput(original: String, temp: String)
}
func romanToInt(original: String) throws -> Int {
var temp = original
var int = 0
while temp.count > 0 {
var found = false
for (glyph, quantity) in dict {
if temp.starts(with: glyph) {
int += quantity
temp.removeFirst(glyph.count)
found = true
break
}
}
guard found == true else {
throw RomanNumericError.badInput(original: original, temp: temp)
}
}
return int
}
do {
try romanToInt(original: "MMXIV") // => 2014
} catch RomanNumericError.badInput(let original, let temp) {
print("Error parsing roman numeral '\(original)' at '\(temp)'")
}
I'm wondering about how swift-y my code is in terms of design patterns, especially in terms of error handling. In Javascript, throwing and catching errors is a very common control flow design, and I'm wondering if I'm approaching it from the right angle in Swift.