Swift: why 'subscript(var digitIndex: Int) -> Int' is a valid function signature? - swift

This piece of code comes from Swift documentation https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
Apparently var is a reserved word, so why it is legal to declare: subscript(var digitIndex: Int) -> Int?
If I change the signature to subscript(#digitIndex: Int) -> Int, I will get this compiler error:
My questions are:
1) why the signature is valid?
2) why my change causes an exception?

Declaring a function argument with var means that it can be modified, is not a constant. In your case, without using var, you had a constant argument but you attempted to decrement it. Thus the error.
Your two cases are:
func foo (x: int) { /* x is a constant, like `let x: int` */ }
func foo (var x: int) { /* x is not a constant */ }

Related

Using overridden math function

Trying to compile this code
pow(10,2)
struct Test {
var i:Int
func pow(_ p:Int) -> Int { return pow(i,p) }
}
var s = Test(i:10)
s.pow(2)
gives me a compiler error. Obviously the standard math.h function pow was blinded out by Swift's scoping rules. This rather smells like a compiler error since the math.h version of pow has a different signature. Is there any way to invoke it, though?
There are two problems: The first is how pow(i,p) is resolved.
As described in Swift 3.0: compiler error when calling global func min<T>(T,T) in Array or Dictionary extension, this
can be solved by prepending the module name to the function call.
The second problem is that there is no pow function taking
two integer arguments. There is
public func powf(_: Float, _: Float) -> Float
public func pow(_: Double, _: Double) -> Double
in the standard math library, and
public func pow(_ x: Decimal, _ y: Int) -> Decimal
in the Foundation library. So you have to choose which one to use,
for example:
struct Test {
var i:Int
func pow(_ p:Int) -> Int {
return lrint(Darwin.pow(Double(i),Double(p)))
}
}
which converts the arguments to Double and rounds the result
back to Int.
Alternatively, use iterated multiplication:
struct Test {
var i: Int
func pow(_ p:Int) -> Int {
return (0..<p).reduce(1) { $0.0 * i }
}
}
I observed at https://codereview.stackexchange.com/a/142850/35991 that
this is faster for small exponents. Your mileage may vary.

Swift subtle difference between curried and higher order function

NOTE: This question was asked while Swift 2.1 was the latest.
Given:
class IntWrapper {
var i: Int = 1
}
func add(inout m: Int, i: Int) {
m += i
}
And a higher order function
func apply() -> (inout i: Int) -> () -> () {
return { (inout i: Int) -> () -> () in
return {
add(&i, i: 1)
}
}
}
Application as so results in the member variable value never changing:
var intW = IntWrapper()
print(intW.i) // Prints '1'
apply()(i: &intW.i)()
print(intW.i) // Prints '1'
However, when changing the function to curried form
func apply()(inout i: Int)() -> () {
add(&i, i: 1)
}
Application results in the member variable value changing:
var intW = IntWrapper()
print(intW.i) // Prints '1'
apply()(i: &intW.i)()
print(intW.i) // Prints '2'
I'm curious to why this is. I always thought that curried syntax was sugar for the higher ordered form of the function, but apparently there are semantic differences.
Additionally this accepted proposal to remove curried syntax from swift seems to state this is merely sugar, and I'm concerned we're losing more than syntax by removing this from the language. Is there a way to get the same functionality from a higher order function?

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.

Swift: reusing a closure definition (with typealias)

I'm trying to do create some closure definitions which I'm gonna use a lot in my iOS app. So I thought to use a typealias as it seemed the most promising ...
I did a small Playground example which shows my issue in detail
// Here are two tries for the Closure I need
typealias AnonymousCheck = (Int) -> Bool
typealias NamedCheck = (number: Int) -> Bool
// This works fine
var var1: AnonymousCheck = {
return $0 > 0
}
var1(-2)
var1(3343)
// This works fine
var var2: NamedCheck = {
return $0 > 0
}
var2(number: -2)
var2(number: 12)
// But I want to use the typealias mainly as function parameter!
// So:
// Use typealias as function parameter
func NamedFunction(closure: NamedCheck) {
closure(number: 3)
}
func AnonymousFunction(closure: AnonymousCheck) {
closure(3)
}
// This works as well
// But why write again the typealias declaration?
AnonymousFunction({(another: Int) -> Bool in return another < 0})
NamedFunction({(another: Int) -> Bool in return another < 0})
// This is what I want... which doesn't work
// ERROR: Use of unresolved identifier 'number'
NamedFunction({NamedCheck in return number < 0})
// Not even these work
// ERROR for both: Anonymous closure arguments cannot be used inside a closure that has exlicit arguments
NamedFunction({NamedCheck in return $0 < 0})
AnonymousFunction({AnonymousCheck in return $0 < 0})
Am I missing something or is it just not supported in Swift?
Thanks
EDIT/ADDITION:
The above is just a simple example. In real life my typealias is more complicated. Something like:
typealias RealLifeClosure = (number: Int, factor: NSDecimalNumber!, key: String, upperCase: Bool) -> NSAttributedString
I basically want to use a typealias as a shortcut so I don't have to type that much. Maybe typealias isn't the right choice... Is there another?
You aren't rewriting the typealias declaration in this code, you're declaring the parameters and return type:
AnonymousFunction({(another: Int) -> Bool in return another < 0})
Happily, Swift's type inference lets you use any of the following - pick the style that feels best to you:
AnonymousFunction( { (number: Int) -> Bool in number < 0 } )
AnonymousFunction { (number: Int) -> Bool in number < 0 }
AnonymousFunction { (number) -> Bool in number < 0 }
AnonymousFunction { number -> Bool in number < 0 }
AnonymousFunction { number in number < 0 }
AnonymousFunction { $0 < 0 }
I don't think you'll be able to do what you want. To simplify your example slightly, you can do this:
typealias NamedCheck = (number: Int) -> Bool
let f: NamedCheck = { $0 < 5 }
f(number: 1)
NamedFunction(f)
NamedFunction( { $0 < 5 } as NamedCheck)
But you can't do what you want, which is to rely on the fact that the tuple arg is called number to refer to it inside the closure without giving it as part of the closure:
// compiler error, no idea what "number" is
let g: NamedCheck = { number < 5 }
Bear in mind that you can name the parameter without giving it a type (which is inferred from the type of g):
let g: NamedCheck = { number in number < 5 }
but also, you can name it whatever you want:
let h: NamedCheck = { whatevs in whatevs < 5 }
NamedFunction(h)
Here's what I think is happening (this is partly guesswork). Remember how functions can have external and internal argument names:
func takesNamedArgument(#namedArg: Int) { etc... }
Or, to write it longhand:
func takesNamedArgument(namedArg namedArg: Int) { etc... }
But you can also give as the second, internal, name whatever you like:
func takesNamedArgument(namedArg whatevs: Int) { etc... }
I think this is what is happening with the closures with named tuples. The "external" name is "number", but you must give it an "internal" name too, which is what you must use in the function body. You can't make use of the external argument within your function. In case of closure expressions, if you don't give an internal name, you can use $0 etc, but you can't just skip it, any more than you can skip the internal name altogether and just rely on the external name when defining a regular function.
I was hoping that I could prove this theory by the following:
let f = { (#a: Int, #b: Int)->Bool in a < b }
resulting in f being of type (a: Int, b: Int)->Bool). This compiles, as does:
let g = { (number1 a: Int, number2 b: Int)->Bool in a < b }
but it doesn't look like the external names for the argument make it out to the type of f or g.
The syntax to create a closure is:
{ (parameters) -> return type in
statements
}
What's at the left of in is the closure signature (parameters and return value). In some cases the signature can be omitted or simplified when type inference is able to determine the number of parameters and their type, and the return value.
In your case it doesn't work because you are passing a type alias, but it is interpreted as a parameter name. The 3 lines work if either you:
name the parameter properly
NamedFunction({number in return number < 0})
AnonymousFunction({number in return number < 0})
use shorthand arguments:
NamedFunction({ return $0 < 0})
AnonymousFunction({ return $0 < 0})
use shorthand arguments and implicit return:
NamedFunction({ $0 < 0})
AnonymousFunction({ $0 < 0})

Why does the code produces error Type '(int, int)' does not conform to protocol 'IntegerLiteralConvertible'

With the code below, I get "Type '(int, int)' does not conform to protocol 'IntegerLiteralConvertible' instead of missing argument as one would expect. What's IntegerLiteralConvertible and why do you think the compiler produces this error instead for the code below?
I have looked at other SO posts regarding this error but have not gotten any insight from them.
func add(x:Int, y:Int) {
}
add(3)
My best guess is that it tries to convert the (3) tuple into a (Int, Int) tuple.
In fact, this is accepted by the compiler and works as expected:
func add(x: Int, y: Int) -> Int {
return x + y
}
let tuple = (4, 7)
add(tuple)
In playground that outputs 11, which is the expected sum result.
Note: the code above works if the func is global, with no named parameters. If it's an instance or class/static method, then the tuple must include parameter names:
class MyClass {
class func add(# x: Int, y: Int) -> Int {
return x + y
}
}
let tuple = (x: 3, y: 7)
MyClass.add(tuple) // returns 10
As for IntegerLiteralConvertible, it's used to make a class or struct adopting it to be initializable from a literal integer. Let's say you have a struct and you want to be able to instantiate by assigning an literal integer, you achieve it this way:
struct MyDataType : IntegerLiteralConvertible {
var value: Int
static func convertFromIntegerLiteral(value: IntegerLiteralType) -> MyDataType {
return MyDataType(value: value)
}
init(value: Int) {
self.value = value
}
}
and then you can create an instance like this:
let x: MyDataType = 5
It looks like you are trying to use currying — Swift has built-in support for this, but it is not automatic, so you have to be explicit about it when declaring your function:
func add(x:Int)(y:Int) -> Int {
return x + y
}
println(add(3)) // (Function)