Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Doh004
Apr 22, 2007

Mmmmm Donuts...
Is it possible to have a protocol's default implementation in an extension work for selectors? For example, I'd like an extension to provide some gesture recognizers:

code:
protocol Draggable: class, UIGestureRecognizerDelegate {
    func didPress(pressGesture: UILongPressGestureRecognizer) -> Void
    func didPan(panGesture: UIPanGestureRecognizer) -> Void
}

extension Draggable where Self: UIView {
    func wasAddedToParentView() {
        let panGesture = UIPanGestureRecognizer(target: self, action: Selector("didPan:"))
        panGesture.delegate = self

        let pressGesture = UILongPressGestureRecognizer(target: self, action: Selector("didPress:"))
        pressGesture.minimumPressDuration = 0.001
        pressGesture.delegate = self
        
        self.addGestureRecognizer(panGesture)
        self.addGestureRecognizer(pressGesture)
    }

    func didPress(pressGesture: UILongPressGestureRecognizer) {
        // do pressing things
    }
    
    func didPan(panGesture: UIPanGestureRecognizer) {
        // do panning things
    }
}
Sadly, when I tap on the view, I get a "does not recognize selector" error. If I then add in the functions in my object that is of the Draggable prototype, there's no crash and it recognizes it (but I don't want that, I just want it handled in the extension). I believe this doesn't work because pure Swift classes don't handle respondsToSelector: and that's what would be used in the UIGestureRecognizer addTarget:action methods.

Adbot
ADBOT LOVES YOU

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
Maybe the protocol (and the methods in it too, perhaps) need to be marked @objc?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
It's an area of some debate, but at least some variants of it would probably be okay, and the current inability to do that is just an unnecessary restriction.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Flobbster posted:

Maybe the protocol (and the methods in it too, perhaps) need to be marked @objc?

I tried that but the compiler yells at you "Members of protocol extensions cannot be declared as @objc". :saddowns:

rjmccall posted:

It's an area of some debate, but at least some variants of it would probably be okay, and the current inability to do that is just an unnecessary restriction.

Oh okay, cool. Well here's a +1 to allowing that in a future release of Swift. I should be fine maybe making a lightweight base class that'll receive the selectors for the time being (or something to that effect).

Also really enjoying 2.0 so far, great job :)

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
The real solution is to replace methods that take selectors with methods that take functions. I was rather disappointed that iOS 9 didn't do that through more of UIKit.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Axiem posted:

The real solution is to replace methods that take selectors with methods that take functions. I was rather disappointed that iOS 9 didn't do that through more of UIKit.

Definitely.

I just hobbled together an extension on UIGestureRecognizer to do just this with some object association. Feels pretty dirty.

lord funk
Feb 16, 2004

Is it possible to write a generic function that returns a random normalized value and infers the type? This sounds like a good use for generics so I don't have to have Float, Double, CGFloat versions of the same function.

Something like:
func randomNormalized<T: FloatingPointType>() -> T

My attempts have all failed because I can't seem to initialize the resulting T.

jawbroken
Aug 13, 2007

messmate king
Sure. If you check the FloatingPointType protocol you will see it includes initialisers from all of the integer types, so you can do

code:
func one<T: FloatingPointType>() -> T {
  return T(1)
}

let i: Float = one() // 1.0
It sounds like you want to initialise from another floating point type though, so you would need a protocol that allows that

code:
protocol DoubleInitializable {
  init(_ value: Double)
}

extension Float:  DoubleInitializable { }
extension Double: DoubleInitializable { }

func one<T: protocol<FloatingPointType, DoubleInitializable>>() -> T {
  return T(1.0)
}
or similar. Maybe you only care about it being DoubleInitializable there, depends on your use case and taste.

lord funk
Feb 16, 2004

jawbroken posted:

Sure. If you check the FloatingPointType protocol you will see it includes initialisers from all of the integer types, so you can do
Thank you. Forgot that I could make my own initializer protocol! Works great.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer
Is there any plan for any sort of preprocessing steps in the future? I'm thinking up to even Scala's macros, where we could run arbitrary Swift on the code as a build step. It seems like it'd be nice to have to something like C#'s async/await transforms.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Doh004 posted:

Definitely.

I just hobbled together an extension on UIGestureRecognizer to do just this with some object association. Feels pretty dirty.

If anyone's curious, I put up a repo with my Draggable extension: https://github.com/BayPhillips/draggable-swift

emoji
Jun 4, 2004
I have a few questions. What is going on here? Why doesn't tuple unpacking work the way I expect?
code:
func sum1(x: Int, _ y: Int) -> Int {
    return x + y
}

func sum2(x: Int, y: Int) -> Int {
    return x + y
}

let a = (1, 1)
let b = (3, y: 4)
let c = (x: 5, y: 6)

sum1(a) // works as expected
sum1(b) // error: missing argument for parameter #2 in call ??
sum1(c) // error: missing argument for parameter #2 in call ??

sum2(a) // fails as expected
sum2(b) // works as expected
sum2(c) // error: missing argument for parameter 'y' in call ??
Also, will it be possible to have generic computed properties like so, or is it and I'm doing it wrong?
code:
struct MyPoint {
	var x, y, z, w: UInt8
	var position<T: FloatingPointType>: (T, T, T) {
		return (T(x), T(y), T(z))
	}
}
I can do this:
code:
struct MyPoint {
    var x,y,z,w: UInt8

    var positionConcrete: (Float, Float, Float) {
        return (x: Float(x), y: Float(y), z: Float(z))
    }
    
    func positionGeneric<T: FloatingPointType>() -> (x: T, y: T, z: T) {
        return (x: T(x), y: T(y), z: T(z))
    }
}

let myPoint = MyPoint(x: 1, y: 2, z: 3, w: 4)
code:
let e1: (Float, Float, Float) = myPoint.positionGeneric() // fine
let e2: (Double, Double, Double) = myPoint.positionGeneric() // fine
let e3: (CGFloat, CGFloat, CGFloat) = myPoint.positionGeneric() //fine

let f1 = float3(myPoint.positionConcrete) // fine
let f2 = float3(myPoint.positionGeneric() as (Float, Float, Float)) // fine
let f3 = float3(myPoint.positionGeneric()) // error: cannot invoke initializer for type 'float3' with an argument list of type '(x: _, y: _, z: _)
It also tells me for f3: note: overloads for 'float3' exist with these partially matching parameter lists: (Float), ([Float]), (SCNVector3)
Why is it not able to find a match between the parameter list and the protocol constraint and use that?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

emoji posted:

I have a few questions. What is going on here? Why doesn't tuple unpacking work the way I expect?
code:
func sum1(x: Int, _ y: Int) -> Int {
    return x + y
}

func sum2(x: Int, y: Int) -> Int {
    return x + y
}

let a = (1, 1)
let b = (3, y: 4)
let c = (x: 5, y: 6)

sum1(a) // works as expected
sum1(b) // error: missing argument for parameter #2 in call ??
sum1(c) // error: missing argument for parameter #2 in call ??

sum2(a) // fails as expected
sum2(b) // works as expected
sum2(c) // error: missing argument for parameter 'y' in call ??

The first function takes a tuple of type (Int,Int) because you've suppressed the label, so the y-labeled arguments don't match anything. The second takes a tuple of type (Int, y: Int), so the y-labeled argument matches now, but the x-labeled argument doesn't. In all cases, the diagnostics could be better.

emoji posted:

Also, will it be possible to have generic computed properties like so, or is it and I'm doing it wrong?

I don't think we actually want to add generic properties, no. Maybe someday.

emoji posted:

It also tells me for f3: note: overloads for 'float3' exist with these partially matching parameter lists: (Float), ([Float]), (SCNVector3)
Why is it not able to find a match between the parameter list and the protocol constraint and use that?

Not sure.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer
This is probably more for rjmccall directly, but is there a way to get lldb to know about C types you'd usually use in the ObjC world? Mostly I'm trying to fix Chisel to deal with being on a Swift frame in the debugger while trying to execute an ObjC expression. What I'm seeing is if you run "expr -l ObjC++ -- (NSInteger)1", it works when you're in an ObjC or ObjC+Swift Xcode target, but in a strictly-Swift one it fails out saying "use of undeclared identifier 'NSInteger'". Is there a way to get lldb to pull in the ObjC stuff at runtime?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I have no idea, sorry. We are doing infrastructural things that should lead to a much more complete debugging experience, and it should lead to types like NSInteger being reliably available; but I don't know what the schedule for that is expected to be.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
Is there a way yet to constrain a generic type parameter to be a subclass of or conform to another generic type parameter?

Let's say I want to pass in two type objects to a function, the second of which extends the first. If this were Java, I would just say something like:

code:
void <T> foo(Class<T> x, Class<? extends T> y)
but trying to say something similar in Swift gives me the error "Inheritance from non-protocol, non-class type T":
code:
func foo<T, U: T>(x: T.Type, y: U.Type)
which makes sense, of course, because T could be anything: a class, a struct, a protocol, an enum... and you can't inherit from some of those.

So is there any way to say "T must be a class" or "T must be a protocol"?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I don't have a compiler at hand, but I believe T : class will constrain it to be a class type. However, I'd be surprised if you could then use T as the "concrete" bound on a different parameter.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Alternatively, though, do you really need to type the second as U.Type? Class metatypes have subtyping that follows inheritance.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

rjmccall posted:

I don't have a compiler at hand, but I believe T : class will constrain it to be a class type. However, I'd be surprised if you could then use T as the "concrete" bound on a different parameter.

I already tried that hoping it would work since that's how you create a class-only protocol, but no such luck—the parser isn't remotely cool with it (Xcode 7.1/Swift 2.1):
code:
func foo<T: class, U>(x: T.Type, y: U.Type) {
  print("from \(x) to \(y)")
}

error: expected a type name or protocol composition restricting 'T'
func foo<T: class, U>(x: T.Type, _ y: U.Type) {
            ^
error: expected '(' in argument list of function declaration
func foo<T: class, U>(x: T.Type, _ y: U.Type) {
            ^
error: consecutive statements on a line must be separated by ';'
func foo<T: class, U>(x: T.Type, _ y: U.Type) {
...among other cascading syntax errors.

quote:

Alternatively, though, do you really need to type the second as U.Type? Class metatypes have subtyping that follows inheritance.

Assuming everything else worked like I'm intending, I'd have to type both as T.Type/U.Type or both as T/U, right? In my example above, if I wrote:

code:
func foo<T, U>(x: T.Type, y: U.Type) {...}
foo(Superclass.self, y: Subclass.self)
then T = Superclass and U = Subclass (as opposed to Superclass.Type and Subclass.Type) so I need the ".Type" to indicate that I want the argument to be the type and not an instance of the type, correct?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I just mean that Subclass.self : Superclass.Type.

It's silly that you can't write T : class as a constraint, but T : AnyObject will probably have the desired effect, although again it probably won't let you express what you want.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
Thanks. Writing T: AnyObject does the right restriction there but trying to do U: T gives me the same "inheritance from non-protocol, non-class type 'T'" error.

It occurs to me that I would want something more general for what I'm trying to do; instead of just classes, the ideal constraint would let me express "let T be any type for which there is some other type U that can conform to or inherit from T" (so T could be a protocol or a class), and then I could write "U: T" as a subsequent type argument and the compiler would be ok with that.

Between this and some tricky tuple-unpacking, I think I'm just trying to do some C++-style metaprogramming that Swift isn't able to handle (...yet?) :v:

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah, it sounds like you're looking for some sort of polymorphism over constraints that is probably waaay into undecidability territory.

But I suspect that the correct answer to "what are you actually trying to do" is much simpler than that.

lord funk
Feb 16, 2004

What does it mean for a class to support NSFastEnumeration?

code:
public class MDLMaterial : NSObject, MDLNamed, NSFastEnumeration {

...

    public subscript (idx: Int) -> MDLMaterialProperty? { get }
    public subscript (name: String) -> MDLMaterialProperty? { get }
    public var count: Int { get }
}
I'm getting this when I try to do it:

Only registered members can see post attachments!

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Implementing NSFastEnumeration only lets you iterate it from objc. To make it enumerable in swift you have to implement SequenceType.

lord funk
Feb 16, 2004

Plorkyeran posted:

Implementing NSFastEnumeration only lets you iterate it from objc. To make it enumerable in swift you have to implement SequenceType.

Check, thanks.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

lord funk posted:

What does it mean for a class to support NSFastEnumeration?

It means it conforms to the Objective-C NSFastEnumeration protocol, which is not at all new in Swift.

lord funk posted:

I'm getting this when I try to do it:



The Swift for..in syntax requires a conformance to the Swift SequenceType protocol, not NSFastEnumeration. There's a NSFastGenerator that makes it super-easy to conform to SequenceType if you have a value that conforms to NSFastEnumeration, but it sounds like you really want to go the other way: you just want your class to conform to SequenceType.

Doh004
Apr 22, 2007

Mmmmm Donuts...
So this is a thing: http://perfect.org/

"web brains"

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
Everyone's beating me to the Swift-on-the-backend bandwagon :( cuz I have a day job and a new baby and poo poo. (https://github.com/allevato/SwiftCGI, still just tinkering, ignore the jacked up Xcode project structure I have to deal with unit tests right now)

Browsing through the Perfect source code, it's pretty disappointing though. Looks like everything's a drat class—they're just writing code but not taking full advantage of the unique design features of the language. But at least they've got a pretty web page for it!

jabro
Mar 25, 2003

July Mock Draft 2014

1st PLACE
RUNNER-UP
got the knowshon


Flobbster posted:

Everyone's beating me to the Swift-on-the-backend bandwagon :( cuz I have a day job and a new baby and poo poo. (https://github.com/allevato/SwiftCGI, still just tinkering, ignore the jacked up Xcode project structure I have to deal with unit tests right now)

Browsing through the Perfect source code, it's pretty disappointing though. Looks like everything's a drat class—they're just writing code but not taking full advantage of the unique design features of the language. But at least they've got a pretty web page for it!

So it's not perfect? :smug:

Toady
Jan 12, 2009

I'm migrating classes in a large Objective-C project to Swift. I've found that if you expose a Swift class using a custom name via @objc, the Swift class can no longer see methods in Objective-C classes that reference that name.

Example:

code:
// TestFoo.h

@import Foundation;
@class TestBar;

@interface TestFoo : NSObject

@property (weak) TestBar *bar;

- (instancetype)initWithBar:(TestBar *)bar;

@end
code:
// TestFoo.m

#import "TestFoo.h"
#import "Test-Swift.h"

@implementation TestFoo

- (instancetype)initWithBar:(TestBar *)bar {
    self = [super init];
    if (self) {
        _bar = bar;
    }
    return self;
}
@end
code:
// Bar.swift

import Foundation

@objc(TestBar)
class Bar: NSObject {

    override init() {
        let foo = TestFoo(bar: self) // Error: Extra argument 'bar' in call
    }
}
Is there a solution for this?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Oh, interesting. I suspect there's just a missing feature there: the type is purely forward-declared in ObjC, and we normally can't import those into Swift because we don't want to introduce the concept of an incomplete type into the language, but here we ought to be able to match it up with a Swift declaration. The workaround, unfortunately, is probably just to make the ObjC declaration less type-safe.

Our usual recommendation right now is to convert from the leaves in. Of course, that's not really optimal for anyone because it's the core classes that are more interesting to Swift-ify.

Toady
Jan 12, 2009

I filed rdar://23666040 with a sample project containing the code posted here.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Thanks!

Doctor w-rw-rw-
Jun 24, 2008
Not sure if this was covered, but when Swift is open-sourced, a) will its Objective-C bridging be intact? and b) does this mean there's a possibility that in addition to the Swift runtime, release of a more liberally-licensed Objective-C runtime (i.e. NCSA, instead of APSL) is possible in addition?

(because seriously, GNUstep, Cocotron, and WinObjC? :rolleyes:)

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I really can't answer any of that, sorry.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

"Apple engineer doesn't deny plans to release new runtime!"

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
Speaking of, when is Swift going to be open-sourced, again? I could have sworn it was sometime soon.

Doctor w-rw-rw-
Jun 24, 2008

Axiem posted:

Speaking of, when is Swift going to be open-sourced, again? I could have sworn it was sometime soon.

According to the swift subreddit still on track to EOY 2015

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Official announcement is up, although the linked repos are still private. In addition to the obvious things it includes Foundation, XCTest, and a package manager.

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008
#calledit (sorta?)

  • Locked thread