Kotlin: Is there a way to clean up number overloads? - numbers

Often I find myself creating lots of overloads for number types because Kotlin doesn't do implicit conversions for non-literals. This results in a huge amount of duplicate overload functions which is tons and tons of boilerplate.
An example of the pain I have doing this can be seen here: https://github.com/Jire/Arrowhead/blob/master/src/main/kotlin/org/jire/arrowhead/Source.kt
I understand the reason why implicit conversions can cause bugs, but I think in most cases, especially for "enlargement" conversions like Byte -> Int and Int -> Long where data isn't lost there should be a better way.
So... my question is how do you deal with this? Are there any creative ways to solve this problem?

Answering your question: you can use a generic function with Number. Then it will accept any subtype of Number. Then you can convert the value into any other numeric type:
fun boo(x: Number) {
val y = x.toLong()
println(y is Long)
}
The only downside of this is autoboxing, but that should not matter for your case.
Regarding the code you posted: I believe you have some architectural errors which cause this situation. Here is your API without too much details:
interface Source {
fun read(address: Long, data: Pointer, bytesToRead: Int)
fun read(address: Int, data: Pointer, bytesToRead: Int) = read(address.toLong(), data, bytesToRead)
fun read(address: Long, data: Memory, bytesToRead: Int = data.size().toInt()) = read(address, data as Pointer, bytesToRead)
fun read(address: Int, data: Memory, bytesToRead: Int = data.size().toInt()) = read(address.toLong(), data, bytesToRead)
fun read(address: Long, struct: Struct, bytesToRead: Int = struct.size()) = read(address, struct.pointer, bytesToRead)
fun read(address: Int, struct: Struct, bytesToRead: Int = struct.size()) = read(address.toLong(), struct, bytesToRead)
fun read(address: Long, bytesToRead: Int): Memory = TODO()
fun read(address: Int, bytesToRead: Int) = read(address.toLong(), bytesToRead)
fun byte(address: Long, offset: Long = 0) = read(address, 1).getByte(offset)
fun byte(address: Int, offset: Long = 0) = byte(address.toLong(), offset)
fun short(address: Long, offset: Long = 0) = read(address, 2).getShort(offset)
fun short(address: Int, offset: Long = 0) = short(address.toLong(), offset)
fun char(address: Long, offset: Long = 0) = read(address, 2).getChar(offset)
fun char(address: Int, offset: Long = 0) = char(address.toLong(), offset)
fun int(address: Long, offset: Long = 0) = read(address, 4).getInt(offset)
fun int(address: Int, offset: Long = 0) = int(address.toLong(), offset)
fun long(address: Long, offset: Long = 0) = read(address, 8).getLong(offset)
fun long(address: Int, offset: Long = 0) = long(address.toLong(), offset)
fun float(address: Long, offset: Long = 0) = read(address, 4).getFloat(offset)
fun float(address: Int, offset: Long = 0) = float(address.toLong(), offset)
fun double(address: Long, offset: Long = 0) = read(address, 8).getDouble(offset)
fun double(address: Int, offset: Long = 0) = double(address.toLong(), offset)
fun boolean(address: Long, offset: Long = 0) = byte(address, offset).unsign() > 0
fun boolean(address: Int, offset: Long = 0) = boolean(address.toLong(), offset)
fun write(address: Long, data: Pointer, bytesToWrite: Int)
fun write(address: Int, data: Pointer, bytesToWrite: Int) = write(address.toLong(), data, bytesToWrite)
fun write(address: Long, data: Memory, bytesToWrite: Int = data.size().toInt())
= write(address, data as Pointer, bytesToWrite)
fun write(address: Int, data: Memory, bytesToWrite: Int = data.size().toInt())
= write(address.toLong(), data, bytesToWrite)
fun write(address: Long, struct: Struct, bytesToWrite: Int = struct.size())
= write(address, struct.pointer, bytesToWrite)
fun write(address: Int, struct: Struct, bytesToWrite: Int = struct.size())
= write(address.toLong(), struct, bytesToWrite)
// ...
}
This API works with Long for address, but also accepts Int for some reason. I think you should peek one (e.i Long) and let the consumer worry about converting Int to Long. This is not a responsibility of an API. Besides, if a consumer works with an API which uses Long for address, he will usually use Long to manipulate with addresses on his side too. This simplifies the API and saves on Int to Long and back conversions, which improves the performance.

Related

Terminated by signal 4

Already checked other question on this topic, and I can't seem to utilize it to resolve my issue, so I'm creating a new question in order to see if I can't gain some insight on this issue and help others who may run into this using the Online Swift Playground.
Getting Terminated by signal 4 using the following code:
import Foundation
//enter equation here
var equation: String = "2 +( 3* 4)/ 2+22 ="
var equationWithoutWhitespace = equation.filter {!$0.isWhitespace}
//converts String equationWithoutWhitespace to array of Charcters e
let e = Array(equationWithoutWhitespace)
func add(_ firstVal: Int, _ secondVal: Int) -> Int {return Int(firstVal + secondVal)}
func sub(_ firstVal: Int, _ secondVal: Int) -> Int {return Int(firstVal - secondVal)}
func mul(_ firstVal: Int, _ secondVal: Int) -> Int {return Int(firstVal * secondVal)}
func div(_ firstVal: Int, _ secondVal: Int) -> Int {return Int(firstVal / secondVal)}
func power(_ firstVal: Double, _ secondVal: Double) -> Int {return Int(pow(firstVal,secondVal))}
func root(_ firstVal: Double, _ secondVal: Double) -> Int {return Int(pow(firstVal,1/secondVal))}
func checkParenthesis(_ equation: [Character]) -> (low: Int, high: Int){
var low = 0
var high = 0
for (index,value) in equation.enumerated() {
if(equation[index] == "("){
low = index
}
else if(equation[index] == ")"){
high = index
}
}
return (low, high)
}
func doMath(firstVal: Character, op: Character, secondVal: Character) -> Int {
var firstVar: Int! = Int("\(firstVal)")
var secondVar: Int! = Int("\(secondVal)")
switch op {
case "+":
return add(firstVar,secondVar)
case "-":
return sub(firstVar,secondVar)
case "*":
return mul(firstVar,secondVar)
case "/":
return div(firstVar,secondVar)
case "x",
"X":
var firstV: Double! = Double("\(firstVar)")
var secondV: Double! = Double("\(secondVar)")
return power(firstV,secondV)
case "r",
"R":
var firstV: Double! = Double("\(firstVar)")
var secondV: Double! = Double("\(secondVar)")
return root(firstV,secondV)
default:
print("error with operation detection")
return 0
}
}
//create new equation
var e2 = e
//get index of parenthesis & operation
var low = checkParenthesis(e2).low
var high = checkParenthesis(e2).high - 1
var op = low + 1
//if there were parenthesis, do this
if(low != 0 && high != 0){
//remove parenthesis
e2.remove(at: checkParenthesis(e2).low)
e2.remove(at: checkParenthesis(e2).high)
print(doMath(firstVal: e2[low],op: e2[op],secondVal: e2[high]))
}
Edit: this is a partial snippet of the complete project, it is essentially a text based calculator but it utilizes different rules than normal PEMDAS
I was looking over it again today, and I found using print(e2[low], e2[op], e2[high], low, op, high), I was able to check what values I was getting for my command, and realized I was 1 position off, because earlier I was compensating for removing the parenthesis, but later moved that function further down in the program. Because of this, var high = checkParenthesis(e2).high - 1 was 1 value off and not giving me an integer, but instead a character. Changing the - 1 to - 2 fixed the issue and everything works as it should. Thanks to everyone for your help!

Can't find variable name in scope

I am trying to learn Swift and I have bought a book to help me learn the language.
I can't understand why the following does not work:
func sum(_a: Int, _b: Int) -> Int {
return a + b
}
func subtract(_a: Int, _b: Int) -> Int{
return a - b
}
var someFunc: (Int, Int) -> Int
someFunc = sum
print(someFunc(5, 4))
someFunc = subtract
print(someFunc (5, 4))
The error I get is Cannot find 'a' (or 'b') in scope.
If I remove the underscores it does give the right answer.
I thought the point of the underscore was that the underscore meant that nothing is assigned to it and the function you want to call that returns a result but you don't care about the returned value.
Can somebody explain in simple language why this does not work.
You have to put a space between _ a, _ b. Like this:
func sum(_ a: Int, _ b: Int) -> Int {
return a + b
}
func subtract(_ a: Int, _ b: Int) -> Int{
return a - b
}
var someFunc: (Int, Int) -> Int
someFunc = sum
print(someFunc(5, 4))
someFunc = subtract
print(someFunc (5, 4))
You can learn these functions in a Playground. You will see there errors, etc...
The underscore means that the parameter will not have a label when calling then function making it more compact.
Below is 3 different ways to use labels for parameters when creating a function
Function with anonymous (no label) parameters
func example1(_ a: Int, _ b: Int) -> Int {
a + b
}
let sum = example1(3, 5)
Function with parameters as labels
func example2(a: Int, b: Int) -> Int {
a + b
}
let sum = example2(a: 3, b: 5)
Function with different parameter names and labels
func example3(first a: Int, second b: Int) -> Int {
a + b
}
let sum = example3(first: 3, second: 5)
When declaring functions in Swift, you can provide names for parameters passed to a function. It is handy to make your functions more readable when using in code. E.g. you can declare it like so:
func move(from startPoint: Int, to endPoint: Int) -> Int {
return startPoint + endPoint
}
In your function's body you can use variables' names, which is quite understandable for you. And usage of your functions will look like:
res = move(from: 1, to: 2)
I this way it will be more readable for any person who will read or use your code. It will be more clear even for you, when you'll return to this code some time later.
You can also declare the function in the way not to show any variables' names at all. For this you can use "_" as a variable's name. And this is the case from your learning book.
Guys have already answered your question. I just wanted to give you a bit deeper understanding.

Nested function techniques for different "flow paths" in swift

I'm learning object oriented things and trying to incorporate nested functions into my code so I can gain understanding of how these different operations flow and work, specifically nested functions.
I want to pass values from one function to another then another and, depending on the calculations within each nested func, output certain final numbers. I'm having trouble understanding how to grab and re-declare return values inside a method so they can be used again.
Crude single nested example:
func increaseNumbers(numOne: Double, numTwo: Double) -> (Double, Double) {
var numOneIncreased = numOne + 2
var numTwoIncreased = numTwo + 5
func playWithNumbersMore(warpOne: Double, warpTwo: Double) -> (Double, Double) {
if warpOne < 50 {
var adjustedOne = warpOne + 16.5
var adjustedTwo = warpTwo + 20.8
} else { do nothing... }
return (adjustedOne, adjustedTwo)
}
playWithNumbersMore(warpOne: numOneIncreased, warpTwo: numTwoIncreased)
// How do i re-assign the return values inside playWithNumbersMore?
return (something, somethingTwo)
}
Crudely speaking this is what I want to do if possible:
func increaseNumbers(numOne: Double, numTwo: Double) -> (Double, Double) {
var numOneIncreased = numOne + 2
var numTwoIncreased = numTwo + 5
func playWithNumbersMore(warpOne: Double, warpTwo: Double) -> (Double, Double) {
if warpOne < 50 {
var adjustedOne = warpOne + 16.5
var adjustedTwo = warpTwo + 20.8
} else { do nothing... }
return (adjustedOne, adjustedTwo)
}
// I want to be able to take return values and do more with them... as well as redefine them
// on completion of final "parent function"
// Sort of like this:
var newNumbToPlayOne = adjustedOne
var newNumbToPlayTwo = adjustedTwo
func playMoreWithNewNumbers...
}
Is this possible or am I off the rails?
func increaseNumbers(numOne: Double, numTwo: Double) -> (Double, Double) {
var numOneIncreased = numOne + 2
var numTwoIncreased = numTwo + 5
func playWithNumbersMore(warpOne: Double, warpTwo: Double) -> (Double, Double) {
if warpOne < 50 {
var adjustedOne = warpOne + 16.5
var adjustedTwo = warpTwo + 20.8
return (adjustedOne, adjustedTwo)
}
let result = playWithNumbersMore(warpOne: numOneIncreased, warpTwo: numTwoIncreased)
numOneIncreased = result.0 // result.0 is a adjustedOne
numTwoIncreased = result.1 // result.1 is a adjustedTwo
return result
}
This is how you can use the result of playWithNumbersMore data.
Am I wrong or it is what a are look for?

Swift: How to reorder and omit parameters in functions stored in variables

I am somewhat familiar with storing and passing around functions in Swift, however I have a few specific questions on the behavior of the language in this regard.
Say we have a variable function MathOperation:
var mathOperation: (Double, Double) -> Double
Now suppose we are setting this to the function Subtract:
func subtract (minuend: Double, subtrahend: Double) -> Double {
return minuend - subtrahend
}
mathOperation = subtract
We should then be able to call subtract with
let result = mathOperation(3, 4.222)
But what if we want to pass in a function that has more parameters, or differently ordered parameters than the declaration of mathOperation calls for? For instance:
func divide (dividend: Double, divisor: Double, roundToInt: Bool = false) -> Double { ... }
How can I set mathOperation to divide in such a manner that roundToInt is ignored?
Also, is it possible to re-order the arguments? Say we have an exponentiation function in a library where it cannot be modified:
func exponentiate (power: Double, base: Double) -> Double { ... }
It is unusual to have the power before the base, and let's say that where mathOperation is used, we need to call it as though it were declared with (base: Double, power: Double).
Is there a way to set mathOperation to exponentiate so that the parameters are reversed when it is called?
One final question. Let us say we have an interpolation function that we want to set mathOperation to:
func interpolate (start: Double, end: Double, by: Double, nonlinearity: (Double) -> Double) -> Double { ... }
Is there a way to set mathOperation to interpolate so that
mathOperation (a, b)
results in
interpolate (start: a, end: b, by: 0.5, nonlinearity: { $0 })
If any of these are possible, it would be ideal if someone could direct me to the official documentation where this is explained.
For your interpolate case (the other cases follow) just define the following:
mathOperation = { interpolate (start: $0, end: $1, by: 0.5, nonlinearity: { $0 })}
Essentially you wrap interpolate in a closure where some of the arguments are fixed, such as by to 0.5 in this example. (This is referred to as 'partial application')
You can also generalize this with something like the following:
func interpolateToMathOperation (by: Double, nonlinearity: #escaping (Double) -> Double) -> (Double, Double) -> Double {
return { interpolate (start: $0, end: $1, by: by, nonlinearity: nonlinearity)}
}
The above returns a mathOperation for interpolate given the default by and nonlinearity arguments.
In action:
// Just add - only an example
1> func interpolate (start: Double, end: Double, by: Double, nonlinearity: (Double) -> Double) -> Double { return start + end }
6> func interpolateToMathOperation (by: Double, nonlinearity: #escaping (Double) -> Double) -> (Double, Double) -> Double {
7. return { interpolate (start: $0, end: $1, by: by, nonlinearity: nonlinearity)}
8. }
9> var mathOperation = interpolateToMathOperation (by: 0.25, nonlinearity: { $0 })
mathOperation: (Double, Double) -> Double = 0x00000001005ea670 $__lldb_expr15`partial apply forwarder for __lldb_expr_14.(interpolateToMathOperation (by : Swift.Double, nonlinearity : (Swift.Double) -> Swift.Double) -> (Swift.Double, Swift.Double) -> Swift.Double).(closure #1) at repl14.swift
10> mathOperation(1,2)
$R1: Double = 3

Scala - strange compile error (multiple overloaded alternatives of a method define default arguments)

In Scala IDE I get the following error about the class I am to compile:
in object MapArea, multiple overloaded alternatives of method addAnim
define default arguments.
So yes, They do! So what? I do not understand the philosophy of this...
UPDATE:
It turns out that there could be a situation where compiler can't know which method to choose (as pointed out by Tomasz Nurkiewicz), ok I understand.. but in my situation these two methods can clearly be distinguished. Here is the exact piece of code (with all original names and stuff preserved this time):
def addAnim (name: String, x: Float, y: Float, tex: Buffer[Texture], fps: Int, percent: Float = 0): TImageSequence =
addAnim (name, x, y, tex(0).getImage.getWidth, tex(0).getImage.getHeight, tex, fps, percent)
def addAnim (name: String, x: Float, y: Float, w: Float, h: Float, tex: Buffer[Texture], fps: Int, percent: Float = 0): TImageSequence = {
// do stuff
}
It isn't possible to have two methods with default parameters and with the same name.
Scala generates methods to obtain default values with names based on target method's name, so some sort of name collision may occur.
scala> object Test {
| def m(i: String = "Default value") {}
| }
defined module Test
scala> Test.`m$default$1`
res0: String = Default value
You are not showing your code, but here is a simple example:
object C {
def addAnim(x: Int = 42) {}
def addAnim(y: String = "abc") {}
}
If I now call:
C.addAnim()
which method should be invoked? The object C won't compile because the compiler is not capable of guessing which addAnim method do you mean when not providing any argument.
Why not combine both methods in one by making w and h optional as well, e.g.
def addAnim (name: String,
x: Float, y: Float,
tex: Buffer[Texture],
fps: Int,
percent: Float = 0,
w: Float = Float.NaN, h:Float = Float.NaN): TImageSequence