Swift functions inside a var - swift

I am learning Swift, and want to know how to add functions to a var,
here the JS example...
function suma (a, b){
return a + b
}
console.log("sua suma::", suma(2,3))
function multiplica (a, b){
return a * b
}
console.log("sua multiplik::", multiplica(2,3))
const operations = {
suma,
multiplica
}
console.log ("sum of first class::", operations.suma(2,3))
console.log ("mult of first class::", operations.multiplica(2,3))
so how do I achieve the same on Swift?
Here what I have tried:
import Foundation
func suma(a:Int, b:Int) -> Int {
return a + b
}
func multiplica(a:Int, b:Int) -> Int {
return a * b
}
print("sua suma", suma(a: 2, b: 3))
print("sua multiplica", multiplica(a: 2, b: 3))
var operations = {
suma
multiplica
}
print("sua operatio", operations.suma(a: 2, b: 3)
So how to edit the Swift code to call the function inside operations?
Cheers

You could use a tuple for this:
let operations = (
suma: suma
multiplica: multiplica
)
print("sua operatio", operations.suma(2, 3)
Note that the names are duplicated. The one before the : is just a label so that you can refer to it with a name, and the one after the : actually refers to the function.
I would advise against writing Swift code in a JS style. You should not group functions together like this. Write a class/struct instead, and declare the functions in there. Use static where necessary.

As Sweeper mentioned in his answer the Swift equivalent of the JS code would probably be a class with static functions.
class Operations {
static func suma(a:Int, b:Int) -> Int {
return a + b
}
static func multiplica(a:Int, b:Int) -> Int {
return a * b
}
}
You would call the functions like this
print("sua operatio \(Operations.suma(a: 2, b: 3))")

Related

Can't find variable name in scope

I am trying to learn Swift and I have bought a book to help me learn the language.
I can't understand why the following does not work:
func sum(_a: Int, _b: Int) -> Int {
return a + b
}
func subtract(_a: Int, _b: Int) -> Int{
return a - b
}
var someFunc: (Int, Int) -> Int
someFunc = sum
print(someFunc(5, 4))
someFunc = subtract
print(someFunc (5, 4))
The error I get is Cannot find 'a' (or 'b') in scope.
If I remove the underscores it does give the right answer.
I thought the point of the underscore was that the underscore meant that nothing is assigned to it and the function you want to call that returns a result but you don't care about the returned value.
Can somebody explain in simple language why this does not work.
You have to put a space between _ a, _ b. Like this:
func sum(_ a: Int, _ b: Int) -> Int {
return a + b
}
func subtract(_ a: Int, _ b: Int) -> Int{
return a - b
}
var someFunc: (Int, Int) -> Int
someFunc = sum
print(someFunc(5, 4))
someFunc = subtract
print(someFunc (5, 4))
You can learn these functions in a Playground. You will see there errors, etc...
The underscore means that the parameter will not have a label when calling then function making it more compact.
Below is 3 different ways to use labels for parameters when creating a function
Function with anonymous (no label) parameters
func example1(_ a: Int, _ b: Int) -> Int {
a + b
}
let sum = example1(3, 5)
Function with parameters as labels
func example2(a: Int, b: Int) -> Int {
a + b
}
let sum = example2(a: 3, b: 5)
Function with different parameter names and labels
func example3(first a: Int, second b: Int) -> Int {
a + b
}
let sum = example3(first: 3, second: 5)
When declaring functions in Swift, you can provide names for parameters passed to a function. It is handy to make your functions more readable when using in code. E.g. you can declare it like so:
func move(from startPoint: Int, to endPoint: Int) -> Int {
return startPoint + endPoint
}
In your function's body you can use variables' names, which is quite understandable for you. And usage of your functions will look like:
res = move(from: 1, to: 2)
I this way it will be more readable for any person who will read or use your code. It will be more clear even for you, when you'll return to this code some time later.
You can also declare the function in the way not to show any variables' names at all. For this you can use "_" as a variable's name. And this is the case from your learning book.
Guys have already answered your question. I just wanted to give you a bit deeper understanding.

Generic factory method and type inference

I have the following class with a generic factory method:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
}
extension Something {
class func zip<A, B>(_ a: A, _ b: B) -> Something<(A, B)> {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
How come I can’t call zip without explicitly specifying the return type?
// ERROR: Cannot invoke `zip` with an argument list of type `(Int, Int)`
let y = Something.zip(1, 2)
// OK: Works but it’s unacceptable to require this on caller's side
let x = Something<(Int, Int)>.zip(1, 2)
Thank you for your time!
The reason you're seeing this is that there's nothing in this call:
let y = Something.zip(1, 2)
That tells Swift what T should be.
Your call implicitly specifies what A and B should be, and specifies the method should return Something<A, B>. But that Something<A, B> is not connected to Something<T>.
In fact, nothing at all in your call is connected to T; T is left unspecified, so it could be anything. I mean that literally—you can actually put (nearly) any random type in the angle brackets after Something and it'll work exactly the same:
let y = Something<UICollectionViewDelegateFlowLayout>.zip(1, 2)
What you would really like to do is somehow specify that T has to be a tuple and the two parameters are of the same types as the tuple's elements. Unfortunately, Swift doesn't currently have the features needed to properly do that. If the language were more sophisticated, you could say something like this:
extension<A, B> Something where T == (A, B) {
class func zip(a: A, _ b: B) -> Something {
let initial = (a, b)
return Something(initial: initial)
}
}
But for now, you'll have to make do with this horrible hack, which works by meaninglessly reusing the T type parameter so that it's no longer at loose ends:
extension Something {
class func zip<B>(a: T, _ b: B) -> Something<(T, B)> {
let initial = (a, b)
return Something<(T, B)>(initial: initial)
}
}
In short explanation, you use generics not correct. It's not realtime feature, it's precompile thing. If you need to make abstract class from generic input values, see and do like this:
class Abstract<T> {
init(value: T) {
print("inputed value: \(value)")
}
}
class Something {
class func zip<A, B>(value: A, value2: B) -> Abstract<(A, B)> {
print("Something.zip", value, value2)
return Abstract<(A, B)>(value: (value, value2))
}
}
Something.zip(5, value2: 40) // "inputed value: (5, 40)"
T simply isn't related to A and B in that way and so can't be inferred.
Eg.
let z = Something<(String, String)>.zip(1, 2)
let z2 = Something<AnyObject>.zip(1, 2)
work just fine to return a Something<(Int, Int)>
You can introduce type inference for your case like this:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
class func zip<A, B>(_ a: A, _ b: B) -> Something<T> where T == (A, B) {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
let y = Something.zip(1, 2) //works

Im confused on how this function is being called, there is no call for it?

I'm confused on how getFunctionNeededForReference is running. There is no call for it and where are the functions returned to? where are they going? I know they are being referenced but where are the functions going to, there is not call for getFunctionNeededForReference in the beginning? there is no call sending the argument flag anyway?
func add ( a: Int , b : Int)-> Int {
//returing a result and not a variable
return a + b
}
func multiply ( a: Int, b: Int) -> Int{
return a * b
}
// declaring a function as a variable, it takes in 2 Ints and returns an Int
var f1 : (Int, Int)-> Int
f1 = add
f1 = multiply
// Function as a parameter
func arrayOperation (f: (Int, Int) -> Int , arr1: [Int] , arr2: [Int]) -> [Int]
{
// Declaring and initializing an empty array to return
var returningArray = [Int]()
for (i, val) in enumerate(arr1)
{
returningArray.append(f(arr1 [i], arr2 [i]))
}
return returningArray
}
arrayOperation(add, [2,3,4], [4,5,6])
arrayOperation(multiply, [2,3,4], [4,5,6])
//Function as a return value
func getFunctionNeededForReference (flag : Int) -> (Int,Int) ->Int
{
if flag == 0 {
return add
}else {
return multiply
}
}
What you've posted is just some example code showing things that Swift supports. It's not code that's useful for anything. It's just demonstrating Swift's syntax for first-class functions.
If you don't understand what “first-class functions” means, you can look up the term in your favorite search engine and find many explanations.

Why do curried functions require external parameter names?

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)

Curry Function in Swift

I want to make a function that return a curry function like below
func addTwoNumbers(a: Int)(b: Int) -> Int {
return a + b
}
addTwoNumbers(4)(b: 6) // Result: 10
var add4 = addTwoNumbers(4)
add4(b: 10) // returns 14
What is the return type of such function and how can I generate a function like this using a function that take Variadic parameters.
func generateCurry(.../*Variadic parameters*/) -> .../*curry function type*/ {
return ...//curry function
}
I want a generic solution and not take only Int as arguments in the parmeter of the generateCurry function
let curried = curry(func(a, b, c) {
print(a + b + c)
})
curried(1)(2)(3) //prints 6
You can achieve this pretty easily with closures:
/// Takes a binary function and returns a curried version
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a, b) } }
}
curry(+)(5)(6) // => 11
let add: Int -> Int -> Int = curry(+)
add(5)(6) // => 11
It would be really nice to be able to do the same thing for functions that take 3, 4 or more arguments, but without duplicating the implementation. The signature of such a function might start something like:
/// Take a function accepting N arguments and return a curried version
func curry<T>(args: T...) -> /* ? */
What would the return type be? It would change based on the input to the function. This definitely isn't possible in Swift at the moment, and I don't think it would be possible at all without some kind of macro system. But even with macros I don't think the compiler would be satisfied unless it knew the length of the list at compile-time.
Having said that, it's really straight-forward to manually overload the currying function with a version that accepts 3, 4, 5 or more parameters:
func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
return { a in { b in { c in f(a,b,c) } } }
}
func curry<A,B,C,D,E>(f: (A, B, C, D) -> E) -> A -> B -> C -> D -> E {
return { a in { b in { c in { d in f(a,b,c,d) } } } }
}
// etc.
I'm not sure this is actually going to be possible in the same way it is inside of languages like Python.
The core problem I see to having a single generic solution is the strong typing of the closures/funcs you want to accept.
You could fairly easily create a curry function that worked on a specific or common function signature, but as far as a general purpose curry I don't see a way for it to work. The issue is more than about the types of the arguments (as mentioned in comments) but also with the number of them.
I've written up a simple example of how you could implement a curry function. It works, but I don't see a sane way to have a truly generic one like you can in more loosely typed languages.
func add(a1: Int, a2: Int) -> Int {
return a1 + a2
}
func curry(argument: Int, block: (Int, Int) -> Int) -> Int -> Int{
func curried(arg: Int) -> Int {
return block(argument, arg)
}
return curried
}
curry(5, add)(6)
In case you want to quickly get the curry function for any number of parameters, it's possible to generate it as shown in this gist.
The code is in Swift 2.2 and generates code for Swift 2.2 (at the moment). It uses simple template-based approach (a possible alternative is constructing an AST followed by code-generation):
func genCurry(n: Int, indent: Indent = .fourSpaces, accessLevel: AccessLevel = .Default, verbose: Bool = false) -> String {
// ...
// The bulky park is skipped for clarity.
return accessLevel.asPrefix + "func curry<\(genericParams)>(f: \(fSig)) -> \(curriedSig(n)) {\n"
+ indent.single + "return \(closure)\n"
+ "}\n"
}
I recently found that currying was removed back in Swift3. I created my own version which is repetitive but does the job.
precedencegroup CurryPrecedence {
associativity: left
higherThan: MultiplicationPrecedence
}
infix operator <<== :CurryPrecedence
//1 param
func <<==<A,Z>(_ f: #escaping (A) -> (Z), _ p:A) -> () -> (Z) {
{ f(p) }
}
//2 param
func <<==<A,B,Z>(_ f: #escaping (A, B) -> (Z), _ p:B) -> (A) -> (Z) {
{ (A) in f(A,p) }
}
//3 param
func <<==<A,B,C,Z>(_ f: #escaping (A, B, C) -> (Z), _ p:C) -> (A, B) -> (Z) {
{ (A, B) in f(A,B,p) }
}
//4 param
func <<==<A,B,C,D,Z>(_ f: #escaping (A, B, C, D) -> (Z), _ p:D) -> (A, B, C) -> (Z) {
{ (A, B, C) in f(A,B,C,p) }
}
To use it:
let ten = (addTwoNumbers <<== 6 <<== 4)()
or
let ten = (addTwoNumbers <<== 6)(4)