int add(int n1,int n2) {
return n1+n2;
}
1.Function calc1=add;
2.Function calc2=(int n1,int n2) {
return n1+n2;
};
3.var calc3=(int n1,int n2)=>{
n1+n2
};
4.var callc=(int n1,int n2) {
return n1+n2;
};
Are all these doing the same thing?
In 1.Function calc1=add , is this pointing to the memory of add function or setting itself to the add function?
In 4. I am getting the error "The type of function literal can't be inferred because the literal has as block as it's body" but if I replace var keyword with Function then no error?Why?
These do slightly different things that may or may not act the same depending on how you use them.
1.
Function calc1 = add;
Declares a variable of type Function and assigns a reference to the add function to it.
If add is top-level, static or local variable, then all references to it is going to be the same value. If you refer an instance function (a method), you create a new closure every time.
2.
Function calc2=(int n1,int n2) {
return n1+n2;
};
Declares a variable with type Function, then evaluates a function literal to a function value. Each evaluation of that literal creates a new object.
3.
var calc3=(int n1,int n2)=>{
n1+n2
};
You probably meant to write
var calc3=(int n1,int n2)=>
n1+n2;
This is almost equivalent to 2. A body of => expression; is a shorthand for { return expression; }. However, you declare the variable as var, not Function, so type inference gives the variable the type int Function(int, int).
4.
var callc=(int n1,int n2) {
return n1+n2;
};
Completely equivalent to 3 if you do it as a local variable, but as a top-level variable, type inference does not look into the body to find the return type.
What you see is not an error, just a helpful info. I'm also not entirely sure it's correct. When I check the cpde in DartPad, it actually infers int Function(int, int) for var x = (int x, int y) { return x + y; };.
The biggest difference between the different cases in practice is that number 1 does not create a new closure each time it's evaluated, and that number 1 and 2 have type Function instead of int Function(int, int). That affects type checking, because Function allows any call to be made, while the precise function type only allows you to call the function with two integers (and knows that the result is an integer).
Related
I can define a generic function:
package hello
func IsZero[T int64|float64](value T) bool {
return value == 0
}
Then if I try to alias that function in another package, it fails:
package world
import "hello"
var IsZero = hello.IsZero
The above doesn't compile with:
cannot use generic function hello.IsZero without instantiation
Instead this works:
var IsZero = hello.IsZero[int64]
Is it possible to do this, using some other syntax?
That's not an alias. And you already have your answer, actually. But if you want a formal reference, from the language specs, Instantiations:
A generic function that is is not called requires a type argument list for instantiation
So when you attempt to initialize a variable of function type, the function hello.IsZero is not called, and therefore requires instantiation with specific type parameters:
// not called, instantiated with int64
var IsZero = hello.IsZero[int64]
At this point the variable (let's give it a different name for clarity) zeroFunc has a concrete function type:
var zeroFunc = IsZero[int64]
fmt.Printf("type: %T\n", zeroFunc)
Prints:
type: func(int64) bool
This might or might not be what you want, as this effectively monomorphises the function.
If you just want to have a local symbol, with the same implementation (or a tweaked version thereof), declaring a "wrapper" function works. Just remember that the type parameters of your wrapper can only be as strict or stricter than the wrapped one's
E.g. Given
IsZero[T int64 | float64](v T)
your wrapper can not be
WrapIsZeroPermissive[T int64 | float64 | complex128](v T) bool {
return IsZero(v) // does not compile, T's type set is a superset
}
but can be
WrapIsZeroStricter[T int64](v T) bool {
return IsZero(v) // ok, T's type set is a subset
}
If the function is small, like in the question, it's probably easier to just vendor it:
package vendor
func thisIsJustCopy[T int64|float64](value T) bool {
return value == 0
}
but if the function is big, you can do it like this:
package world
import "hello"
func IsZero[T int64|float64](value T) bool {
return hello.IsZero(value)
}
I try to alias that function in another package
Aliases work for types only. Your code just tries to declare a variable.
Is it possible to do this, using some other syntax?
No.
I think an extension lambda requires that you pass in the correct argument, but i seems not to do so in the following example.
open class Base {
open fun f() = 1
}
class Derived : Base() {
override fun f() = 99
}
fun Base.g(): Int { return f()}
fun Base.h(xl: Base.() -> Int): Int { return xl()}
fun main() {
val b: Base = Derived() // Upcast
println(b.g())
println(b.h { f()}) // [1]
}
I understand that Base.h takes a function that takes a Base object as its parameter. But line [1] shows that it accepts f(), which is a function that takes no parameter. I was thinking hard about this and I prefixed it with this.f() and it still worked. Not convinced, I modified the code as follows:
open class Base {
open fun f() = 1
}
class Derived : Base() {
override fun f() = 99
}
fun Base.g(): Int { return f()}
fun Base.h(xl: (Base) -> Int): Int { return xl(Base())}
fun test(i:Int) = 1
fun main() {
val b: Base = Derived() // Upcast
println(b.g())
println(b.h { test(1) })
}
This code works. I've run it to verify. And as you can see, b.h() accepts test(), which takes an Int. And this is contrary to the fact that Base.h() takes a Base.
Could you explain this? Thank you for reading.
Note the curly brackets around the functions that are passed in! They change everything.
In the second code, b.h { test(1) } is not passing the function test to b.h. The syntax to pass test to b.h would be b.h(::test), and that does produce an error as you would expect.
b.h { test(1) } passes a function (a lambda expression) that takes a Base as parameter, ignores that parameter, calls test(1) and returns the result. You are basically passing a function that looks like this to b.h:
fun foo(p: Base) = test(1)
You might be wondering how Kotlin knows about Base when you did not write the word Base in the call at all. Well, it can just look at the declaration of b.h, and see that { test(1) } must take a parameter of Base.
The first code snippet is a bit different, because b.h accepts a Base.() -> Int in that case. Base.() -> Int represents a function whose receiver type is Base, that is, a function func that can be called like someBaseObject.func(). Compare this to a function func that takes a Base object as parameter, which can be called like func(someBaseObject).
Again, { f() } is not passing the function f. It is a lambda expression that does nothing but calls f. In this case though, f itself can be passed to b.h (b.h(Base::f)), because it is a function with a receiver type of Base! You can do someBaseObject.f(), can't you? Passing the lambda is similar to passing an extension function that is declared like this (you're just "wrapping" f in another function):
fun Base.foo() = f()
And since the receiver of the function is Base, you are able to access other functions that has Base as the receiver (such as f) in the lambda. You can also specify the receiver (which is this) explicitly.
I noticed that I get the same effect if I define this trivial function:
fun double ( i: Int ) = i*2
and if I define a variable and assign a lambda (with an identical body) to it:
var double = { i : Int -> i*2 }
I get the same result if I call double(a) with either declaration.
This leaves me confused. When is it needed, recommended, advantageous to define a variable as a lambda rather than define a function to it?
When is it needed, recommended, advantageous to define a variable as a lambda rather than define a function to it?
Whenever you have the choice of either, you should use a fun declaration. Even with a fun you can still get a first-class callable object from it by using a function reference.
On the JVM, a fun is significantly more lightweight, both in terms of RAM and invocation overhead. It compiles into a Java method, whereas a val compiles into an instance field + getter + a synthetic class that implements a functional interface + a singleton instance of that class that you must fetch, dereference, and invoke a method on it.
You should consider a function-typed val or var only when something is forcing you to do it. One example is that you can dynamically replace a var and effectively change the definition of the function. You may also receive function objects from the outside, or you may need to comply with an API that needs them.
In any case, if you ever use a function-typed property of a class, you'll know why you're doing it.
First, if I understand you right, your question is "Why are functions first-class citizens in Kotlin -- And when to use them as such?", right?
Kotlin functions are first-class, which means that they can be stored in variables and data structures, passed as arguments to and returned from other higher-order functions. You can operate with functions in any way that is possible for other non-function values. (see here)
As stated in the docs, one use case are higher-order functions. As a first step, I will leave the wikipedia link here: https://en.wikipedia.org/wiki/Higher-order_function
Basically, a higher-order function is a function that takes functions as parameters, or returns a function.
This means that a higher-order function has at least one parameter of a function type or returns a value of a function type.
Following a short example of a higher-order function that receives a parameter of function type (Int) -> Boolean:
fun foo(pred: (Int) -> Boolean) : String = if(pred(x)) "SUCCESS" else "FAIL"
This higher-order function can now be called with any (Int) -> Boolean function.
The docs also state ... [can be used] in any way that is possible for other non-function values.
This means that you can, for example, assign different functions to a variable, depending on your current context.
For example:
// This example is verbose on purpose ;)
var checker: (Int) -> Boolean
if (POSITIVE_CHECK) {
checker = { x -> x > 0 } // Either store this function ...
} else {
checker = { x -> x < 0 } // ... or this one ...
}
if (checker(someNumber)) { // ... and use whatever function is now stored in variable "checker" here
print("Check was fine")
}
(Code untested)
You can define variable and assign it lambda when you want change behaviour for some reason. For example, you have different formula for several cases.
val formula: (Int) -> Int = when(value) {
CONDITION1 -> { it*2 }
CONDITION2 -> { it*3 }
else -> { it }
}
val x: Int = TODO()
val result = formula(x)
If you simply need helper function, you should define it as fun.
If you pass a lambda as a parameter of a function it will be stored in a variable. The calling application might need to save that (e.g. event listener for later use). Therefore you need to be able to store it as a variable as well. As said in the answer however, you should do this only when needed!
For me, I would write the Lambda variable as followed:
var double: (Int) -> Int = { i -> //no need to specify parameter name in () but in {}
i*2
}
So that you can easily know that its type is (i: Int) -> Int, read as takes an integer and returns an integer.
Then you can pass it to somewhere say a function like:
fun doSomething(double: (Int) -> Int) {
double(i)
}
Why is the valueOf() function present in everything in AS3? I can't think of an instance when this isn't redundant. In terms of getting a value, x and x.valueOf() are completely the same to me (except that one probably takes more CPU cycles). Furthermore even though they may not be the same in terms of setting something, x.valueOf() = y (if even legal) is just completely pointless.
I am confident though that this is here for a reason that I'm just not seeing. What is it? I did try Googling for a minute. Thanks!
As you say, its completely redundant.
The valueOf method is simply included so that ActionScript 3 complies with the ECMA language specification (obviously there are other requirements to be an ECMA language - i believe toString is another example).
Returns the primitive value of the specified object. If this object does not have a
primitive value, the object itself is returned.
Source: Adobe AS3 Reference http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Object.html#valueOf()
Edit:
A primitive value can be a Number, int, bool, etc... They are just the value. An object can have properties, methods, etc.
Biggest difference, in my opinion though:
primitive2 = primitive1;
In this example, primitive 2 contains a copy of the data in primitive 1.
obj2 = obj1;
In this one, however, ob2 points to the same object as obj1. Modify either obj1 or obj2 and they both reflect the change, since they are references.
In short, valueOf is used when you want to see the primitive representation of an object (if one exists) rather than the object itself.
Here is a clear example between
Value Vs. ValueOf:
Value = Thu Jan 2 13:46:51 GMT-0800 2014 (value is date formatted)
ValueOf = 1388699211000 (valueOf is in Raw epoch)
valueOf isn't useless. It allows an Object to provide a value for an expression that expects a primitive type. It's available in AS3 as well as JavaScript.
If someone wrote a function that takes an int, you could pass it your object (more precisely, it passes the result of your object's valueOf() function).
The usefulness is tempered by 1) the fact that the Object isn't passed, so it's only an Object in the outermost scope, and 2) the fact that it's a read-only operation, no assignment can be made.
Here're a couple concrete examples off the top of my head:
Example 1: A Counter class that automatically increments its value every time it's read:
class Counter
{
private var _cnt:int = 0;
public function Counter() { }
public function valueOf():int
{
return _cnt++;
}
public function toString():String { return ""+valueOf(); }
}
Usage:
var c:* = new Counter();
trace(c); // 0
trace(c); // 1
trace(2*c+c); // 2*2+3 = 7
trace(c); // 4
Notes:
I added the toString() pass-through, since functions that take String prefer toString over valueOf.
You must type c as * and not Counter, otherwise you'll get a compiler error about implicit coercion of Counter to Number.
Example 2: A (read only) pointer type
Let's say you have an array of ints, and you want to have a reference (aka pointer) to an element in the array. ECMA scripts don't have pointers, but you can emulate one with valueOf():
class ArrayIntPointer
{
private var arr:Array;
private var idx:int;
public function ArrayIntPointer(arr:Array,
idx:int)
{
this.arr = arr;
this.idx = idx;
}
public function valueOf():int
{
return arr[idx];
}
public function toString():String { return ""+valueOf(); }
}
Usage:
var arr:Array = [1, 2, 3, 4, 5];
var int_ptr:* = new ArrayIntPointer(arr, 2);
// int_ptr is a pointer to the third item in the array and
// can be used in place of an int thanks to valueOf()
trace(int_ptr); // 3
var val:int = 2*int_ptr+1;
trace(val); // 7
// but it's still an object with references, so I
// can change the underlying Array, nand now my
// object's primitive (aka, non-Object types) value
// is 50, and it still can be used in place of an int.
arr[2] = 50;
trace(int_ptr); // 50
// you can assign int_ptr, but sadly, this doesn't
// affect the array.
That's pretty slick. It'd be really slick if you could assign the pointer and affect the array, but unfortunately that's not possible, as it assigns the int_ptr variable instead. That's why I call it a read-only pointer.
Simple question here, when void follows a function in AS3 what is it doing?
public function sayGoodbye():void { trace("Goodbye from MySubClass");}
void type indicates to the compiler that the function you have written will not return any value, in the other side if you indicate other type T than void the compiler expect that you return T.
Ex:
function foo(a:int):int { // here the compiler expect that somewhere
// in your function you return an int
return a;
}
void means that it has no return value. I.e., you can't use it in an expression.
void specifies that the function will return no value, or, to be more exact, the special undefined value type. Note that the function return can be used in an expression and it is the unique value of the undefined type.
In actionscript 3 to conform to the strict mode you need to specify variable types and function return types in order for the compiler to know what types to expect and to optimize your application.