A totally rookery in TypeScript with Function Overloading - function

I'm just learning TypeScript from here , at the Function Overloads section, got an 'undefined' error, Like I said I'm very new on TypeScript, don't know what is going on and how to fix it, please help!
Here is the snippet:
function foo_overload(s: string): void;
function foo_overload(n: number, s: string): void;
function foo_overload(x: any, y?: any): void {
console.log(x);
console.log(y);
}
foo_overload("Jack")
foo_overload(50, "Zhao");
And when I compile and execute this, the output like this:
Jack
undefined
50
Zhao
What the "undefined" it is?

Your pattern matching works well until you hit function foo_overload(x: any, y?: any):.
In that function, while you declare y to be optional, you invoke y with console.log(y), so it returns undefined, as in the first function invocation, you did not offer a y value (there is nothing after Jack).
Hope it helps!

Related

extension lambdas accept wrong parameters

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.

TypeScript interface with multiple call signatures

I saw in TypeScript 2.2 the option for "overloading" function by defined Interface call signatures and I spent quite a time to understand how to use it.
so after working on it and "cracking" it I thought it will be worth to post it here.
the issue I started with was, for example:
interface Func1 {
(num1: number, num2: number): number;
(str1: number, str2: string): string;
}
function F1(num1: number, num2: number): number {
return num1 + num2;
}
const f1: Func1 = F1;
console.log(f1(1, 2));
but the compiler did not pass it because the Func1 can't accept the F1 function.
I want to make overloading and I don't know what to do.
see answer below.
after digging it I found we can do quite of overloading. Overloading in TypeScript is not different from any other JavaScript code. it must be implemented in one function and not in multiple ones, like in C++. you need to make your function accept all options.
for example:
interface Func1 {
(v1: number, v2: number): number;
(v1: string, v2: string): string;
}
const f1: Func1 = (v1, v2): any => {
return v1 + v2;
};
console.log(f1("1", "2"));
console.log(f1(1, 2));
the function f1 suppose to have types for all options of overloading interface call signature, if you set strong type it will block you because of the types are not castable. like in this example number not castable to string.
you also can create multiple functions which use of the interface call signature overloading and pass those to your f1 and if the type match it will pass. just make sure your function can handle all the interface call signature.
it important to check types in implemented function when using classes or if the function parameters are not simple, like above example, using typeof and control all options.
hope it helped.

C++11: Why result_of can accept functor type as lvalue_reference, but not function type as lvalue_reference?

I've got program below:
#include<type_traits>
#include<iostream>
using namespace std;
template <class F, class R = typename result_of<F()>::type>
R call(F& f) { return f(); }
struct S {
double operator()(){return 0.0;}
};
int f(){return 1;}
int main()
{
S obj;
call(obj);//ok
call(f);//error!
return 0;
}
It fails to compile in the line of "call(f)".
It's weird that "call(obj)" is OK.
(1) I've a similar post in another thread C++11 result_of deducing my function type failed. But it doesn't tell why functor objects are OK while functions are not.
(2) I'm not sure if this is related to "R call(F& f)": a function type cannot declare a l-value?
(3) As long as I know, any token with a name, like variable/function, should be considered a l-value. And in the case of function parameter, compiler should "decay" my function name "f" to a function pointer, right?
(4) This is like decaying an array and pass it to a function----And a function pointer could be an l-value, then what's wrong with "call(F& f)"?
Would you help to give some further explanations on "why" is my case, where did I get wrong?
Thanks.
The problem with call(f) is that you deduce F as a function type, so it doesn't decay to a function pointer. Instead you get a reference to a function. Then the result_of<F()> expression is invalid, because F() is int()() i.e. a function that returns a function, which is not a valid type in C++ (functions can return pointers to functions, or references to functions, but not functions).
It will work if you use result_of<F&()> which is more accurate anyway, because that's how you're calling the callable object. Inside call(F& f) you do f() and in that context f is an lvalue, so you should ask what the result of invoking an lvalue F with no arguments is, otherwise you could get the wrong answer. Consider:
struct S {
double operator()()& {return 0.0;}
void operator()()&& { }
};
Now result_of<F()>::type is void, which is not the answer you want.
If you use result_of<F&()> then you get the right answer, and it also works when F is a function type, so call(f) works too.
(3) As long as I know, any token with a name, like variable/function, should be considered a l-value. And in the case of function parameter, compiler should "decay" my function name "f" to a function pointer, right?
No, see above. Your call(F&) function takes its argument by reference, so there is no decay.
(4) This is like decaying an array and pass it to a function----And a function pointer could be an l-value, then what's wrong with "call(F& f)"?
Arrays don't decay when you pass them by reference either.
If you want the argument to decay then you should write call(F f) not call(F& f). But even if you do that you still need to use result_of correctly to get the result of f() where f is an lvalue.

Q: Does functionality exist to invoke some promise over an array of arguments and "all"-ify it without boilerplate for-each code?

I was struggling to describe this succintly in the title so I'll paste in my typescript code that achieves what I'm talking about -
aggregate<T, A>(args: A[], invokable: (arg: A) => promise<T>): promise<T[]> {
let allPromises = new Array<promise<T>>();
for (let arg of args) {
allPromises.push(invokable(arg));
}
return promise.all(allPromises);
}
This takes a list of arguments of type A and for each of them invokes some function (which returns a promise which returns type T). Each of these promises are collected into a list which is then all-ified and returned.
My question is, does this function already exist in Bluebird as I'd rather do things properly and use that existing, tested functionality! I had problems getting my head around some of the documentation so I might not have grokked something I should have!
Your problem is perfectly solvable with Array.prototype.map.
Your code can be turned into:
aggregate<T, A>(args: A[], invokable: (arg: A) => promise<T>): promise<T[]> {
return promise.all(args.map(invocable));
}

AS3: Is it possible to give a vector function argument a default value?

I have a function where I'd like to make a vector argument optional-- that is, something like this:
public function test(arg1:int, arg2:Vector.<int> = new Vector.<int>(5)) {}
So in that example, I want the first argument to be required, and an optional vector passed in. If the second argument is not provided, create an int vector with 5 elements instead. It throws a compile error: "Parameter initializer unknown or is not a compile-time constant."
Making the argument not optional works, as in:
public function test(arg1:int, arg2:Vector.<int>) {}
But that's not exactly what I'm looking for. Doing some searching I found a supposed workaround, which is
public function test(arg1:int, arg2:Vector.<int> = null) {}
But that doesn't compile either.
I've already moved on in my code with a workaround just to be done with it, but I'm still curious. Can you have a vector as a default argument, and how?
I don't think this is possible. Probably just because the compiler was never programmed to handle this situation because optional parameters do work with many other datatypes in AS3. I did some research and other have reported the same issue as you with no success in setting an empty vector object in the function declaration.
I would simply do the following if you haven't already:
var myDefaultVector:Vector.<int> = new Vector.<int>(5);
function test(arg1:int, arg2:Vector.<int> = null) {
if( arg2 == null ) {
arg2 = myDefaultVector;
}
// rest of your code
}
I have tried compiling the above code in Flash and it compiled successfully.