How to get function's parameter value without parameter name in swift? - swift

func test(_: [Int]) {
print("xxx")
}
test([1,2,3])
I saw this code is valid in swift, how can I get the value passed into test?

To explicitly answer your question:
how can I get the value passed in test?
You can't, in the same way that after
let _ = someFunction()
you have no way to get at the return value of someFunction. That's really the whole point of _ which basically means "I'm ignoring this intentionally".

In order to get the parameter value inside the function, you have to specify the parameterName. Swift's function has this kind of structure :
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
where argumentLabel is used on the function caller, for example
func eat(byWhom person: String){}
would become
eat(byWhom: "Victor")
in the caller code.
On the other hand, you can get the "Victor" value from the parameterName :
func eat(byWhom person: String){
print(person) // should print "Victor"
}

create function like this
func test(_ value: [Int]) { }
and then you can call it like this.
test([1,2]) without mentioning the parameter name.

There's no chance to get functions parameter value w/o its name. That is why it is being used. But you can do this:
func test(_ value: [Int]) {
print(value)
}
test([1,2,3])

Related

How can I change an inout parameter from within a escaping closure?

I was trying to modify a parameter of function from within a escaping closure as below:
var completion = [()->Void]()
func addCompletion(closure: #escaping ()->Void) {
completion.append(closure)
}
func testAdd(v: inout Int) {
addCompletion{
v = 1 // Compiler tells 'Escaping closure captures 'inout' parameter 'v'
print("hello1 \(v)")
}
}
var x = 0
testAdd(v:&x)
for comp in completion {
comp()
}
I was wondering if there is another way to let escaping closure change surrounding variable (as function's inout parameter), besides making it into reference type as a class object.
inout is specified to have a "copy-in copy-out" behaviour. The value of x is copied when you call the function. In the function body, the copy of x can be modified, or whatever. Then, when the function returns, the copy is copied again, and assigned to the original x. "Call-by-reference" could happen as an optimisation.
This explains why you can't modify an inout parameter in an escaping closure. The swift compiler can't possibly know when every escaping closure returns, to copy the modified value back.
You can use an actual pointer:
func testAdd(v: UnsafeMutablePointer<Int>) {
addCompletion{
v.pointee = 1 // you just need to change all references to "v" to "v.pointee"
print("hello1 \(v.pointee)")
}
}
Alternatively, if you don't like pointers, you can also do this trick (adapted from my other answer):
func testAdd(modifyV: #escaping ((inout Int) -> Void) -> Void) {
addCompletion{
modifyV { v in // here you can change v however you like!
v = 1
print("hello1 \(v)")
}
}
}
You just need to change the caller to:
testAdd { $0(&x) }

In Swift 4, how can you get the string-representation of a data type stored in a variable of type 'Any'?

What is the easiest way to get the string-representation of a value's data type if that value is stored in an 'Any' variable?
For instance, I'm debugging code that has this...
extension SomeClass : Mappable{
static func map(value:Any) -> SomeClass{
return Parse(value)
}
}
I'm trying to figure out what data types are being passed through the function, but if I use type(of:) I keep getting 'Any' and not the value held in it.
extension SomeClass : Mappable{
static func map(value:Any) -> SomeClass{
let nameOfType = ??? <-- This is what I'm trying to figure out
log(nameOfType)
return Parse(value)
}
}
I simply want to print the data type to the debug window, not do testing with is or as, etc. It's strictly for logging/debugging reasons.
Ok, I figured it out. It's a two-step process.
You have to:
Use type(of:) to get the type of the variable (as others have described)
Use String(describing:) to get the name of that type (that was the missing piece)
Here's an example...
let typeName = String(describing: type(of:value))
That's what I was after. Thanks for the other answers. Hope this helps!
static func map(value:AnyObject) -> AnyClass{
return value.classForCoder
}
Or
static func map(value:Any) -> AnyClass{
return (value as AnyObject).classForCoder
}
In Swift 4 you can achieve that like this:
static func map(value: Any) -> Any.Type {
return type(of: value)
}

Difference between Closure Functions and Functions

I'm trying to learn swift and came across closures got the hang of it but still I have a question to ask, couldn't find any answers on the internet and I'm not sure if it's appropriate to ask here but I really need an answer on this.
say we have the following class
class Human{
var gender:String?
private func fCheckGender(pGender:String?){
guard pGender != nil else {
print("Gender not specified")
return
}
if pGender == "M"{
print("Male")
}
else if pGender == "F"{
print("Female")
}
else{
print("gender Unknown")
}
}
private func cCheckGender( pGender:#autoclosure ()->(String?)){
guard pGender() != nil else {
print("Gender not specified")
return
}
if pGender() == "M"{
print("Male")
}
else if pGender() == "F"{
print("Female")
}
else{
print("gender Unknown")
}
}
func MyCheckGender(){
fCheckGender(pGender: gender)
cCheckGender(pGender: gender)
}
}
var myHuman:Human = Human()
myHuman.gender = "M"
myHuman.MyCheckGender()
I would like to know the difference of
fCheckGender and cCheckGender when and where should I use the closures
Thanks in advance!
P.S I have intentionally used void->String ()->(String?)
I only want to learn the difference in this scenario. I'm sorry for my bad english
Closure:
Closure is a block of code, treat it like an unnamed function.
When a closure is passed as an argument, the closure is not evaluated till the code inside the function invokes the argument.
Auto closure:
Auto closure is just a closure which packages the parameter values along with it.
When you define an autoclosure, there would be no parameters to the closure.
Difference between fCheckGender and cCheckGender:
fCheckGender takes a String value as an argument.
cCheckGender takes closure as an argument.
When cCheckGender is invoked, the closure is passed an argument, at this point, the closure is only passed as an argument, the closure is not executed. Only when the closure parameter is used inside the function, the closure gets executed.
The example you have stated might not be the best one to demonstrate the difference.
Let's consider a different example:
Example:
func add(a: Int, b: Int) -> Int {
print("add")
return a + b
}
func f1(pValue: Int) {
print("f1")
print("value = \(pValue)")
}
func f2(pClosure: (Int, Int) -> Int, pA: Int, pB: Int) {
print("f2")
let value = pClosure(pA, pB)
print("value = \(value)")
}
//In autoclosure the closure always takes no parameters, because the closure is packaged with parameter values while invoking
func f3(pClosure: #autoclosure () -> Int) {
print("f3")
let value = pClosure()
print("value = \(value)")
}
f1(pValue: add(a: 10, b: 20))
print("=====================\n")
f2(pClosure: add, pA: 10, pB: 20)
print("=====================\n")
f3(pClosure: add(a: 10, b: 20))
print("=====================\n")
Output:
add
f1
value = 30
=====================
f2
add
value = 30
=====================
f3
add
value = 30
=====================
Explanation of example:
In the function f1 pValue is an Int value.
So when f1 is invoked, the add is evaluated
In the functions f2 and f3 pClosure is a closure.
pClosure (closure) is not evaluated till it is invoked inside the function.
Note:
Focus on f3 first which accepts a closure as the argument.
Once you fully understand f3, then examine f2.
Auto closure captures the parameter values when it is invoked and later uses it.
Why and when do we need to pass a closure instead of a value:
There might be a scenario, where you would like to defer the execution of add till the time the function f2 invokes it.
There might be a scenario, where you make an asynchronous request and you want a piece of code to execute when the request completes. In this case you might pass a closure. (Closure need not always return a value, it is an unnamed function, so it can accept parameters)
Why and when do we need to an autoclosure:
When you want to defer the execution of add and also capture the value of it's parameters.
Suggestion:
Though time consuming, it is best for you to go through the Swift documentation from the beginning to fully understand it.
Reference:
As Hamish has pointed please read about closures, then auto closures from https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
Function
In the function createUser the firebase runs background of the app so when the user enters button of the login app the function "RegisteredButtonPressed" is trigged.
Inside the registeredButtonPressed function the username & password are given by the user if its correct then "completion" function is trigerred. After that "completed" function will be activated the it prints into console.
same code concept I have written in closure.
class Firebase {
func createUser (username: String, password: String, completion: (Bool, Int) -> Void) {
let isSuccess = true
let userID = 123
completion(isSuccess, userID)
}
}
class MYApp {
func registerButtonPressed () {
let firebase = Firebase()
firebase.createUser(username: "Gullu", password: "123456", completion: completed(isSuccess:userID:))
}
func completed (isSuccess: Bool, userID: Int) {
print("Registration id is success \(isSuccess)")
print("User id is \(userID)")
}
}
Closure
Converting func keyword to closure
remove the func keyword & name of function
Bring the starting curly bracket after func starts in the beginning (in "func completed" after userid: Int a curly bracket is there , so bring it before the second bracket starts).
Replace it with "in" keyword
instead of calling the completed function cut paste the 3rd point above code & paste it to completion inside firebase.creativeUser
Delete the completion parameter to make it trailing closure
class MYApp {
func registerButtonPressed () {
let firebase = Firebase()
firebase.createUser(username: "Gullu", password: "123456") {
(isSuccess: Bool, userID: Int) in
print("Registration id is success \(isSuccess)")
print("User id is \(userID)")
}
}
}

What exactly differentiate two functions in Swift?

I wonder what makes two "similar functions" different with each other and can be called unambiguously
This is what I've learned from self-study
The uniqueness comes from: Function name + Argument order and argument name + return type. The combination of them must be unique to be able to make the function unique (Please see the example below)
Nmu1 and Num2 would cause ambiguous, because the return type (doesn't has the so called return name, the function name already act as this role) is not referred when calling a function
Although Num3 function has a different parameter name, it won't uniquely separate it from the function in Num1 and Num2. Because the argument name won't referred when the function had been called therefore, only a different argument name won't make a function unique; And the function in Num4 is different with all functions above, because its signature Function name + Argument order and argument name + return type is unique among all previous 3 functions.
Num5 and Num6 functions are different with each other, for they have different argument orders when they were defined
//Num1
func foo(guy name: String) -> String {
return "Hi \(name)"
}
//Num2
func foo(guy name: String) {
print("Hi \(name)")
}
//Num3
func foo(guy called: String) -> String {
return "Hi \(called)"
}
//Num4
func foo(dude name: String) -> String {
return "What's up \(name)"
}
//Num5
func foo(man name: String, from place: String) {
print("Hi! I'm \(name) I come from \(place)")
}
//Num6
func foo(from place: String, man name: String) {
print("Hi! I'm \(name) I come from \(place)")
}
Question: I might miss or possibly even misunderstood some parts. It would be very nice of you that you can correct me and add the parts I missed
Thanks
[Update]
Let's discuss a bit more on this issue. Let's started with the question that discuss the difference between Argument and Parameter. This question makes a lot of sense here!
Back to the quote from the official swift document
Each function parameter has both an argument label and a parameter name. The argument label is used when calling the function; each argument is written in the function call with its argument label before it. The parameter name is used in the implementation of the function. By default, parameters use their parameter name as their argument label.
Argument, Parameter, Argument Labels and Parameter Names are different. The difference here can be used to differential functions.
Functions with same parameter name, same parameter order, same return type and even same function body can be differentiated from different argument Labels.
func foo(dude name: String) -> Int {
print("Hi \(name)!")
return 1
}
func foo(man name: String) -> Int {
print("Hi \(name)!")
return 1
}
//foo(dude: String) & foo(man: String) is identical when calling
For more information please address to Multiple functions with the same name
Defined as Obj-C- compatible methods, Num1 and Num2 can not exist together, and you will have error defining them in NSObject subclass; however, you can mark them as #nonobjc and error will gone, since Swift able to choose correct overload by return type expected:
//Num1
#nonobjc func foo(guy name: String) -> String {
return "Hi \(name)"
}
//Num2
#nonobjc func foo(guy name: String) {
print("Hi \(name)")
}
All your other points, except this mark, seems correct to me

How do I declare a function that takes *any* block/closure as parameter?

I want to pass any block around as a parameter, without wanting to know the precise block parameter/return type.
func myFunc(block:(xxx) -> yyy) -> AnyObject {
...
}
So xxx in my code should match any number of parameters (including none) of any type. And yyy could be anything from void to AnyObject to an NSObject.
You can make a generic function:
func myFunc<A,B>(block:A -> B) -> AnyObject {
...
}
Unfortunately, you can't do that in Swift. Function Types are defined by their parameters and return types and there is no general function type. Functions also don't conform to Any or AnyObject, so you also can't use those either.
In Swift it's still possible to use the Selector. Maybe you can achieve what you want using that. See sample below:
func myFunc(selector:Selector) -> AnyObject {
self.performSelector(selector)
}
func someSelector() -> String {
return "test"
}
var result: AnyObject = myFunc(Selector("someSelector"))