In javascript it is pretty easy to take a variable count of arguments and pass it to a sub function without the need to modify the sub function. For example, you want to write a wrapper function which takes a generic function as first argument and calls it with the rest of the arguments:
function wrapper(func, ...args) {
return func(...args)
}
I want to archive something similar in swift. There I have many many c function which I want to wrap with another function for some safety reasons.
Now I have two major road blockers:
The first one: I don't know how to do something like func(...args) in swift. This is why I temporary tried this:
private func apply<ReturnValue, FunctionParams>(_ fun: (_ params: FunctionParams...) -> ReturnValue, _ paramsPass: [FunctionParams]) throws -> ReturnValue {
switch paramsPass.count {
case 0:
return fun()
case 1:
return fun(paramsPass[0])
case 2:
return fun(paramsPass[0], paramsPass[1])
case 3:
return fun(paramsPass[0], paramsPass[1], paramsPass[2])
case 4:
return fun(paramsPass[0], paramsPass[1], paramsPass[2], paramsPass[3])
case 5:
return fun(paramsPass[0], paramsPass[1], paramsPass[2], paramsPass[3], paramsPass[4])
case 6:
return fun(paramsPass[0], paramsPass[1], paramsPass[2], paramsPass[3], paramsPass[4], paramsPass[5])
default:
throw NSError(domain: "apply", code: paramsPass.count, userInfo: nil);
}
}
This is not really good and only works for a max parameter count of 6.
The second road blocker is, I am not able to write the required swift types to archive something like I described. This is what I tried:
private func runUnsafeFunction<ReturnValue, FunctionParams>(_ fun: (_ params: FunctionParams...) -> ReturnValue, _ paramsPass: FunctionParams...) throws -> ReturnValue {
// wrapper code
return try apply(fun, paramsPass)
}
However, if I try to call it, I get: Generic parameter 'ReturnValue' could not be inferred
Probably I miss something here. But at this point I am stuck.
Why not pass the function and its arguments in a closure?
func runUnsafeFunction<ReturnValue>(function: () -> ReturnValue) -> ReturnValue {
// do stuff
return function()
}
Example
func add(_ a: Int, _ b: Int) -> Int {
a + b
}
func add(_ a: Int, _ b: Int, _ c: Int) -> Int {
a + b + c
}
let result = runUnsafeFunction { add(3, 4) }
let result2 = runUnsafeFunction { add(3, 4, 5) }
Related
After experimenting with currying in Swift, I came up with the code below. I want to see if it's possible to simplify this enum Operate. Currently, I need to initialize like this:
let multiply = Operate.Multiply.op
I would prefer to have each case have an associated value that directly returns a closure without having to do this hacky switch block. Is this possible?
Here's some code that you can run in a Swift playground:
import Foundation
enum Operate {
case Plus
case Minus
case Multiply
case unsafeDivide
var op: (Double) -> (Double) -> Double {
get {
switch self {
case .Plus:
return { n in
return { n + $0}
}
case .Minus:
return { n in
return { n - $0}
}
case .Multiply:
return { n in
return { n * $0}
}
case .unsafeDivide:
return { n in
return { n / $0 }
}
}
}
}
}
let multiply = Operate.Multiply.op
let plus = Operate.Plus.op
let unsafeDivide = Operate.unsafeDivide.op
// 3 + (16 * 2) -> 35
plus(3)(multiply(16)(2))
Bonus: How can I handle errors with unsafeDivide in a 'Swiftly' manner, that is, prevent this:
let unsafeDivide = Operate.unsafeDivide.op
unsafeDivide(2)(0)
What you seem to be doing is currying. You remove a lot of duplicated code by extracting a curry function:
func curry<A,B,C>(_ f: #escaping (A, B) -> C) -> (A) -> (B) -> C {
return { a in { b in f(a, b) } }
}
// ...
var op: (Double) -> (Double) -> Double {
switch self {
case .plus: // please follow Swift naming conventions, enum cases start with a lowercase
return curry(+)
case .minus:
return curry(-)
case .multiply:
return curry(*)
case .unsafeDivide:
return curry(/)
}
}
That already looks a lot nicer. You seem to not like switch statements, so here's how you'd do it with a dictionary:
var op: (Double) -> (Double) -> Double {
let dict: [Operate: (Double, Double) -> Double] =
[.plus: (+), .minus: (-), .multiply: (*), .unsafeDivide: (/)]
return curry(dict[self]!)
}
In fact, you can use the new callAsFunction feature in Swift 5.2 to omit even the word op on the caller side:
func callAsFunction(_ a: Double) -> (Double) -> Double {
op(a)
}
This allows you to do:
Operator.multiply(2)(3)
Using associated values is another way:
enum Operate {
case plus(Double)
case minus(Double)
case multiply(Double)
case unsafeDivide(Double)
func callAsFunction(_ b: Double) -> Double {
switch self {
case .plus(let a):
return a + b
case .minus(let a):
return a - b
case .multiply(let a):
return a * b
case .unsafeDivide(let a):
return a / b
}
}
}
But I personally don't like it because having associated values means that you can't simply use == to compare enum values, among other restrictions.
Preventing dividing by 0 at compile time is impossible, because the values you pass in might not be compile time constants. If you just want to check for compile time constants, then you might need a static code analyser like SwiftLint. At runtime, division of the Double 0 is well-defined by the IEEE standard anyway. It won't crash or anything.
I am trying to determine the correct Int type to use at runtime.
Essentially, I am trying to do something like this:
func sizeToType<T>(size:UInt8) throws -> T.Type {
switch size {
case 1:
return UInt8.self
case 2:
return UInt16.self
case 4:
return UInt32.self
case 8:
return UInt64.self
default:
throw MyError.runtimeError("Incorrect size")
}
But this won't compile, and force me to write it this way:
func UTILtoType<T : FixedWidthInteger>(size:UInt8) throws -> T.Type {
switch size {
case 1:
return UInt8.self as! T.Type
case 2:
return UInt16.self as! T.Type
case 4:
return UInt32.self as! T.Type
case 8:
return UInt64.self as! T.Type
default:
throw MyError.runtimeError("Incorrect size")
}
But I am worried that the latter will actually not work as I expect. I don't want my UInt8 to be "upcasted" to an Int.
What's the right way to do this?
EDIT: to answer the question of what I am trying to accomplish. My end goal is to have a function that might look like this (I am trying to make this work, I know this does not compile as is):
static func parseInt<T : FixedWidthInteger> (unsafeRawPointer:UnsafeRawPointer, stride: Int, from:Int, length:Int) -> T {
var res : UTILtoType(size:length) = 0
for x in 0..<length {
res += (unsafeRawPointer.advanced(by:(from + x) * stride).load(as:UTILtoType(size:length).self))
}
return res
}
so that I can end up having the ability to simply call:
let a = parseInt(unsafeRawPointer:pointer, stride:1, from:0, len:2)
and this will create a UInt16 and assign it to a, which will be of type UInt16. It seems redundant to me to specify both the length and UInt16, so I was hoping I could infer the type.
I am getting a compile time error that myFunc reference is ambiguous.
func f (s: String) -> String { return "version 1: " + s }
func f(sourceString s: String) -> String { return "version 2: " + s }
var myFunc: (String)-> String = f as (sourceString : String)->String
How can I explicitly reference each version of the overloaded function, f, in the example above? If I comment out either declaration of func f it will compile and work. But I would like to know how to reference each of the functions if both are declared. Thanks.
I don't know how to do exactly what you want, but maybe this helps:
var myFunc1: (String)-> String = { s in f(sourceString: s) }
var myFunc2: (String)-> String = { s in f(s) }
You can now call:
let s1 = myFunc1("one") // returns "version 2: one"
let s2 = myFunc2("two") // returns "version 1: two"
Interesting one this. I don’t think it’s possible without doing something along the lines of #marcos’s suggestion. The problem you is you can “cast away” the names in tuples:
let named_pair = (s: "hello", i: 1)
named_pair.s // hello
let anon_pair = named_pair as (String,Int)
// or anon_pair: (String,Int) = named_pair, if you prefer
anon_pair.s // no such member 's'
Now suppose you define two functions, identical except one has named arguments:
func f(s: String, i: Int) { println("_: \(s)") }
func f(#s: String, #i: Int) { println("s: \(s)") }
You can then call it via tuples with named vs unnamed arguments:
f(named_pair) // prints s: hello
f(anon_pair) // prints _: hello
// but if you try to call a named argument function with unnamed tuples:
func g(# s: String, # i: Int) { println("s: \(s)") }
g(anon_pair) // compiler error
let h = g
h(anon_pair) // compiler error
h(named_pair) // works
But because you can cast away these names you can do this:
// compiles and runs just fine...
(g as (String,Int)->())(anon_pair)
let k: (String,Int)->() = g
// as does this
k(anon_pair)
And this ability to do this means it’s not possible to use a type to disambiguate an function overloaded only by argument names, as far as I can tell.
Referencing func f (s: String) -> String { return "version 1: " + s }:
let myFunction = f(s:)
Referencing func f(sourceString s: String) -> String { return "version 2: " + s }:
let myFunction = f(sourceString:)
Referencing func anotherFunction(_ param: Any) {}:
let myFunction = anotherFunction(_:)
If you haven't overloaded the function, you don't need to explicity write out the parameter names when referencing the function.
Number of arguments should vary.
If the number of arguments are same then their data types should
vary.
Example
func f(x : String) -> NSString {
return a
}
func f(x : UInt) -> NSString {
return "{\(x)}"
}
I don't think you can. You can call one or the other:
println(f("test")) // version 1: test
println(f(sourceString: "test")) // version 2: test
the little knowledge , I have about first class function is that it supports passing functions as arguments and we can also return them as the values in another function ... I am very new in Swift programming language can anyone please elaborate it with an example.
A very simple example to demonstrate this behaviour:
func functionA() {
println("Hello by functionA")
}
func executeFunction(function: () -> ()) {
function()
}
executeFunction(functionA)
First-Class functions are functions that can return another functions.
For instance:
func operate( operand: String) -> ((Double, Double) -> Double)?{
func add(a: Double, b: Double) -> Double {
return a + b
}
func min(a: Double, b: Double) -> Double{
return a - b
}
func multi(a: Double, b: Double) -> Double {
return a * b
}
func div (a: Double, b: Double) -> Double{
return a / b
}
switch operand{
case "+":
return add
case "-":
return min
case "*":
return multi
case "/":
return div
default:
return nil
}
}
The function operate returns a function that takes two double as its arguments and returns one double.
The usage of this function is:
var function = operate("+")
print(" 3 + 4 = \(function!(3,4))")
function = operate("-")
print(" 3 - 4 = \(function!(3,4))")
function = operate("*")
print(" 3 * 4 = \(function!(3,4))")
function = operate("/")
print(" 3 / 4 = \(function!(3,4))")
When you don't care about the implementation of a function, using First-Class functions to return these functions become beneficials. Plus, sometimes, you are not responsible to develop (or not authorised ) of the functions like add, min. So someone would develop a First-Class function to you that returns these functions and it is your responsibility to continue ....
A function that returns a function while capturing a value from the lexical environment:
A function of an array of Comparables that returns a function of a test predicate that returns a function of a value that returns a Bool if the value is the extreme of the array under test. (Currying)
Any programming language is said to have first-class-functions, when functions are treated like normal variables. That means a function can be passed as parameter to any other function, can be returned by any function and also can be assigned to any variable.
i.e., (Referring apple's examples)
Passing function as parameter
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
Returning function
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
Properties of First class function
A function is an instance of the Object type.
You can store the function in a variable.
You can pass the function as a parameter to
another function.
You can return the function from a function.
You can store them in data structures such as hash tables, lists, …
refer https://www.geeksforgeeks.org/first-class-functions-python/
Given this simple currying function:
func foo(x:Int)(y:Int)->String{
return "\(x) with \(y)"
}
I'd expect to be able to do something like this:
let bar = foo(1)
bar(2) //<- error: Missing argument label 'y:' in call
If I label the call to bar (as in bar(y:2)) everything works fine. But I don't understand why the parameter name is necessary. Is there any way to avoid it?
The obvious thing:
func foo(x:Int)(_ y:Int)->String ...
does not seem to work.
It's a bug, you should file a radar at bugreport.apple.com
As a confirmation, if you place an underscore, like this
func foo(x: Int)(_ y: Int) -> String
you get a warning
Extraneous '_' in parameter: 'y' has no keyword argument name
So it explicitly says that y has no external name, but it still requires one when called, which is clearly against the language specification.
I believe it is a compiler bug, your example should work as described in The Swift Programming Language book where they mention declaring curried functions:
func addTwoNumbers(a: Int)(b: Int) -> Int {
return a + b
}
addTwoNumbers(4)(5) // Returns 9
https://bugreport.apple.com
good find!
I am not sure I fully understand your currying. Here is my take on it. I have a function foo as follows:
func foo(x:Int, y:Int) -> String{
return "\(x) with \(y)"
}
let bar = foo(1, 2) // gives "1 with 2"
I wish to curry this function to 'fix' the value for x, so do so as follows:
func fooCurry(x:Int) -> (Int -> String) {
func curry(y:Int) -> String {
return foo(x, y)
}
return curry
}
The above returns a new function which can be used as follows:
let curriedFoo = fooCurry(1)
let barWithCurry = curriedFoo(2) // gives "1 with 2"
The function returned by fooCurry has the signature (Int -> String), which means that the parameter does not have an external name.
Not the best syntax, but if you want to get around it for now, you can use the following for basic curried functions:
func foo(x:Int) -> Int -> String {
return {
return "\(x) with \($0)"
}
}
Then you can just do:
let bar = foo(1)
bar(2) //-> 1 with 2
Now obviously the problem with this becomes obvious when you want to write a curried function for piping four Ints for example:
func makerAdders(a:Int)(b:Int)(c:Int)(d:Int) {...}
becomes like this:
func add(a:Int) -> Int -> Int -> Int -> Int {
return {
b in return {
c in return {
d in return a + b + c + d
}
}
}
}
The inner closures make it a bit better than using inner functions, but again it defeats the purpose of the nice func add(a:Int)(b:Int)(c:Int)(d:Int) {return a+b+c+d} syntax.
Definitely a bug in the compiler as far as I can tell. Until it's fixed you can get a properly curried version of any function using these functions (note that I've included cases for two and three arguments, extend at your leisure:
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in return f(a,b) } }
}
func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
return { a in { b in { c in return f(a,b,c) } } }
}
Just use:
curry(addTwoNumbers)(1)(2)