Swift vs Kotlin
Dropbox wrote a candid and insightful post titled The (not so) hidden cost of sharing code between iOS and Android. It's a common dream to have "one codebase to rule them all" but reality intruded, not only for DropBox, but on projects I have worked on as well.
Dropbox needed to support both Android and iOS devices, so instead of writing for each platform in Java and Objective C respectively, they labored to produce a layer of C++ code that worked for both. But success was hard to come by, and in their own words:
By writing code in a non-standard fashion, we took on overhead that we would have not had to worry about had we stayed with the widely used platform defaults. This overhead ended up being more expensive than just writing the code twice.
I would add, from my own experience, that a "generic code layer" targets the lowest common denominator, and fails to take full advantage of native device features. Add that Apple and Google are continuously improving their tool chain -- Xcode and Swift, Android Studio and Kotlin -- and you miss out on those developments as well.
Xcode and Android Studio are both robust environments, complete with a text editor, hooks to version control, and connections to emulators. Interestingly, the GUI editor in Xcode is referred to as a storyboard, a common term in the movie and animation business. In Android Studio, it's called a layout editor and the blue theme and markings are reminiscent of an architect's blueprints. Indeed, Apple is known for its artistic side while Google is known for its technical side.
A more significant difference is how iOS and Android interpret device rotation. Under iOS, the app loads the horizontal storyboard and continues where it left off from portrait mode. Under Android, however, the app loads its horizontal layout and is restarted. The memory of the app is reset, and you need to save and restore your instance state if you want the illusion of continuity. In addition, the GUI elements need to be refreshed to properly reflect the state you choose.
Regarding the native languages, Swift has a light C/C++ feel whereas Kotlin is described to me as a concise and safe derivative of Java (not an expert in Java, my opinion doesn't count). Here's what I learned from writing LuldCalc:
if statement
Swift: does not need parens around the condition.
if condition {}
Kotlin:
if (condition) {}
enum
Swift:
Kotlin: as a matter of style, Kotlin insists that enumerations begin with a capital letter.
Swift: unlike C, Swift does not need a break statement between cases.
Dropbox needed to support both Android and iOS devices, so instead of writing for each platform in Java and Objective C respectively, they labored to produce a layer of C++ code that worked for both. But success was hard to come by, and in their own words:
By writing code in a non-standard fashion, we took on overhead that we would have not had to worry about had we stayed with the widely used platform defaults. This overhead ended up being more expensive than just writing the code twice.
I would add, from my own experience, that a "generic code layer" targets the lowest common denominator, and fails to take full advantage of native device features. Add that Apple and Google are continuously improving their tool chain -- Xcode and Swift, Android Studio and Kotlin -- and you miss out on those developments as well.
Xcode and Android Studio are both robust environments, complete with a text editor, hooks to version control, and connections to emulators. Interestingly, the GUI editor in Xcode is referred to as a storyboard, a common term in the movie and animation business. In Android Studio, it's called a layout editor and the blue theme and markings are reminiscent of an architect's blueprints. Indeed, Apple is known for its artistic side while Google is known for its technical side.
A more significant difference is how iOS and Android interpret device rotation. Under iOS, the app loads the horizontal storyboard and continues where it left off from portrait mode. Under Android, however, the app loads its horizontal layout and is restarted. The memory of the app is reset, and you need to save and restore your instance state if you want the illusion of continuity. In addition, the GUI elements need to be refreshed to properly reflect the state you choose.
Regarding the native languages, Swift has a light C/C++ feel whereas Kotlin is described to me as a concise and safe derivative of Java (not an expert in Java, my opinion doesn't count). Here's what I learned from writing LuldCalc:
if statement
Swift: does not need parens around the condition.
if condition {}
Kotlin:
if (condition) {}
enum
Swift:
enum operation
{
case none
case add, subtract, multiply, divide
case equal
}
}
enum class Operation
{
{
None, Add, Subtract, Multiply, Divide, Equal }
switch
Swift: unlike C, Swift does not need a break statement between cases.
switch opKey {
case.add:
refPrice = savedRefPrice + refPrice
case.subtract:
refPrice = savedRefPrice - refPrice
case.multiply:
refPrice = savedRefPrice * refPrice
case.divide:
refPrice = savedRefPrice / refPrice
case .none:
print ("opKey is none")
case .equal:
print ("opKey is equal")
}
Kotlin: uses "when" with a similar benefit of not requiring a break statement.
when(opKey) {
Operation.Add -> refPrice = savedRefPrice + refPrice
Operation.Subtract -> refPrice = savedRefPrice - refPrice
Operation.Multiply -> refPrice = savedRefPrice * refPrice
Operation.Divide -> refPrice = savedRefPrice / refPrice
Operation.None -> print("opKey is None")
Operation.Equal -> print("opKey is Equal")
}
Function returning multiple values
Swift: Functions are declared starting with "func" and the return values are identified at the end, following the ->.
when(opKey) {
Operation.Add -> refPrice = savedRefPrice + refPrice
Operation.Subtract -> refPrice = savedRefPrice - refPrice
Operation.Multiply -> refPrice = savedRefPrice * refPrice
Operation.Divide -> refPrice = savedRefPrice / refPrice
Operation.None -> print("opKey is None")
Operation.Equal -> print("opKey is Equal")
}
Function returning multiple values
Swift: Functions are declared starting with "func" and the return values are identified at the end, following the ->.
func getDelta (refPrice: Double, tier: Int, multiplier: Int)->(delta:Double, percent:Double)
{
var percent: Double = 0.0
var delta: Double = 0.0
. . .
return (delta, percent)
}
}
The code to call getDelta() and obtain the return values looks like this:
let price = getDelta (refPrice: refPrice, tier: tier, multiplier: bandMultiplier)
print ("Delta is \(price.delta)")
print ("Percent is \(price.percent)")
Kotlin: You need to first define a data class that will hold the return values, then append the data class to the end of the function declaration.
data class Delta(var delta: Double, var percent: Double) fun getDelta (refPrice: Double, tier: Int, multiplier: Int): Delta { var percent = 0.0 var delta = 0.0 . . . return Delta (delta, percent)
}
The code to call getDelta() and obtain the return values looks like this:
var (delta, percent) = getDelta(refPrice, tier, bandMultiplier) print ("delta is $delta") print ("precent is $percent")
Swift has the cleaner implementation, not just compared to Kotlin, but to C/C++ as well.
Nan and Infinity
Both Swift and Kotlin handle Nan (not a number) and Infinity in the same way. Swift: if price.isNaN || price.isInfinite { // ERROR }
Kotlin: if (price.isNaN() || price.isInfinite()) { // ERROR }
Int to Double
Swift: uses a cast like C
(Double)(multiplier)Kotlin: uses a function multiplier.toDouble()Cool difference in for loop
Swift: This will loop from 1 to n, without a need for a counter. Swift beats C.
for _ in 1...n { roundFactor *= 10 }
Kotlin: repeat will do the same, but more concisely. Kotlin beats Swift.repeat(n) { roundFactor *= 10}Ternary Operation
Swift: behaves like C.refPrice = (Double)(refPriceStr) ?? 0.0Kotlin: will crash on .toDouble() if refPriceStr is non-numeric. refPrice = if (refPriceStr.isNotEmpty()) refPriceStr.toDouble() else 0.0 Therefore, exception handling is needed. try { refPrice = refPriceStr.toDouble() } catch (e: NumberFormatException) { refPrice = 0.0 }This last example makes it easy for me to declare Swift as the prettier and more approachable language.
The photo on top was inspired by this image on the right: "Three Apples that changed the world." Knowing my fondness for Apple, a friend sent this to me with a helpful translation: "Newton's Apple, Eve's Apple, and Steve's Apple."
Comments