Overriding function with generics in kotlin - function

For example I have following sample code
fun f<T>( cb: (T, Int) -> Unit ): Unit {
println("f called with cb which accepts 2 arguments");
}
fun f<T>( cb: (T) -> Unit ): Unit {
println("f called with cb which accepts 1 argument");
f<T> {item, position -> cb(item) }
}
fun main(args : Array<String>) {
f { item -> }
f { item, position -> }
}
Obliviously I want f function choose right implementation depends on amount of arguments I'm going to pass to closure
Currently kompiller gives me error:
(8, 7) : Overload resolution ambiguity:
internal fun <T> f(cb: (T, kotlin.Int) -> kotlin.Unit): kotlin.Unit defined in root package
internal fun <T> f(cb: (T) -> kotlin.Unit): kotlin.Unit defined in root package
Code in online sandbox: http://kotlin-demo.jetbrains.com/?publicLink=100745728838428857114-628607155
Compiller version: org.jetbrains.kotlin:kotlin-gradle-plugin:0.10.770
UPD: related issue on youtrack: https://youtrack.jetbrains.com/issue/KT-6939

Thanks to #miensol I realized it was my mistake. I forgot to specify type for T while calling f().
Fixed code:
fun f<T>( cb: (T, Int) -> Unit ): Unit {
println("f called with cb which accepts 2 arguments");
}
fun f<T>( cb: (T) -> Unit ): Unit {
println("f called with cb which accepts 1 argument");
f<T> {item, position -> cb(item) }
}
fun main(args : Array<String>) {
f<String> { item -> }
f<Boolean> { item, position -> }
}

Related

Kotlin - Pass a function and its arguments to a reusable handler function

My problem comes from an error handler that I need to write. The handler is meant to catch an error, do an action 'A', and then proceed to retry the original function that failed in the first place. The blocker comes when I need to generalise the handler to be able to accept any function definition.
For example:
fun foo(a: Any) {
// Do something and return null if unsuccessful
}
fun bar(b: Any, c: Any) {
// Do something else and return false if unsuccessful
}
fun handler(fn: Function???, args: Array[arguments???]) {
log.warn("Error has been caught at <${functionName}>, doing action A and retrying")
// Do action A
log.warn("Retrying <${functionName}>")
fn(args)
}
fun main() {
val resultFoo = foo('bar')
if (resultFoo == null) {
handler(foo, ['bar'])
}
val resultBar = bar('foo', { 'foo': 'bar' })
if (!resultBar) {
handler(bar, ['foo', { 'foo': 'bar' }])
}
}
As you can see, I have two functions foo and bar with different definitions which I would like to be able to call from handler. Otherwise I would need to copy-paste the body inside handler to each individual function and handle the error inside there. I was hoping to be able to generalise this and be able to reuse it.
If you want to avoid reflection, which would provide no compile-time error checking, you should overload your function to have variants with different numbers of variables. Then you can use generics, and you'll get compile-time checking.
There's not a clean way to pass functions along with their names, so I made the name for logging a separate argument in this example.
// zero args handler
inline fun <R> handler(loggedFunctionName: String?, fn: ()->R): R {
val functionName = "<$loggedFunctionName>" ?: "function"
log.warn("Error has been caught at $functionName, doing action A and retrying")
// Do action A
log.warn("Retrying $functionName")
return fn()
}
// one arg handler
inline fun <A, R> handler(loggedFunctionName: String?, fn: (A)->R, argA: A): R
= handler(loggedFunctionName) { fn(argA) }
// two args handler
inline fun <A, B, R> handler(loggedFunctionName: String?, fn: (A, B)->R, argA: A, argB: B): R
= handler(loggedFunctionName) { fn(argA, argB) }
fun main() {
val resultFoo = foo("bar")
if (resultFoo == null) {
handler("foo", ::foo, "arg")
}
val resultBar = bar("arg1", "arg2")
if (!resultBar) {
handler("bar", ::bar, "arg1", "arg2")
}
}
However, it seems you could reduce boilerplate further by incorporating your logical test of the result as another argument:
// zero args handler
inline fun <R> handler(loggedFunctionName: String?, fn: ()->R, verifyResult: (R)->Boolean): R {
val firstResult = fn()
if (verifyResult(firstResult)){
return firstResult
}
val functionName = "<$loggedFunctionName>" ?: "function"
log.warn("Error has been caught at $functionName, doing action A and retrying")
// Do action A
log.warn("Retrying $functionName")
return fn()
}
// one arg handler
inline fun <A, R> handler(loggedFunctionName: String?, fn: (A)->R, verifyResult: (R)->Boolean, argA: A): R
= handler(loggedFunctionName, { fn(argA) }, verifyResult)
// two args handler
inline fun <A, B, R> handler(loggedFunctionName: String?, fn: (A, B)->R, verifyResult: (R)->Boolean, argA: A, argB: B): R
= handler(loggedFunctionName, { fn(argA, argB) }, verifyResult)
fun main() {
handler("foo", ::foo, { it != null }, "arg")
handler("bar", ::bar, { it }, "arg1", "arg2")
}
First of all you need to know, what exactly you want to generalize.
As I can see from your example, you want to repeat function call with same arguments. So instead all this messing with argument-arrays you can wrap payload (function call with arguments) into lambda and call it twice.
Second question is repeat condition. In foo it's result == null, in bar it's result == false. So condition is different for different functions. You can calculate condition in separate lambda.
So you can write something like this:
fun <T, F: KFunction<*>> F.callAndRepeatOnCondition (
payload: (F) -> T,
condition: (T) -> Boolean,
): T {
var result = payload(this)
if (condition(result)) {
println("log: doing something and repeat function ${this.name} ")
println("some super logic before repeat")
result = payload(this)
}
return result
}
fun foo(a: Int, b: String): String? { return null }
fun bar(c: Int): Boolean { return false }
fun main() {
val resultFoo = ::foo.callAndRepeatOnCondition({ it(1, "a") }, { it == null })
val resultBar = ::bar.callAndRepeatOnCondition({ it(2) }, { !it })
}
PS. If you don't need to log function name or can pass it explicitly, here is a little less ugly solution:
fun foo(a: Int, b: String): String? { return null }
fun bar(c: Int): Boolean { return false }
fun <T> (() -> T).repeatIf(condition: (T) -> Boolean): T {
val result = this()
if (!condition(result)) return result
println("some super logic before repeat")
return this()
}
fun <T> (() -> T).repeatWithLoggingIf(logName: String, condition: (T) -> Boolean): T {
val result = this()
if (!condition(result)) return result
println("log: repeating $logName")
println("some super logic before repeat")
return this()
}
fun main() {
run { // without logName
val resultFoo = { foo(1, "a") }.repeatIf { it == null }
val resultBar = { bar(2) }.repeatIf { !it }
}
run { // with logName
val resultFoo = { foo(1, "a") }.repeatWithLoggingIf("foo") { it == null }
val resultBar = { bar(2) }.repeatWithLoggingIf("bar") { !it }
}
}

Explicitly cast a type that involves a specific function item type

Here is an example:
use std::iter::Filter;
use std::slice::Iter;
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys = xs.iter().filter(nothing);
ys
}
fn main () {
}
Compilation fails with:
src/main.rs:8:5: 8:7 error: mismatched types:
expected `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool>`,
found `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool {test1::nothing}>`
(expected fn pointer,
found fn item) [E0308]
src/main.rs:8 ys
^~
This is because the inferred type of ys has the type of a specific function item in it. In this particular case the issue is easy to fix: one can either explicitly specify the type without the function item in the binding, or avoid the let altogether.
Both of these work:
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys: Filter<Iter<i32>, fn(&&i32) -> bool> = xs.iter().filter(nothing);
ys
}
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
xs.iter().filter(nothing)
}
Therefore, as the Reference says, indeed Rust is capable of performing this coercion itself. But what if the code was more complex and I had to perform this cast manually? How would I do this?
In this case as won’t work, and transmute seems to be an overkill, although, I believe, it would do the job.
You can actually cast using as:
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys = xs.iter().filter(nothing as fn(&&i32) -> bool);
^~~~~~~~~~~~~~~~~~~~
ys
}
However you need to use as to change the function's type, not the Filter type, as as is not allowed to change arbitrary types.
Personally, I consider the necessity of the cast a short-coming and hope that type inference will improve to the point it becomes unnecessary. The fact that it works for a direct return is a red-herring, it should probably work with an intermediate value too.

XCode 6.3 / Swift 1.2 curried functions runtime error in release build?

This little generic function produces an interesting runtime error:
func clamps <T: Comparable> (from: T, to: T)(_ x: T) -> T {
if x < from { return from }
if x > to { return to }
return x
}
(As I explain below, please keep in mind that I was unable to significantly reduce the error generating code any further – except by removing one of the if lines!)
We can use it to generate a clamp function like so:
let clamp: Int -> Int = clamps(2, 4)
We'll print some examples like so:
for i in 0...5 {
println("clamp(\(i)) -> \(clamp(i))")
}
When run in Debug the for loop produces the following output:
// clamp(0) -> 2
// clamp(1) -> 2
// clamp(2) -> 2
// clamp(3) -> 3
// clamp(4) -> 4
// clamp(5) -> 4
Which is what we would expect. When run in Release configuration, however, we get:
// clamp(0) -> 4296676200
// clamp(1) -> 4296676200
// clamp(2) -> 4296676200
// clamp(3) -> 4296676200
// clamp(4) -> 4296676200
// clamp(5) -> 4296676200
Notice that this number is very close to UInt32.max (which is 4294967295), so my guess is that it is some sort of UnicodeScalar value... If you use this clamps with other types, like CGFloat, the results are similarly nonsensical.
If we rewrite the function so as to avoid Swift's currying syntax, then everything works fine both in Debug and Release:
func clamps2 <T: Comparable> (from: T, to: T) -> T -> T {
return {
if $0 < from { return from }
if $0 > to { return to }
return $0
}
}
let clamp2: Int -> Int = clamps2(2, 4)
for i in 0...5 {
println("clamp2(\(i)) -> \(clamp2(i))")
}
// clamp2(0) -> 2
// clamp2(1) -> 2
// clamp2(2) -> 2
// clamp2(3) -> 3
// clamp2(4) -> 4
// clamp2(5) -> 4
So the question is whether this really is a bug or have I missed something obvious to the whole world?
As a final example, consider that this (an otherwise useless function) does not reproduce the error:
func f <T: Comparable> (from: T, to: T)(_ x: T) -> T {
if x < from {
return x // <---- returning x
}
return x
}
But this does:
func f <T: Comparable> (from: T, to: T)(_ x: T) -> T {
if x < from {
return from // <---- returning from
}
return x
}
Apple Developer Relations response
My bug report just got a message from Apple Developer Relations saying that they believe this issue has been addressed in the latest Xcode 7 beta.

Why compiler treats closures and local functions differently?

I thought closures and functions are same thing. But when referencing to a property inside local function compiler doesn't require self. But inside closure it requires to write self. What i mean is why this two things are different?
The sample code for clarity:
class Foo {
let bar = "bar"
func baz() {
func localBaz() {
println(bar) // No complain from compiler.
}
let bazClosure = {
println(self.bar) // Here if I write just println(bar), compiler complains.
}
}
}
You expectation is wrong - functions and closures in Swift are not the same thing. A func essentially sets up a lazy var binding with a [unowned self] declaration. Thus, if you want to get rid of func you could transform the following:
class Foo {
let bar = "bar"
// this is not your 'baz'; just an example
func baz () { println (bar) }
}
}
as
class Foo {
let bar = "bar"
lazy var baz = { [unowned self] in println (self.bar) }
}
You can see that func is doing more than just a closure.
Furthermore, and importantly, func sets up a recursive binding environment which allows the body of func bar to reference bar. Thus you can write:
1> class Foo {
2. func fact (x:Int) -> Int {
3. if 1 == x { return x }
4. else { return x * fact (x - 1) }}
5. }
6> Foo().fact(5)
$R0: (Int) = 120
but not
7> class Foo {
8. lazy var fact = { (x:Int) -> Int in
9. if 1 == x { return x }
10. else { return x * fact (x - 1) }}}
repl.swift:10:27: error: variable used within its own initial value
else { return x * fact (x - 1) }}}
^
Indeed, I do not know why closure need self in swift to access instance properties but let's think about it.
Your baz() is a class function, I mean it belongs to the class Foo and the closure like a external function. In Objective-C all class function actually need a self argument to invoke that function.
Therefore a closure need a self pointer (or something named self reference the instance of Foo) to access its property.

Swift, math functions and protocols

I'm trying to create 2 protocols ArithmeticType and MathematicType that will be used in where clauses of generic operator functions
protocol ArithmeticType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
}
extension Int : ArithmeticType {
}
extension Double : ArithmeticType {
}
extension Float : ArithmeticType {
}
ArithmeticType works as expected and either Int, Float and Double conform to it. However the following fails
import Darwin
protocol MathematicType {
func sin(x: Self) -> Self
}
extension Double : MathematicType {
}
extension Float : MathematicType {
}
on console output of the playground I read:
Playground execution failed: <EXPR>:35:1: error: type 'Double' does not conform to protocol 'MathematicType'
extension Double : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Double -> Self'
func sin(x: Self) -> Self
^
<EXPR>:39:1: error: type 'Float' does not conform to protocol 'MathematicType'
extension Float : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Float -> Self'
func sin(x: Self) -> Self
^
I would like that math functions behave like the operators above. Is there any way?
== EDIT:
Now I realize that trying to simplify my question was a bad idea. the context is this class (vector of optional values)
class Vector<T> {
var data=[T?]()
init(fromArray: Array<T>) {
for i in fromArray {
data.append(i)
}
}
init() {
}
init(count: Int){
for i in 0..<count {
data.append(nil)
}
}
init(count: Int, repeatedValue: T) {
for i in 0..<count {
data.append(repeatedValue)
}
}
func count() -> Int {
return data.count
}
func append(newElement: T?) {
data.append(newElement)
}
subscript(index: Int) -> T? {
let i = index>0 ? index % count() : -index % count()
return data[i]
}
}
outside of it I defined a generic function for the + operator
func +<T where T: ArithmeticType>(left: Vector<T>, right: Vector<T>) -> Vector<T> {
let resultCount = max(left.count(),right.count())
var result = Vector<T>()
for i in 0..<resultCount {
if left[i] != nil && right[i] != nil {
result.append(left[i]!+right[i]!)
}
else {
result.append(nil)
}
}
return result
}
that works as expected, however when I tried to define a generic sin function as
func sin<T where T : FloatingPointType>(x: Vector<T>) -> Vector<T>{
var result = Vector<T>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(sin(o))
}
else {
result.append(nil)
}
}
return result
}
I got "could not find an overload of sin that accepts the supplied arguments"
then my attempt with MathemticType trying to mimic what I already done for + operator
(ArithmeticType was inspired from IntegerAritmeticType source found by command clicking on import swift more than my knowledge of what I was doing)
== UPDATE
If I write a specialized function only for Double
func sin(x: Vector<Double>) -> Vector<Double>{
var result = Vector<Double>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(Darwin.sin(o))
}
else {
result.append(nil)
}
}
return result
}
it works as expected.
So the question may become "How can I generalize this to either Double and Float" ?
The compiler error is because you declared sin() as a method of the MathematicType protocol, and then declared that Double implements MathematicType, but didn't actually write the sin() method.
extension Double {
func sin(x: Double) -> Double {
return Darwin.sin(x)
}
}
I don't think that's what you want, though, is it? You want to be able to write this:
let myAngle = 3.14159
let sineValue = myAngle.sin()
If that's the case, your protocol and extension would need to look like this:
protocol MathematicType {
func sin() -> Self
}
extension Double : MathematicType {
func sin() -> Double {
return Darwin.sin(self)
}
}
Your MathematicType protocol, and your declarations of conformance to it in Float and Double extensions, say that Float and Double should provide sin as an instance method. That is, you're saying one should be able to write code like:
let zero = 0.0 // inferred type Double
zero.sin(1.5707963268) // returns about 1.0
Notice that invocation of sin isn't actually related to the value of zero, so this probably isn't the behavior you want.
You're probably looking to have sin be a free function, so you can just write:
sin(1.5707963268)
Right?
In that case, your work is already done... the standard library defines both:
func sin(x: Double) -> Double
func sin(x: Float) -> Float
If what you actually want is for your MathematicType to be usable as a generic parameter, meaning "a type you can take the sine of", you'll need a generic sin function. Something like this (quick kludgy solution, there's probably better):
func sine<T: FloatingPointType>(x: T) -> T {
if let v = x as? Double {
return sin(v) as T
}
if let v = x as? Float {
return sin(v) as T
}
fatalError("unknown FloatingPointType")
}
(Notice also that there's already a protocol that both Float and Double conform to, so I've used that in the example.)
I think the issue is that operator requirements and instance method requirements are different, even though they syntactically look similar. Operators are always defined at the global level, so an operator requirement is a requirement on an operator at the global level. On the other hand, instance method requirements are requirements on instance methods. There is no way to specify a global function requirement.