Selector for current method

Hi there!

in Swift 3, we now have #selector and #keyPath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

    var cannedOutput: [Selector: Any?] = [
        #selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
    ]

    dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
        let selector = #selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
        return cannedOutput[selector] as! [URL]
    }

}

Problem: I had to specify #selector twice.

I though I’d be able to use #function but:

#selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
#function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if #selector (without arguments) returned the current selector.

Or am I missing something?

R+

NSSelectorFromString(function) works just fine for this already.

···

On Nov 13, 2016, at 6:50 PM, Rudolf Adamkovič via swift-evolution <swift-evolution@swift.org> wrote:

Hi there!

in Swift 3, we now have selector and keypath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

   var cannedOutput: [Selector: Any?] = [
       selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
   ]

   dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
       let selector = selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
       return cannedOutput[selector] as! [URL]
   }

}

Problem: I had to specify selector twice.

I though I’d be able to use function but:

selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if selector (without arguments) returned the current selector.

Or am I missing something?

R+
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

NSSelectorFromString(function) works just fine for this already.

Hi Robert,

it doesn’t work.

NSSelectorFromString(function)
… returns "contentsOfDirectory(at:includingPropertiesForKeys:options:)"

selector(DirectoryListingMock.contentsOfDirectory(at:includingPropertiesForKeys:options:))
… returns "contentsOfDirectoryAt:includingPropertiesForKeys:options:error:"

In other words, "NSSelectorFromString(function)” returns Swift function name, not selector like _cmd or selector does.

R+

···

On 14 Nov 2016, at 01:01, Robert Widmann <devteam.codafi@gmail.com> wrote:

On Nov 13, 2016, at 6:50 PM, Rudolf Adamkovič via swift-evolution <swift-evolution@swift.org> wrote:

Hi there!

in Swift 3, we now have selector and keypath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

  var cannedOutput: [Selector: Any?] = [
      selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
  ]

  dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
      let selector = selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
      return cannedOutput[selector] as! [URL]
  }

}

Problem: I had to specify selector twice.

I though I’d be able to use function but:

selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if selector (without arguments) returned the current selector.

Or am I missing something?

R+
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

This doesn’t seem unreasonable, but I’m not sure if that makes it reasonable. :-) What’s your use case? The stripped-down code seems like it could use any unique key, including function.

Jordan

···

On Nov 13, 2016, at 15:50, Rudolf Adamkovič via swift-evolution <swift-evolution@swift.org> wrote:

Hi there!

in Swift 3, we now have selector and keypath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

   var cannedOutput: [Selector: Any?] = [
       selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
   ]

   dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
       let selector = selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
       return cannedOutput[selector] as! [URL]
   }

}

Problem: I had to specify selector twice.

I though I’d be able to use function but:

selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if selector (without arguments) returned the current selector.

Or am I missing something?

R+
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

One use case for bare `#selector` would be in patterns like NSTextViewDelegate’s -textView:doCommandBySelector:, where there are many call sites that need to pass the selector (and thus are open to copy-paste errors). I could imagine having a helper to make this less error prone and less verbose:

class SomeView : NSView {
  private func validate(selector: Selector = selector, action: (Void) -> Void) -> Bool {
    guard checkDelegate(selector) else {
      return
    }
    action()
  }

  @objc func action1(_ sender: AnyObject?) {
    validate {
        // do action
    }
  }

  ...

  @objc func actionN(_ sender: AnyObject?) {
    validate {
        // do action
    }
  }

}

-tim

···

On Nov 14, 2016, at 11:07 AM, Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

This doesn’t seem unreasonable, but I’m not sure if that makes it reasonable. :-) What’s your use case? The stripped-down code seems like it could use any unique key, including function.

Jordan

Hi Jordan,

The stripped-down code seems like it could use any unique key, including function.

That would work only if function could be used with an argument just like #selector:

class DirectoryListingStub: DirectoryListing {

   var cannedOutput: [Selector: Any?] = [
       function(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
   ]

   func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
       return cannedOutput[function] as! [URL]
   }

}

Obviously, this doesn’t work as function takes no arguments.

There's no way to get selector for the current method. And there’s no way to get function for arbitrary method.

R+

···

On 14 Nov 2016, at 20:07, Jordan Rose <jordan_rose@apple.com> wrote:

This doesn’t seem unreasonable, but I’m not sure if that makes it reasonable. :-) What’s your use case? The stripped-down code seems like it could use any unique key, including function.

Jordan

On Nov 13, 2016, at 15:50, Rudolf Adamkovič via swift-evolution <swift-evolution@swift.org> wrote:

Hi there!

in Swift 3, we now have selector and keypath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

  var cannedOutput: [Selector: Any?] = [
      selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
  ]

  dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
      let selector = selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
      return cannedOutput[selector] as! [URL]
  }

}

Problem: I had to specify selector twice.

I though I’d be able to use function but:

selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if selector (without arguments) returned the current selector.

Or am I missing something?

R+
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Sorry, I see that function doesn’t work as a drop-in replacement for selector. What I’m wondering is what you’re actually using this all for. It seems rare to have a dictionary keyed by the name of a function (but not its arguments) and rarer still to need to prepopulate that dictionary. The only use case I can think of is some generalized mock object, but even then I wonder how useful it is in practice.

(Per the original request, remember too that many Swift methods do not have selectors, since they are not exposed to Objective-C.)

Jordan

···

On Nov 15, 2016, at 03:47, Rudolf Adamkovič <salutis@me.com> wrote:

Hi Jordan,

The stripped-down code seems like it could use any unique key, including function.

That would work only if function could be used with an argument just like #selector:

class DirectoryListingStub: DirectoryListing {

  var cannedOutput: [Selector: Any?] = [
      function(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
  ]

  func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
      return cannedOutput[function] as! [URL]
  }

}

Obviously, this doesn’t work as function takes no arguments.

There's no way to get selector for the current method. And there’s no way to get function for arbitrary method.

R+

On 14 Nov 2016, at 20:07, Jordan Rose <jordan_rose@apple.com> wrote:

This doesn’t seem unreasonable, but I’m not sure if that makes it reasonable. :-) What’s your use case? The stripped-down code seems like it could use any unique key, including function.

Jordan

On Nov 13, 2016, at 15:50, Rudolf Adamkovič via swift-evolution <swift-evolution@swift.org> wrote:

Hi there!

in Swift 3, we now have selector and keypath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

var cannedOutput: [Selector: Any?] = [
     selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
]

dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
     let selector = selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
     return cannedOutput[selector] as! [URL]
}

}

Problem: I had to specify selector twice.

I though I’d be able to use function but:

selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if selector (without arguments) returned the current selector.

Or am I missing something?

R+
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

What I’m wondering is what you’re actually using this all for.

For example, when testing with Quick (popular testing framework), one can describe a function:

describe(“player.play()”) {
    ...
}

If function worked like selector, we could do:

describe(function(Player.play())) {
    ...
}

This would be safe and refactoring friendly.

P.S. I could do this with selector but that would require @objc/dynamic which is not ideal.

R+

···

On 15 Nov 2016, at 18:02, Jordan Rose <jordan_rose@apple.com> wrote:

Sorry, I see that function doesn’t work as a drop-in replacement for selector. What I’m wondering is what you’re actually using this all for. It seems rare to have a dictionary keyed by the name of a function (but not its arguments) and rarer still to need to prepopulate that dictionary. The only use case I can think of is some generalized mock object, but even then I wonder how useful it is in practice.

(Per the original request, remember too that many Swift methods do not have selectors, since they are not exposed to Objective-C.)

Jordan

On Nov 15, 2016, at 03:47, Rudolf Adamkovič <salutis@me.com <mailto:salutis@me.com>> wrote:

Hi Jordan,

The stripped-down code seems like it could use any unique key, including function.

That would work only if function could be used with an argument just like #selector:

class DirectoryListingStub: DirectoryListing {

  var cannedOutput: [Selector: Any?] = [
      function(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
  ]

  func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
      return cannedOutput[function] as! [URL]
  }

}

Obviously, this doesn’t work as function takes no arguments.

There's no way to get selector for the current method. And there’s no way to get function for arbitrary method.

R+

On 14 Nov 2016, at 20:07, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

This doesn’t seem unreasonable, but I’m not sure if that makes it reasonable. :-) What’s your use case? The stripped-down code seems like it could use any unique key, including function.

Jordan

On Nov 13, 2016, at 15:50, Rudolf Adamkovič via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi there!

in Swift 3, we now have selector and keypath yet there’s still no _cmd like we have in Objective-C.

Example:

class DirectoryListingStub: DirectoryListing {

var cannedOutput: [Selector: Any?] = [
     selector(contentsOfDirectory(at:includingPropertiesForKeys:options:)): nil
]

dynamic func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions) throws -> [URL] {
     let selector = selector(contentsOfDirectory(at:includingPropertiesForKeys:options:))
     return cannedOutput[selector] as! [URL]
}

}

Problem: I had to specify selector twice.

I though I’d be able to use function but:

selector = contentsOfDirectoryAt:includingPropertiesForKeys:options:error:
function = contentsOfDirectory(at:includingPropertiesForKeys:options:)

It’d be great if selector (without arguments) returned the current selector.

Or am I missing something?

R+
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution