Swift: Print Name of a Function Stored in a Variable

Swift: Print name of a function stored in a variable

Swift is a statically dispatched programming language. This results in Swift using memory addresses as much as possible when it needs to call a function. The side effect is the inability to capture the called function name, since in most of the cases it will be a simple memory address.

#function works because this the construct gets replaced at compile time by the caller function (it's not a runtime construct).

If you have the debug symbols available, you could reconstruct the function name from a binary address, however this would require access to the dSYM infrastructure from within your application, which it's unlikely that you'll want to do, since shipping you app along with the debug symbols is an invitation for hackers to reverse engineer with your app.

Dynamically dispatched languages, like Objective-C, keep a reference to the called function (selector), but only if the called function is a method (i.e. a member function). Other languages, like Ruby, JavaScript, are interpreted languages, which makes the function name available at all times.

Print passed variable name in funciton parameter argument as string (Swift)

There is no way for printValue func to know that you passed a value named positionX because printValue knows only about a variable named variable.
What you could do is changing the printValue func passing also the variable name as a String. E.g:

func printValue(_ value: Double, _ name: String) {
print("\(name) = \(value)")
}

and call it like:

override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad starts here")
let poisitionX: Double = 5.7
printValue(positionX, "positionX")
}

How to print variable name in swift?

You could change your struct to an enum

enum API: String {
case apiEndPoint = "example.com/profile?"
case apiEndPoint1 = "example.com/user?"
}

func doSomething(endPoint: API) {
print("\(endPoint): \(endPoint.rawValue)")
}

Example

doSomething(endPoint: .apiEndPoint)

apiEndPoint: example.com/profile?

How To Store Swift function in a variable

You have to help the compiler decide which function you want because it does not distinguish between parameter names when deciding if a function's signature is valid for assignment.

You can disambiguate your intent by being specific on the parameter names

let c:  (left :String) -> () = cars(left:)
let c2: (right:String) -> () = cars(right:)

How can I have a variable and a function with same name in Swift

it's not possible, as they share the same namespace:

https://forums.swift.org/t/why-doesnt-swift-allow-a-variable-and-a-function-with-the-same-name/5038

Assign print function to a variable

I believe you've found a known bug (or limitation) of the Swift compiler.

The built-in print function has three parameters. Parameter #1 is unlabeled and is type String ... (variadic). Parameter #2 has label separator, is type String, and has a default value. Parameter #3 has label terminator, is type String, and has a default value. Since parameters #2 and #3 have default values, you can call it like print("hello").

Closures (like myPrint) cannot use labeled parameters. So myPrint takes three unlabeled parameters. Parameter #1 is type String ... (variadic). Parameter #2 is type String. Parameter #3 is also type String. Closure parameters cannot have default values, so myPrint requires all three parameters. You cannot call it like myPrint("hello"), because you haven't passed anything for parameters #2 and #3 and they do not (and cannot) have default values.

In Swift, a variadic parameter (like parameter #1 of print and myPrint) consumes all arguments until in reaches a label. If you try to call myPrint("hello", " ", "\n"), all three arguments will be assigned to parameter #1, and nothing will be assigned to parameters #2 and #3.

Since you cannot have labeled parameters in a closure, there is no way to call your myPrint closure, because there is no way to pass values for parameters #2 and #3.

This is a known limitation. See SR-2475 and SR-494.

Class have a variable name same as function name

While both the property and method share the same base name add, they have different full names. The method's full name is add(_:) due to the fact that it has a parameter (with no argument label), and the property's full name is just add. The fact that their full names differ is what allows them to overload each other.

If the method had no parameters, then the compiler would not have allowed the overload, as their full names are now both add and therefore conflict:

class AClass {
var add: () -> Int {
return {
return 1
}
}

func add() -> Int { // error: Invalid redeclaration of 'add()'
return 2
}
}

Does the compiler always get the variable rather than call the function?

Assuming they have the same function type (such as in your example), then yes. There is an overload ranking rule that favours variables over functions:

    // If the members agree on instance-ness, a property is better than a
// method (because a method is usually immediately invoked).
if (!decl1->isInstanceMember() && decl2->isInstanceMember())
score1 += weight;
else if (!decl2->isInstanceMember() && decl1->isInstanceMember())
score2 += weight;
else if (isa<VarDecl>(decl1) && isa<FuncDecl>(decl2))
score1 += weight;
else if (isa<VarDecl>(decl2) && isa<FuncDecl>(decl1))
score2 += weight;

lib/Sema/CSRanking.cpp

In order to call the method, you can use refer to it by its full name, for example:

let a = AClass()
print(a.add(_:)(1)) // 21


Related Topics



Leave a reply



Submit