Re: [swift-users] Reflection in Swift 3?

2016-11-15 Thread Rick Mann via swift-users

> On Nov 15, 2016, at 05:24 , Jeremy Pereira  
> wrote:
> 
> 
>> On 15 Nov 2016, at 10:33, Rick Mann  wrote:
>> 
>> Well, that's not really any different than a switch statement, in that it 
>> has to be maintained.
> 
> Yes, but I would argue that it is a good thing because you need to do some 
> validation before you instantiate the class anyway.
> 
> Furthermore, it gives you more flexibility in terms of initialisation because 
> the closure can invoke any initialiser regardless of parameters and can do 
> other processing as well.

Yeah, but that's not the flexibility I need. And with good 
reflection/introspection, I can do all the validation I need dynamically. In an 
ideal world, I could do something like this:

let pathRenderers = classesThatImplement(protocol: Renderer)
for pr in pathRenderers {
for ini in pr.initializers {
if ini.has(signature: (Path))
{
let renderer = pr.instantiate(aPath)
return
}
}
}

Obviously more complicated than this, but you get the idea.

> 
>> 
>>> On Nov 15, 2016, at 01:50 , Jeremy Pereira 
>>>  wrote:
>>> 
>>> Perhaps I’m missing something here, but why not use a map?
>>> 
>>>  let factoryMap = [ String : () -> SuperClassOrCommonProtocol ] = [ 
>>> “MySubClass" : { return MySubClass() }, … ]
>>> 
>>>  …
>>> 
>>>  guard let factoryMethod = factoryMap[theClassName] else { /* error */ }
>>>  return factoryMethod()
>>> 
>>> This is an approach I always ended up taking in Objective-C anyway, 
>>> because, if you don’t know what’s in the string, you need to validate it 
>>> (imagine if the user of your app finds out that they can cause you to 
>>> instantiate any arbitrary class) and if you do know what’s in the string, 
>>> why are you not creating the instance directly?
>>> 
>>> 
 On 14 Nov 2016, at 23:48, Rick Mann via swift-users 
  wrote:
 
 Thanks, David. That's interesting as a thought exercise, but doesn't 
 really get me away from having switch statements. I'll probably end up 
 just "slightly polluting" my classes by adding extension methods to create 
 the appropriate auxiliary classes. Sure wish Swift supported optional 
 methods without @objc (I guess it's not that big a deal to use @objc).
 
> On Nov 13, 2016, at 11:19 , David Sweeris  wrote:
> 
> 
>> On Nov 13, 2016, at 1:55 AM, Rick Mann  wrote:
>> 
>> 
>>> On Nov 12, 2016, at 22:47 , David Sweeris  wrote:
>>> 
>>> 
 On Nov 13, 2016, at 00:38, Rick Mann via swift-users 
  wrote:
 
 So, it seems there's still no way to do something like instantiate a 
 class given only its name (as a String)?
 
 In my situation, I have a number of subclasses (or protocol 
 implementations), which parallel some other class hierarchy. I need to 
 dynamically create one based on the name of another. I don't want the 
 latter classes to "know" anything about the former.
>>> 
>>> Not that I know of... If this is all your code, can you fake it by 
>>> switching over the type's name?
>> 
>> Yeah, it just happens in a few places, would be nice to write the code 
>> once and then just ensure classes exist. I know I could do it 
>> subclassing NSObject, but Swift really ought to have proper reflection.
> 
> Reflection is on the todo list (although I can’t recall if it’s in-scope 
> for Swift 4).
> 
> There’s also the possibility of putting the names of the classes you want 
> to instantiate into an enum. In fact, if all the classes in question have 
> a common superclass, you could this:
> class MyAwesomeSuperClass { required init() {} }
> class MyAwesomeSubClass : MyAwesomeSuperClass {}
> class Whatever : MyAwesomeSuperClass {}
> class Etc : Whatever {}
> enum ClassNames : String {
> //Unfortunately the value of each case has to be a literal, so
> //you can’t just say `case etc = "\(Etc.self)"`
> case myAwesomeSuperClass = "MyAwesomeSuperClass"
> case myAwesomeSubClass = "MyAwesomeSubClass"
> case whatever = "Whatever"
> case etc = "Etc"
> init(_ instance: MyAwesomeSuperClass) { self = ClassNames.init(rawValue: 
> "\(type(of: instance))")! }
> init(_ type: MyAwesomeSuperClass.Type) { self = ClassNames.init(rawValue: 
> "\(type)")! }
> var type: MyAwesomeSuperClass.Type {
> switch self {
> case .myAwesomeSuperClass:  return MyAwesomeSuperClass.self
> case .myAwesomeSubClass:return MyAwesomeSubClass.self
> case .whatever: return Whatever.self
> case .etc:  return Etc.self
> }
> }
> }
> var etc = Etc()
> var className = 

Re: [swift-users] Reflection in Swift 3?

2016-11-15 Thread Jeremy Pereira via swift-users

> On 15 Nov 2016, at 10:33, Rick Mann  wrote:
> 
> Well, that's not really any different than a switch statement, in that it has 
> to be maintained.

Yes, but I would argue that it is a good thing because you need to do some 
validation before you instantiate the class anyway.

Furthermore, it gives you more flexibility in terms of initialisation because 
the closure can invoke any initialiser regardless of parameters and can do 
other processing as well.

> 
>> On Nov 15, 2016, at 01:50 , Jeremy Pereira  
>> wrote:
>> 
>> Perhaps I’m missing something here, but why not use a map?
>> 
>>   let factoryMap = [ String : () -> SuperClassOrCommonProtocol ] = [ 
>> “MySubClass" : { return MySubClass() }, … ]
>> 
>>   …
>> 
>>   guard let factoryMethod = factoryMap[theClassName] else { /* error */ }
>>   return factoryMethod()
>> 
>> This is an approach I always ended up taking in Objective-C anyway, because, 
>> if you don’t know what’s in the string, you need to validate it (imagine if 
>> the user of your app finds out that they can cause you to instantiate any 
>> arbitrary class) and if you do know what’s in the string, why are you not 
>> creating the instance directly?
>> 
>> 
>>> On 14 Nov 2016, at 23:48, Rick Mann via swift-users  
>>> wrote:
>>> 
>>> Thanks, David. That's interesting as a thought exercise, but doesn't really 
>>> get me away from having switch statements. I'll probably end up just 
>>> "slightly polluting" my classes by adding extension methods to create the 
>>> appropriate auxiliary classes. Sure wish Swift supported optional methods 
>>> without @objc (I guess it's not that big a deal to use @objc).
>>> 
 On Nov 13, 2016, at 11:19 , David Sweeris  wrote:
 
 
> On Nov 13, 2016, at 1:55 AM, Rick Mann  wrote:
> 
> 
>> On Nov 12, 2016, at 22:47 , David Sweeris  wrote:
>> 
>> 
>>> On Nov 13, 2016, at 00:38, Rick Mann via swift-users 
>>>  wrote:
>>> 
>>> So, it seems there's still no way to do something like instantiate a 
>>> class given only its name (as a String)?
>>> 
>>> In my situation, I have a number of subclasses (or protocol 
>>> implementations), which parallel some other class hierarchy. I need to 
>>> dynamically create one based on the name of another. I don't want the 
>>> latter classes to "know" anything about the former.
>> 
>> Not that I know of... If this is all your code, can you fake it by 
>> switching over the type's name?
> 
> Yeah, it just happens in a few places, would be nice to write the code 
> once and then just ensure classes exist. I know I could do it subclassing 
> NSObject, but Swift really ought to have proper reflection.
 
 Reflection is on the todo list (although I can’t recall if it’s in-scope 
 for Swift 4).
 
 There’s also the possibility of putting the names of the classes you want 
 to instantiate into an enum. In fact, if all the classes in question have 
 a common superclass, you could this:
 class MyAwesomeSuperClass { required init() {} }
 class MyAwesomeSubClass : MyAwesomeSuperClass {}
 class Whatever : MyAwesomeSuperClass {}
 class Etc : Whatever {}
 enum ClassNames : String {
  //Unfortunately the value of each case has to be a literal, so
  //you can’t just say `case etc = "\(Etc.self)"`
  case myAwesomeSuperClass = "MyAwesomeSuperClass"
  case myAwesomeSubClass = "MyAwesomeSubClass"
  case whatever = "Whatever"
  case etc = "Etc"
  init(_ instance: MyAwesomeSuperClass) { self = ClassNames.init(rawValue: 
 "\(type(of: instance))")! }
  init(_ type: MyAwesomeSuperClass.Type) { self = ClassNames.init(rawValue: 
 "\(type)")! }
  var type: MyAwesomeSuperClass.Type {
  switch self {
  case .myAwesomeSuperClass:  return MyAwesomeSuperClass.self
  case .myAwesomeSubClass:return MyAwesomeSubClass.self
  case .whatever: return Whatever.self
  case .etc:  return Etc.self
  }
 }
 }
 var etc = Etc()
 var className = ClassNames(etc)
 var newEtc = className.type.init()
 
 The same trick works if all the types in question conform to the same 
 protocol, too:
 protocol MyAwesomeProtocol {
  init()
  func toIntMax() -> IntMax
 }
 extension Int : MyAwesomeProtocol {}
 struct Five : MyAwesomeProtocol { func toIntMax() -> IntMax { return 5 } }
 enum ProtocolNames : String {
  case five = "Five"
  case int = "Int"
  init(_ instance: MyAwesomeProtocol) { self = ProtocolNames.init(rawValue: 
 "\(type(of: instance))”)! }
  init(_ type: MyAwesomeProtocol.Type) { self = 
 ProtocolNames.init(rawValue: "\(type)")! }
  var type: 

Re: [swift-users] Reflection in Swift 3?

2016-11-14 Thread Rick Mann via swift-users
Thanks, David. That's interesting as a thought exercise, but doesn't really get 
me away from having switch statements. I'll probably end up just "slightly 
polluting" my classes by adding extension methods to create the appropriate 
auxiliary classes. Sure wish Swift supported optional methods without @objc (I 
guess it's not that big a deal to use @objc).

> On Nov 13, 2016, at 11:19 , David Sweeris  wrote:
> 
> 
>> On Nov 13, 2016, at 1:55 AM, Rick Mann  wrote:
>> 
>> 
>>> On Nov 12, 2016, at 22:47 , David Sweeris  wrote:
>>> 
>>> 
 On Nov 13, 2016, at 00:38, Rick Mann via swift-users 
  wrote:
 
 So, it seems there's still no way to do something like instantiate a class 
 given only its name (as a String)?
 
 In my situation, I have a number of subclasses (or protocol 
 implementations), which parallel some other class hierarchy. I need to 
 dynamically create one based on the name of another. I don't want the 
 latter classes to "know" anything about the former.
>>> 
>>> Not that I know of... If this is all your code, can you fake it by 
>>> switching over the type's name?
>> 
>> Yeah, it just happens in a few places, would be nice to write the code once 
>> and then just ensure classes exist. I know I could do it subclassing 
>> NSObject, but Swift really ought to have proper reflection.
> 
> Reflection is on the todo list (although I can’t recall if it’s in-scope for 
> Swift 4).
> 
> There’s also the possibility of putting the names of the classes you want to 
> instantiate into an enum. In fact, if all the classes in question have a 
> common superclass, you could this:
> class MyAwesomeSuperClass { required init() {} }
> class MyAwesomeSubClass : MyAwesomeSuperClass {}
> class Whatever : MyAwesomeSuperClass {}
> class Etc : Whatever {}
> enum ClassNames : String {
> //Unfortunately the value of each case has to be a literal, so
> //you can’t just say `case etc = "\(Etc.self)"`
> case myAwesomeSuperClass = "MyAwesomeSuperClass"
> case myAwesomeSubClass = "MyAwesomeSubClass"
> case whatever = "Whatever"
> case etc = "Etc"
> init(_ instance: MyAwesomeSuperClass) { self = ClassNames.init(rawValue: 
> "\(type(of: instance))")! }
> init(_ type: MyAwesomeSuperClass.Type) { self = ClassNames.init(rawValue: 
> "\(type)")! }
> var type: MyAwesomeSuperClass.Type {
> switch self {
> case .myAwesomeSuperClass:  return MyAwesomeSuperClass.self
> case .myAwesomeSubClass:return MyAwesomeSubClass.self
> case .whatever: return Whatever.self
> case .etc:  return Etc.self
> }
>}
> }
> var etc = Etc()
> var className = ClassNames(etc)
> var newEtc = className.type.init()
> 
> The same trick works if all the types in question conform to the same 
> protocol, too:
> protocol MyAwesomeProtocol {
> init()
> func toIntMax() -> IntMax
> }
> extension Int : MyAwesomeProtocol {}
> struct Five : MyAwesomeProtocol { func toIntMax() -> IntMax { return 5 } }
> enum ProtocolNames : String {
> case five = "Five"
> case int = "Int"
> init(_ instance: MyAwesomeProtocol) { self = ProtocolNames.init(rawValue: 
> "\(type(of: instance))”)! }
> init(_ type: MyAwesomeProtocol.Type) { self = 
> ProtocolNames.init(rawValue: "\(type)")! }
> var type: MyAwesomeProtocol.Type {
> switch self {
> case .five: return Five.self
> case .int:  return Int.self
> }
> }
> }
> var five = Five()
> var fiveName = ProtocolNames(five)
> var newFive = fiveName.type.init()
> 
> Either way, though, you’ll have to do something like if let nf = newFive as? 
> Int {…} if you want to use any functionality that isn’t explicitly in the 
> superclass or protocol.
> 
> It certainly involves some boilerplate code, but it also has the advantages 
> of validating the name before you try to use it and ensuring that any switch 
> statements can actually handle all the classes. 
> 
> - Dave Sweeris


-- 
Rick Mann
rm...@latencyzero.com


___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Reflection in Swift 3?

2016-11-13 Thread David Sweeris via swift-users

> On Nov 13, 2016, at 1:55 AM, Rick Mann  wrote:
> 
> 
>> On Nov 12, 2016, at 22:47 , David Sweeris  wrote:
>> 
>> 
>>> On Nov 13, 2016, at 00:38, Rick Mann via swift-users 
>>>  wrote:
>>> 
>>> So, it seems there's still no way to do something like instantiate a class 
>>> given only its name (as a String)?
>>> 
>>> In my situation, I have a number of subclasses (or protocol 
>>> implementations), which parallel some other class hierarchy. I need to 
>>> dynamically create one based on the name of another. I don't want the 
>>> latter classes to "know" anything about the former.
>> 
>> Not that I know of... If this is all your code, can you fake it by switching 
>> over the type's name?
> 
> Yeah, it just happens in a few places, would be nice to write the code once 
> and then just ensure classes exist. I know I could do it subclassing 
> NSObject, but Swift really ought to have proper reflection.

Reflection is on the todo list (although I can’t recall if it’s in-scope for 
Swift 4).

There’s also the possibility of putting the names of the classes you want to 
instantiate into an enum. In fact, if all the classes in question have a common 
superclass, you could this:
class MyAwesomeSuperClass { required init() {} }
class MyAwesomeSubClass : MyAwesomeSuperClass {}
class Whatever : MyAwesomeSuperClass {}
class Etc : Whatever {}
enum ClassNames : String {
//Unfortunately the value of each case has to be a literal, so
//you can’t just say `case etc = "\(Etc.self)"`
case myAwesomeSuperClass = "MyAwesomeSuperClass"
case myAwesomeSubClass = "MyAwesomeSubClass"
case whatever = "Whatever"
case etc = "Etc"
init(_ instance: MyAwesomeSuperClass) { self = ClassNames.init(rawValue: 
"\(type(of: instance))")! }
init(_ type: MyAwesomeSuperClass.Type) { self = ClassNames.init(rawValue: 
"\(type)")! }
var type: MyAwesomeSuperClass.Type {
switch self {
case .myAwesomeSuperClass:  return MyAwesomeSuperClass.self
case .myAwesomeSubClass:return MyAwesomeSubClass.self
case .whatever: return Whatever.self
case .etc:  return Etc.self
}
   }
}
var etc = Etc()
var className = ClassNames(etc)
var newEtc = className.type.init()

The same trick works if all the types in question conform to the same protocol, 
too:
protocol MyAwesomeProtocol {
init()
func toIntMax() -> IntMax
}
extension Int : MyAwesomeProtocol {}
struct Five : MyAwesomeProtocol { func toIntMax() -> IntMax { return 5 } }
enum ProtocolNames : String {
case five = "Five"
case int = "Int"
init(_ instance: MyAwesomeProtocol) { self = ProtocolNames.init(rawValue: 
"\(type(of: instance))”)! }
init(_ type: MyAwesomeProtocol.Type) { self = ProtocolNames.init(rawValue: 
"\(type)")! }
var type: MyAwesomeProtocol.Type {
switch self {
case .five: return Five.self
case .int:  return Int.self
}
}
}
var five = Five()
var fiveName = ProtocolNames(five)
var newFive = fiveName.type.init()

Either way, though, you’ll have to do something like if let nf = newFive as? 
Int {…} if you want to use any functionality that isn’t explicitly in the 
superclass or protocol.

It certainly involves some boilerplate code, but it also has the advantages of 
validating the name before you try to use it and ensuring that any switch 
statements can actually handle all the classes. 

- Dave Sweeris___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Reflection in Swift 3?

2016-11-12 Thread Rick Mann via swift-users

> On Nov 12, 2016, at 22:47 , David Sweeris  wrote:
> 
> 
>> On Nov 13, 2016, at 00:38, Rick Mann via swift-users  
>> wrote:
>> 
>> So, it seems there's still no way to do something like instantiate a class 
>> given only its name (as a String)?
>> 
>> In my situation, I have a number of subclasses (or protocol 
>> implementations), which parallel some other class hierarchy. I need to 
>> dynamically create one based on the name of another. I don't want the latter 
>> classes to "know" anything about the former.
> 
> Not that I know of... If this is all your code, can you fake it by switching 
> over the type's name?

Yeah, it just happens in a few places, would be nice to write the code once and 
then just ensure classes exist. I know I could do it subclassing NSObject, but 
Swift really ought to have proper reflection.


-- 
Rick Mann
rm...@latencyzero.com


___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Reflection in Swift 3?

2016-11-12 Thread David Sweeris via swift-users

> On Nov 13, 2016, at 00:38, Rick Mann via swift-users  
> wrote:
> 
> So, it seems there's still no way to do something like instantiate a class 
> given only its name (as a String)?
> 
> In my situation, I have a number of subclasses (or protocol implementations), 
> which parallel some other class hierarchy. I need to dynamically create one 
> based on the name of another. I don't want the latter classes to "know" 
> anything about the former.

Not that I know of... If this is all your code, can you fake it by switching 
over the type's name?

- Dave Sweeris 
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users