I have a Vec2 class in kotlin.
I overloaded the operator * like this:
operator fun times(v:Float): Vec2 {
return Vec2(this.x * v, this.y * v)
}
End the behavior is just as I expected, I can use * and *= to scale the vector
var a = Vec2() * 7f; a *= 2f
However, from my understanding what I do here, is I create a new object, by calling Vec2(), every time I use *
Even if I use *= and I do not really need to return anything, as I could just edit the object itself (using this keyword)
Is there any way to overload the *= operator, so that it has the similar behavior to this function?
fun mul(v:Float) {
this.x *= v; this.y *= v
}
I need my application to run smoothly, and these operators are used quite a lot,
I do not want any lags caused by garbage collector's work.
There is no need to create a new object, you should just change your x and y to var's so they become reassignable.
Doing this will most likely end you up with something like this:
class Vec2(var x: Float, var y: Float) {
operator fun times(v: Float) {
x *= v
y *= v
}
}
Then in your implementation it is as simple as:
val a = Vec2(1.0f, 1.0f)
a * 2f
// After this line both x and y are 2.0f
If you really want to overload the *= operator then add the timesAssign operator function instead for more info see the kotlin docs
Related
I had to swap 2 numbers in one line expression using no other variable except x and y.
So I wrote the following .c program to swapp two numbers with the given conditions and it works like charm.
int main() {
int x =5, y =2;
x = y-x+(y=x);
printf("X=%d, y=%d", x, y);
return 0;
}
But when i try to do the same in kotlin it gives me an error that
Assignments are not expressions, and only expressions are allowed in
this context,
I can resolve this issue by introducing a third variable just like this. But I'm not allowed to have any other variable except x and y which are already given. So is there any other way I can do this in one line using any kotlin property?
Below is the kotlin program
fun main() {
var x = 5
var y = 10
x = y-x+(y=x)
println("X = $x, Y = $y")
}
While I have two suggestions below, I want to start with a recommendation against either of them, at least in this simple example.
It's usually a lot more clear to optimise code for developers to read in the following ways:
create an extra variable with a descriptive name
prefer val over var to avoid accidental mutations
and try to make the code 'linear', so the operations can be read from top-to-bottom without jumping between functions
avoid code that needs an IDE to see what the type-hints are
And I'll trust that the compiler will make make the code performant.
fun main() {
val x = 5
val y = 10
val newX = y
val newY = x
println("X = $newX, Y = $newY")
}
Local function
You could use a local function to perform the swap, as the function will still be able to access the original values.
fun main() {
var x = 5
var y = 10
fun swap(originalX: Int, originalY: Int) {
y = originalX
x = originalY
}
swap(x, y)
println("X = $x, Y = $y")
}
Scope function
This could be code-golfed into one line
use to to create a Pair<Int, Int>,
and a scope function to use the result.
fun main() {
var x = 5
var y = 10
(x to y).apply { x = second; y = first }
println("X = $x, Y = $y")
}
One line? Yes. More difficult to read? I think so.
I have a multiplication operator override in my base class
open class Tuple(
open val x: Double,
open val y: Double,
open val z: Double,
open val w: Double
) {
open operator fun times(scalar: Double) = Tuple(x * scalar, y * scalar, z * scalar, w)
}
I would like for this operator override to work exactly the same for subclasses
data class Point(
override val x: Double,
override val y: Double,
override val z: Double
) : Tuple(x, y, z, 1.0) {
//Attempt 1
override operator fun times(scalar: Double) = Point(x * scalar, y * scalar, z * scalar)
// Attempt 2
private fun toPoint(other: Tuple) = Point(other.x, other.y, other.z)
operator fun times(scalar: Double) = toPoint(super.times(scalar))
}
but to instead return the subclass, which requires a subset of parameters of the base class in order to be instantiated.
Is there a way where I can write just one function and have it return the corresponding type based on the input class type?
I don't think it's possible.
The main reason is, your operator fun creates a new instance of Tuple.
In the Tuple class, it has no idea how many sub-classes or which sub-classes it has. Therefore, it cannot create a new instance of its subclass, and it doesn't know how to create.. well it can receive a class object and create an instance with reflection. But it's not what you are looking for I guess.
Another example is that Object is the superType of all classes. You cannot in Object add a method (if you could) to expect that it can magically create an instance of any type.
However, if you made your classes mutable( all required val variables -> var), and make the operator fun update the values instead of creating new objects, you can do in this way:
In Tuple:
open operator fun times(scalar: Double) =
this.also {x *= scalar; y *= scalar; z *= scalar; w}
In Point, you don't need do anything special. Then you can do:
val p = Point(1.0,2.0,3.0)
print(p*10.0)
It prints Point(x=10.0, y=20.0, z=30.0)
If you do need them to be immutable, you can extract those operator functions to a file:
operator fun Tuple.times(scalar: Double) :Tuple= Tuple ( x * scalar, y * scalar, z * scalar, w )
operator fun Point.times(scalar: Double) :Point= Point ( x * scalar, y * scalar, z * scalar)
I am trying to find the find the result of num1 raised to the power num2:
This is my code ->
fun power(num1 : Int, num2: Int): Int {
var result = 1
while (num2 != 0) {
return result *= num1
num2--
}
}
But the above code is producing the following error -->
Calculator.kt:30:16: error: assignments are not expressions, and only expressions are allowed in this context
return result *= num1
^
Calculator.kt:33:5: error: a 'return' expression required in a function with a block body ('{...}')
}
^
I have read a number of articles but not able to understand. Any help will be highly appreciated.
Thank you
An expression is something that evaluates to a value. An assignment is something that assigns a value to a variable or property.
x *= y is an assignment that is shorthand for x = x * y.
You cannot return an assignment, because it does not evaluate to a value. An assignment contains an expression on the right side of the equals sign, but as a whole does not represent an expression.
There are some other syntax problems you have. You can't modify a function paramter's value (num2-- isn't allowed).
The logic also doesn't make sense. return returns an expression immediately. To fix your code, you need to create a local variable from num2, and move the return statement to the end.
fun power(num1 : Int, num2: Int): Int {
var result = 1
var count = num2
while (count != 0) {
result *= num1
count--
}
return result
}
FYI, there's a function called repeat that is simpler than using a while loop with a counter. It runs the code inside the brackets by the number of times you give.
fun power(num1 : Int, num2: Int): Int {
var result = 1
repeat(num2) {
result *= num1
}
return result
}
You function contains multiple errors, I suggest you to study Kotlin, here a reference. Kotlin website has some more material.
Back to your problem, I have modified your function:
fun power(num1 : Int, num2: Int): Int {
var result = 1
var num2_local = num2
while (num2_local != 0) {
result *= num1
num2_local--
}
return result
}
Problems with your version:
you return from the function immediately
basic types args passed to kotlin functions are passed by const copy, this means that you cannot modify them (e.g num2--)
If you keep a local modifiable reference (var keyword) withing your function, then you achieve your goal
I have this code in a Swift application and was curious of what its equivalent syntax would be in Objective C
typealias Signal = (Float) -> (Float)
static let sine: Signal = { (time: Float) -> Float in
return amplitude * sin(2.0 * Float.pi * frequency * time)
}
I believe I would declare Signal as follows:
typedef float (^Signal)(float);
but I am not sure how I would setup a similar way of setting up the syntax to retrieve the value. I thought about a class method but the didn't quite work out.
Thank you
This is not a computed property. This is a “closure”.
So this defines a type alias for a closure that takes a Float as a parameter and returns a Float:
typealias Signal = (Float) -> (Float)
You can create an instance of this Signal closure like so:
let doubler: Signal = { $0 * 2 }
And you can call that closure like so:
print(doubler(21)) // 42
The equivalent Objective-C syntax to define the type for a “block”:
typedef float (^Signal)(float);
To create an instance of a Signal block:
Signal doubler = ^(float input) {
return input * 2;
};
And to call it:
NSLog(#"%f", doubler(21)); // 42
I tried to print out:
F degrees Fahrenheit = C degrees Celsius
and I can't get it to work I have tried so many things also be nice I'm new to coding.
fun main(args: Array<String>) {
var F = "32";
var C = (F - 32) * .5555556;
var conversion = "F degrees Fahrenheit = C degrees Celsius"
println(conversion);
}
You can use a template string:
fun main() {
var f = 68.0;
var c = (f - 32.0) * 5.0 / 9.0;
var conversion = "$f degrees Fahrenheit = $c degrees Celsius"
println(conversion)
}
Other things to note:
I've used a floating point number instead of a string for the f variable. This allows me to use floating point math to calculate the Celsius equivalent.
I renamed the variables to be lowercase, as per the coding conventions.
I replaced the .5555556 literal with 5.0 / 9.0. Better to introduce rounding errors later rather than earlier.
Even though in this case it's sufficient to only explicitly turn the f variable into a floating point number to force floating point math to be used, it's probably safer to just apply the same logic to all numbers.