I'd like to use the name of function to resolve some problems, but #function seems not to work well with #inline(__always), here is my codes:
#inline(__always) func log() {
print(#function)
}
func a() { log() } // want 'a()', but got 'log()'
func b() { log() }
func c() { log() }
//...
Can anybody explain? or that's just a stupid idea.
If your intention is to print the name of the function which calls
log(), then you should pass it as default argument (which is evaluated
in the context of the caller), as demonstrated
in Building assert() in Swift, Part 2: __FILE__ and __LINE__ in the Swift blog.
Example:
#inline(__always) func log(_ message: String, callingFunction: String = #function) {
print("\(callingFunction): \(message)")
}
func a() { log("Hello world") }
func b() { log("Foo") }
func c() { log("Bar") }
a() // a(): Hello world
b() // b(): Foo
c() // c(): Bar
This works regardless of whether the log function is inlined or not.
(Inlining does not change the semantics of a program. In particular,
it does not mean that the source code of func log is included from
the source code of func a() and compiled as a single function.)
Related
New to Swift and I am currently getting around passing a function as an optional parameter in the following way:
import Foundation
func foo()
{
print("Foo")
}
func bar()
{
print("Bar")
}
func dummy()
{
return
}
func myFunc()
{
myFunc(callBack: dummy())
}
func myFunc(callBack: (Void))
{
foo()
callBack
}
myFunc()
myFunc(callBack: bar())
i.e. exploiting polymorphism
This seems like an inelegant way to do this, is there a better way,
Thanks,
Tom
edit:
I am aware I could shorten this by doing:
import Foundation
func foo()
{
print("Foo")
}
func bar()
{
print("Bar")
}
func dummy()
{
return
}
func myFunc(callBack: (Void) = dummy())
{
foo()
callBack
}
myFunc()
myFunc(callBack: bar())
But I would still say this is an inelegant solution
You can easily define a default value for a function as parameter:
func foo(completion: () -> Void = { }) {
completion()
}
You could also have it be nil by default:
func foo(completion: (() -> Void)? = nil) {
When it's an optional closure, you'll have to call it like this:
completion?()
Your are referring to default arguments:
You can define a default value for any parameter in a function by assigning a value to the parameter after that parameter’s type. If a default value is defined, you can omit that parameter when calling the function.
So you need something like:
func myfunc (callback: ()->void = dummy) {
LinusGeffarth notes that callbacks in Swift are called completion, or closure as avismara notes.
Full code with answer applied:
import Foundation
func foo()
{
print("Foo")
}
func bar()
{
print("Bar")
}
func myFunc(completion: () -> Void = { })
{
foo()
completion()
}
myFunc()
myFunc(completion: bar)
Umm, are you passing function as an optional parameter, though? It looks like you have written a method that accepts Void, you have a function that accepts Void and you are just calling that method. I don't see any trace of polymorphism here except probably that the myFunc has multiple signatures. This method is an inelegant solution not because it is inelegant, but because it isn't a solution.
Here is a correct example of polymorphism in functional systems:
func printA() {
print("A")
}
func printB() {
print("B")
}
//This method accepts a function as a parameter
func higherOrderPrinter(with print: () -> Void ) {
print() //Can be anything, depends on the method you send here. Polymorphism much? :)
}
higherOrderPrinter(with: printA) //Prints A. See carefully how I am NOT doing printA()
higherOrderPrinter(with: printB) //Prints B
//In fact...
higherOrderPrinter {
print("C")
} //Prints C
In ruby I can pass a block into a method and have the block evaluated in the context of the receiving object.
class Receiver
def method_a
puts "hello from method_a"
end
def method_b
puts "hello from method_b"
end
def define_something &action
method_a
instance_eval &action
end
end
thing = Receiver.new
thing.define_something { method_b }
which produces the following output:
hello from method_a
hello from method_b
Whats the right way to implement something like this in Swift?
Here is what I have, but of course Xcode complains that methodB is an unresolved identifier.
class Receiver {
func methodA() {
print("hello from method A")
}
func methodB() {
print("hello from method B")
}
func defineSomething( action: () -> Void ) {
methodA()
action()
}
}
let thing = Receiver()
thing.defineSomething { methodB() }
BTW, this can also be done in Kotlin which has the idea of a function type with a receiver.
for example the following produces similar output to what the ruby example produces.
class Receiver {
fun methodA() = println("hello from methodA")
fun methodB() = println("hello from methodB")
fun defineSomething( action: Receiver.() -> Unit) {
methodA()
action()
}
}
fun main(args: Array<String>) {
val thing = Receiver()
thing.defineSomething { methodB() }
}
hello from methodA
hello from methodB
I don't know of a way to do that in the language. You can do it manually by having action take a Receiver instance as input, and then call action(self) inside of defineSomething(action:).
class Receiver {
func methodA() {
print("hello from method A")
}
func methodB() {
print("hello from method B")
}
func defineSomething(action: (_: Receiver) -> Void ) {
methodA()
action(self)
}
}
let thing = Receiver()
thing.defineSomething { $0.methodB() }
hello from method A
hello from method B
I have a protocol P that returns a copy of the object:
protocol P {
func copy() -> Self
}
and a class C that implements P:
class C : P {
func copy() -> Self {
return C()
}
}
However, whether I put the return value as Self I get the following error:
Cannot convert return expression of type 'C' to return type 'Self'
I also tried returning C.
class C : P {
func copy() -> C {
return C()
}
}
That resulted in the following error:
Method 'copy()' in non-final class 'C' must return Self to conform
to protocol 'P'
Nothing works except for the case where I prefix class C with final ie do:
final class C : P {
func copy() -> C {
return C()
}
}
However if I want to subclass C then nothing would work. Is there any way around this?
The problem is that you're making a promise that the compiler can't prove you'll keep.
So you created this promise: Calling copy() will return its own type, fully initialized.
But then you implemented copy() this way:
func copy() -> Self {
return C()
}
Now I'm a subclass that doesn't override copy(). And I return a C, not a fully-initialized Self (which I promised). So that's no good. How about:
func copy() -> Self {
return Self()
}
Well, that won't compile, but even if it did, it'd be no good. The subclass may have no trivial constructor, so D() might not even be legal. (Though see below.)
OK, well how about:
func copy() -> C {
return C()
}
Yes, but that doesn't return Self. It returns C. You're still not keeping your promise.
"But ObjC can do it!" Well, sort of. Mostly because it doesn't care if you keep your promise the way Swift does. If you fail to implement copyWithZone: in the subclass, you may fail to fully initialize your object. The compiler won't even warn you that you've done that.
"But most everything in ObjC can be translated to Swift, and ObjC has NSCopying." Yes it does, and here's how it's defined:
func copy() -> AnyObject!
So you can do the same (there's no reason for the ! here):
protocol Copyable {
func copy() -> AnyObject
}
That says "I'm not promising anything about what you get back." You could also say:
protocol Copyable {
func copy() -> Copyable
}
That's a promise you can make.
But we can think about C++ for a little while and remember that there's a promise we can make. We can promise that we and all our subclasses will implement specific kinds of initializers, and Swift will enforce that (and so can prove we're telling the truth):
protocol Copyable {
init(copy: Self)
}
class C : Copyable {
required init(copy: C) {
// Perform your copying here.
}
}
And that is how you should perform copies.
We can take this one step further, but it uses dynamicType, and I haven't tested it extensively to make sure that is always what we want, but it should be correct:
protocol Copyable {
func copy() -> Self
init(copy: Self)
}
class C : Copyable {
func copy() -> Self {
return self.dynamicType(copy: self)
}
required init(copy: C) {
// Perform your copying here.
}
}
Here we promise that there is an initializer that performs copies for us, and then we can at runtime determine which one to call, giving us the method syntax you were looking for.
With Swift 2, we can use protocol extensions for this.
protocol Copyable {
init(copy:Self)
}
extension Copyable {
func copy() -> Self {
return Self.init(copy: self)
}
}
There is another way to do what you want that involves taking advantage of Swift's associated type. Here's a simple example:
public protocol Creatable {
associatedtype ObjectType = Self
static func create() -> ObjectType
}
class MyClass {
// Your class stuff here
}
extension MyClass: Creatable {
// Define the protocol function to return class type
static func create() -> MyClass {
// Create an instance of your class however you want
return MyClass()
}
}
let obj = MyClass.create()
Actually, there is a trick that allows to easily return Self when required by a protocol (gist):
/// Cast the argument to the infered function return type.
func autocast<T>(some: Any) -> T? {
return some as? T
}
protocol Foo {
static func foo() -> Self
}
class Vehicle: Foo {
class func foo() -> Self {
return autocast(Vehicle())!
}
}
class Tractor: Vehicle {
override class func foo() -> Self {
return autocast(Tractor())!
}
}
func typeName(some: Any) -> String {
return (some is Any.Type) ? "\(some)" : "\(some.dynamicType)"
}
let vehicle = Vehicle.foo()
let tractor = Tractor.foo()
print(typeName(vehicle)) // Vehicle
print(typeName(tractor)) // Tractor
Swift 5.1 now allow a forced cast to Self, as! Self
1> protocol P {
2. func id() -> Self
3. }
9> class D : P {
10. func id() -> Self {
11. return D()
12. }
13. }
error: repl.swift:11:16: error: cannot convert return expression of type 'D' to return type 'Self'
return D()
^~~
as! Self
9> class D : P {
10. func id() -> Self {
11. return D() as! Self
12. }
13. } //works
Following on Rob's suggestion, this could be made more generic with associated types. I've changed the example a bit to demonstrate the benefits of the approach.
protocol Copyable: NSCopying {
associatedtype Prototype
init(copy: Prototype)
init(deepCopy: Prototype)
}
class C : Copyable {
typealias Prototype = C // <-- requires adding this line to classes
required init(copy: Prototype) {
// Perform your copying here.
}
required init(deepCopy: Prototype) {
// Perform your deep copying here.
}
#objc func copyWithZone(zone: NSZone) -> AnyObject {
return Prototype(copy: self)
}
}
I had a similar problem and came up with something that may be useful so I though i'd share it for future reference because this is one of the first places I found when searching for a solution.
As stated above, the problem is the ambiguity of the return type for the copy() function. This can be illustrated very clearly by separating the copy() -> C and copy() -> P functions:
So, assuming you define the protocol and class as follows:
protocol P
{
func copy() -> P
}
class C:P
{
func doCopy() -> C { return C() }
func copy() -> C { return doCopy() }
func copy() -> P { return doCopy() }
}
This compiles and produces the expected results when the type of the return value is explicit. Any time the compiler has to decide what the return type should be (on its own), it will find the situation ambiguous and fail for all concrete classes that implement the P protocol.
For example:
var aC:C = C() // aC is of type C
var aP:P = aC // aP is of type P (contains an instance of C)
var bC:C // this to test assignment to a C type variable
var bP:P // " " " P " "
bC = aC.copy() // OK copy()->C is used
bP = aC.copy() // Ambiguous.
// compiler could use either functions
bP = (aC as P).copy() // but this resolves the ambiguity.
bC = aP.copy() // Fails, obvious type incompatibility
bP = aP.copy() // OK copy()->P is used
In conclusion, this would work in situations where you're either, not using the base class's copy() function or you always have explicit type context.
I found that using the same function name as the concrete class made for unwieldy code everywhere, so I ended up using a different name for the protocol's copy() function.
The end result is more like:
protocol P
{
func copyAsP() -> P
}
class C:P
{
func copy() -> C
{
// there usually is a lot more code around here...
return C()
}
func copyAsP() -> P { return copy() }
}
Of course my context and functions are completely different but in spirit of the question, I tried to stay as close to the example given as possible.
Just throwing my hat into the ring here. We needed a protocol that returned an optional of the type the protocol was applied on. We also wanted the override to explicitly return the type, not just Self.
The trick is rather than using 'Self' as the return type, you instead define an associated type which you set equal to Self, then use that associated type.
Here's the old way, using Self...
protocol Mappable{
static func map() -> Self?
}
// Generated from Fix-it
extension SomeSpecificClass : Mappable{
static func map() -> Self? {
...
}
}
Here's the new way using the associated type. Note the return type is explicit now, not 'Self'.
protocol Mappable{
associatedtype ExplicitSelf = Self
static func map() -> ExplicitSelf?
}
// Generated from Fix-it
extension SomeSpecificClass : Mappable{
static func map() -> SomeSpecificClass? {
...
}
}
To add to the answers with the associatedtype way, I suggest to move the creating of the instance to a default implementation of the protocol extension. In that way the conforming classes won't have to implement it, thus sparing us from code duplication:
protocol Initializable {
init()
}
protocol Creatable: Initializable {
associatedtype Object: Initializable = Self
static func newInstance() -> Object
}
extension Creatable {
static func newInstance() -> Object {
return Object()
}
}
class MyClass: Creatable {
required init() {}
}
class MyOtherClass: Creatable {
required init() {}
}
// Any class (struct, etc.) conforming to Creatable
// can create new instances without having to implement newInstance()
let instance1 = MyClass.newInstance()
let instance2 = MyOtherClass.newInstance()
Take this code:
protocol P: class {
static var hello: String { get }
}
class A: P {
class var hello: String {
return "Hello"
}
}
class B: A {
override static var hello: String {
return "Hello World"
}
}
class C: A {}
class D: C {
override static var hello: String {
return "Hello D"
}
}
func sayHello(elements: P.Type...) {
for p in elements {
print(p.hello)
}
}
func sayHelloAgain(elements: A.Type...) {
for p in elements {
print(p.hello)
}
}
func sayHelloThe3rd(elements: [A.Type]) {
for p in elements {
print(p.hello)
}
}
sayHello(A.self, B.self, C.self)
sayHelloAgain(A.self, B.self, C.self)
Compare it to this (taken from this presentation)
func register<T: UITableViewCell where T: ReusableView, T: NibLoadableView>(_: T.Type) { ... }
tableView.register(FoodTableViewCell)
Why do I have to use A.self in one case, but not in the other?
And also, don't need to use .self when calling with one argument.
sayHello(A)
sayHello(A, B) //doesn't compile
The .self is syntactic salt. It's not necessary from a technical perspective, but it exists to cause errors in code that's often a result of a typo, such as:
struct Foo { }
let foo = Foo
This code will give you a compiler error, telling you that either you need to complete the initializer/function/method call, or append .self if you meant to refer to the type.
In the latter example, the context deals exclusively with types and not values, so there's no chance of confusing one with the other, thus, .self isn't necessary.
Perhaps there's a way to modify the function declaration in your example so as to not require the .self, but I'm not aware of such a feature. I'd be interested to find out.
I came across a strange behaviour. The following code produces a compile error where I call bar() with the message: "Missing argument for parameter #1 call"
func bar() {
println("bar with no argument")
}
class ClassA {
func bar(varOfAnyType: String) {
println("bar with argument")
}
func foo() {
bar()
}
}
If I change bar() function's name then I get no errors:
func barNameChanged() {
println("bar with no argument")
}
class ClassA {
func bar(varOfAnyType: String) {
println("bar with argument")
}
func foo() {
barNameChanged()
}
}
What's the reason for the compiler not allowing to override the function outside the class?
Cheers, Daniel
At the moment, the Swift compiler cannot distinguish between a method and a global function with the same name, regardless of overloading.
The solution is to prefix the global function with its module name, e.g.,
func bar() { }
class ClassA {
func bar(anything: String) {}
func foo() { Module.bar() }
}