Swift function parameters as local variables - swift

I am learning some of the fine point of Swift. On function parameters, the documentation says:
Function parameters are constants by default.
… and proceeds to discuss in-out parameters, which I suppose are Swift’s version of reference parameters.
In other languages, parameters behave as local variables, so you can do this with impunity:
func test(a: Int) {
a = a + 1 // cannot assign to a
print(a*2)
}
var x = 3
test(x)
print(x) // -> 3 as before
I know I can easily create local variables, but is there a Swift equivalent to parameters as local variables?
Note:
The SO description for the parameter tag even uses the word “label”:
Parameters are a type of variable used in a subroutine to refer to the data provided as input to the subroutine.

Before Swift 3, Swift used to have them. You used to be able to do something like this:
func f(var x: Int) { // note the "var" modifier here
x += 1
print(x) // prints 2
}
var a = 1
f(a)
print(a) // prints 1
But it was removed in Swift 3, via SE-0003. The Swift community decided that this is not a good feature. The motivations given in that proposal are:
var is often confused with inout in function parameters.
var is often confused to make value types have reference semantics.
Function parameters are not refutable patterns like in if-, while-, guard-, for-in-, and case statements.

Not sure I understood what do you try to achieve, but if you want to modify external x (so it would be not 3 as before), then you have to make function parameter as inout:
func test(_ a: inout Int) {
a = a + 1 // no error anymore
print(a*2)
}
var x = 3
test(&x)
print(x) // -> 4
Update:
func test(_ a: Int) {
var a = a // make read-write
a = a + 1
print(a*2)
}
var x = 3
test(x)
print(x) // -> 3 as before

Related

Is there shorthand to specify a specific overload when passing a function as a closure-based argument?

I'm wondering if Swift has a way to let you pass in a specific overload of a function as an argument to a second function that takes a closure with a matching signature, based on type, but without explicitly creating a closure yourself.
Note: This is not a problem I'm trying to solve. It's just a curiosity about the language based on something I ran into when creating an extension to a struct that suddenly broke the compile. It was easily addressed with a closure, like below. It just had me wondering if there was another way to solve it.
Here's code showing what I mean. Let's start with this struct Foo...
struct Foo {
let value: Int
}
Once defined, we can use it as part of a mapping operation via a closure, like so...
let values = [1, 2, 3, 4]
let foos = values.map{ Foo(value: $0) }
However, since the initializer itself already matches the signature of the closure argument type-wise, you can skip the manually-created closure entirely and pass in the function directly, like so...
let values = [1, 2, 3, 4]
let foos = values.map(Foo.init)
What's interesting to note is Swift's compiler finds that match based only on the type of the argument to init, not it's label, which was required earlier in the closure version.
What I discovered is by defining the following extension somewhere in code-scope view of the values.map(Foo.init) call site...
extension Foo {
init(valueToDouble value: Int) { self.value = value * 2 }
}
...that call site suddenly gets flagged as ambiguous and it breaks the compile. This is because even though the labels are different, the argument type--Int in this example--is the same and it doesn't know which one to use.
Now again, this is easily solved with a simple closure, like so...
// Original init
let foos = values.map{ Foo(value: $0) }
// or init in the extension
let foos = values.map{ Foo(valueToDouble: $0) }
I'm just wondering if the Swift compiler has some 'magic sauce' that lets me do something like this...
let foos = values.map(Foo.init(valueToDouble:))
...which obviously doesn't work. :)
So is there anything like that, or is the closure-based version the (only) way to go?
Update
Well, nothing "obvious" about it being wrong because what was wrong is I had a typo (now fixed) and the above syntax does in fact work! Thanks, Itai! :)
In Swift, the "base name" of a method is the method name without any arguments:
Foo.init(x:y:z:) → Foo.init
Foo.bar(_:) → Foo.bar
Foo.baz(baz:) → Foo.baz
Foo.quux() → Foo.quux
When referring to a method by name (rather than calling it), Swift will allow you to refer to it by its base name, so long as the usage is not ambiguous:
struct Foo {
func f(intValue: Int) {}
}
let f = Foo().f
However, when there are multiple methods with the same base name, you can run into situations with ambiguity:
struct Foo {
func f(intValue: Int) {}
func f(stringValue: String) {}
}
let f = Foo().f // error: ambiguous use of 'f'
When this happens, you can either:
Use explicit typing to help disambiguate the methods, if possible:
let f1: (Int) -> Void = Foo().f
let f2: (String) -> Void = Foo().f
Or,
Refer to the method by its fully-qualified name (name with parameter names included):
let f1 = Foo().f(intValue:)
let f2 = Foo().f(stringValue:)
In your case, because both methods have the same type signature, you can't use approach (1) to disambiguate between the calls, and will have to resort to (2).
The issue you ran into is that the parameter name you were using was slightly off:
// ❌ Foo.init(doubleValue:)
// ✅ Foo.init(valueToDouble:)
let foos = values.map(Foo.init(valueToDouble:)) // ✅
This does work, and will work as a shorthand instead of having to call the method directly inside of a closure argument.

Using Any instead of generics

Generics
Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.
Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code. In fact, you’ve been using generics throughout the Language Guide, even if you didn’t realize it. For example, Swift’s Array and Dictionary types are both generic collections. You can create an array that holds Int values, or an array that holds String values, or indeed an array for any other type that can be created in Swift. Similarly, you can create a dictionary to store values of any specified type, and there are no limitations on what that type can be.
The Problem That Generics Solve
Here’s a standard, nongeneric function called swapTwoInts(::), which swaps two Int values:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
This function makes use of in-out parameters to swap the values of a
and b, as described in In-Out Parameters.
The swapTwoInts(::) function swaps the original value of b into a,
and the original value of a into b. You can call this function to swap
the values in two Int variables:
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3" The
swapTwoInts(::) function is useful, but it can only be used with Int
values. If you want to swap two String values, or two Double values,
you have to write more functions, such as the swapTwoStrings(::) and
swapTwoDoubles(::) functions shown below:
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temporaryA = a
a = b
b = temporaryA
}
My question:
Instead of using generics function we could have just used Any type as the argument type right, that will simple as this
func swapTwoInts(_a:inout Any,_b:inout Int){
let temporaryA = a
a = b
b = temporaryA
}
So how to plays important role in swift?
Can I write code without generics like this
var num = 3
var numtwo = 5
print(num)
print(numtwo)
func swap(_ a: inout Any, _ b: inout Any){
let tempA=a
a=b
b=tempA
}
swap(a: &num, b: &numtwo)
In swift, you can assign value to a variable ONLY if the type of the variable is same with the value. So imagine you have this:
var a = 1
var b = 2
func swapTwoValues(_ a: inout Any, _ b: inout Any) {
let temporaryA = a
a = b
b = temporaryA
}
swapTwoValues(&a, &b) // <- Cannot pass immutable value as inout argument: implicit conversion from 'Int' to 'Any' requires a temporary
So compiler forces you to implicitly assign Any for the type of the variables. This is not what you want I think. So you have to tell the compiler that it doesn't matter the type of the arguments. The only thing matters is they both have same type to fulfill compilers need. So to achieve this, you can use generic or some kind of protocol.
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
swapTwoValues(&a, &b) // Done
Tip: You can swap values with tuple in single line of code without using temporaryVar like this: (Even without function and generic and etc.)
(a, b) = (b, a)

Are closures implemented as classes in the Swift compiler? Is a common closure a subclass of a throwing closure?

In Swift, the only reference type available to a programmer is a class. We know that closures are objects as they store references to variables captured in the parent scope. Closures are also reference types, according to Apple's Swift Programming Language Guide. You can see that assigning a closure doesn't create a copy of a captured environment and creates a new reference to the existing environment like in this example:
func test1() {
var x = 42
let f = {
print(x)
}
f() // prints 42
// `g` stores a reference to `f`
let g = f
x = 24
g() // prints 24
}
Are closures implemented in the Swift compiler with a similar "infrastructure" used for implementing classes? Is there a code in the compiler internals hidden from language users that could have looked like this when exposed?
// pseudocode
final class Closure<ArgumentType, ReturnType> {
}
typealias ArgumentType -> ReturnType = Closure<ArgumentType, ReturnType>
If so, is there a separate treatment for throwing closures that looks like this?
// pseudocode
final class ThrowingClosure<ArgumentType, ReturnType> {
}
typealias ArgumentType throws -> ReturnType = Closure<ArgumentType, ReturnType>
The main question here is, can we consider a common closure a subclass of a throwing closure? Because it clearly looks like you can assign a common closure to a whatever place that expects a throwing closure type:
func test(f: () throws -> Int, g: () -> Int) {
print((try? f())!)
print((try? g())!)
}
// prints 4 and 2
test(f: { 4 }, g: { 2 })

Currying func and keep param name/ label in Swift 4

In Swift 4, how can I curry func, and keep param label/ name:
func doSomething(a: A, b: B, c: C) {
}
let do_a = doSomething(a: value_a) // keep name a
let do_ab = do_a(b: value_b) // keep name b
let result = do_ab(c: value_c) // keep name c
With the answer from here Curry Function in Swift
And https://robots.thoughtbot.com/introduction-to-function-currying-in-swift
I can do, but the label is omitted
let curryDo = curry(doSomething)
let doA = curryDo(value_a) // but the a label is removed here.
How to keep param label/name in currying func?
Swift removed currying as a feature in version 3, and all current implementations use closures, which don't have labeled arguments.

Difference between two function calls - Swift

What is the difference between these two Swift functions. I don't quite understand it. I know they are two different functions but they have different parameter structures.
func addTwoIntegers(first x:Int, second y:Int) -> Int{
return x + y
}
func multiplyTwoIntegers(x:Int, y:Int) -> Int{
return x * y
}
The difference between the two functions are evident if you use them inside of Swift’s playground. The first function uses external naming parameters which allow you to see the name of the parameters in kind of an Objective-c style fashion. For example, when I call addTwoIntegers, I will be able to call it like this while passing in the arguments addTwoIntegers(first: x, second: y). The second function does not use external naming parameters so you can only call it passing in the arguments such as multiplyTwoIntegers(2,2)
Copy this code into Xcode’s playground.
func addTwoIntegers(first x:Int, second y:Int) -> Int{
return x + y
}
func multiplyTwoIntegers(x:Int, y:Int) -> Int{
return x * y
}
var x = addTwoIntegers(first: 10, second: 10)
var y = multiplyTwoIntegers(2, 2)
println(x)
println(y)
The first uses externally named parameters as well as local parameter names and the second uses just locally name parameters