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
Doctor w-rw-rw-
Jun 24, 2008
Neat. How long has this been under development?

Details on how generics work?

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008
Swift code:
// Playground - noun: a place where people can play

import Cocoa


func foo(inout x:Array<String>) -> Array<String> {
    x[0] = "qwer"
    return x
}

foo(["asdf", "1234"])
This crashes my Xcode. Known problem? Anyone else able to reproduce?

Doctor w-rw-rw-
Jun 24, 2008

WORLDS BEST BABY posted:

Same. While we're on the topic of playground bugs… are you supposed to be able to import UIKit into playgrounds? I've tried 'import UIKit' in all the configurations I could think of, including in an iOS project — but every time I just get "No such module 'UIKit'".

Playgrounds, for now, seem to be OS X only, without the simulator environment, so if that's intended it doesn't seem to be supported, currently.

Doctor w-rw-rw-
Jun 24, 2008
Swift code:
class A<T> {
    var B : T?

    init() {
    }
}
results in:
code:
error: unimplemented IR generation feature non-fixed class layout
    var B : T?
        ^
LLVM ERROR: unimplemented IRGen feature! non-fixed class layout
This is going to be supported later, right?

Doctor w-rw-rw-
Jun 24, 2008

WORLDS BEST BABY posted:

Thanks, that seems to be it.

Nevermind. I think that Xcode might have a right-sidebar option for iOS playgrounds.

Doctor w-rw-rw-
Jun 24, 2008
After lunch, I asked about reflection/proxies at the Swift lab (Axiem was interested and I was curious), and it didn't sound like there's much of a story for it in Swift yet. I suggested that rather than full-blown NSProxy support, something akin to Java's Proxy class might be worthwhile. Rather than proxying entire classes, dynamically instantiating an object that satisfies one or more interfaces might help keep Swift in a type-safer world than ObjC (and keep ARC working as expected), while also allowing things such as mocking.

(tl;dr: the Proxy class creates an object that delegates to an associated invocation handler class, which has a single function that gets called with the invocation's signature, etc. and handles it completely.)

They suggested filing a radar with a concrete suggestion such as the above. (Axiem, get on it)

Doctor w-rw-rw- fucked around with this message at 00:50 on Jun 5, 2014

Doctor w-rw-rw-
Jun 24, 2008
I cannot for the life of me figure out the right incantations to map the ObjC block params to the swift closure 'in' thingies:

Objective-C code:
@property(copy) void (^readabilityHandler)( NSFileHandle *)
Swift code:
let fileHandle = NSFileHandle(fileDescriptor: STDIN_FILENO)
fileHandle.readabilityHandler() {
}
Help?

Doctor w-rw-rw-
Jun 24, 2008

Plorkyeran posted:

I don't get why you're trying to call readabilityHandler with a closure. Do you mean
code:
fileHandle.readabilityHandler = { fh in ... }
?

Yes. I am dumb.

Doctor w-rw-rw-
Jun 24, 2008

quote:


Summary:
Swift is described as "Objective-C without the C". Objective-C was C + Smalltalk, so subtracting C yields Smalltalk.

Trying to map Objective-C keyword syntax to function-call / dot syntax brings significant complexity to the language without commensurate benefits. The section of the language spec. describing external vs. internal parameter names is larger than the entire Smalltalk language spec.

"Modern Syntax" was tried before, and it was overwhelmingly rejected by the developer community. Developers are accustomed to Objective-C message syntax (which is Smalltalk syntax), and the APIs don't have to be mapped, so there is less effort.

Steps to Reproduce:
Try to use reasonable syntax in Swift.
Try to comprehend the language specification.


Expected Results:
Syntax is easy to use + understand.

Actual Results:
Struggle with "where does the first parameter name go", "how do these things map" etc.
http://openradar.appspot.com/17180612

Why yes that is definitely a constructive and useful suggestion for Swift :shepface:

Doctor w-rw-rw-
Jun 24, 2008
Did you annotate the properties as NSManaged?

Doctor w-rw-rw-
Jun 24, 2008

Dessert Rose posted:

Yes. Also it apparently only works if I actually specify the name of the class. @objc isn't sufficient.

I'm not sure it actually works, though, because when I try to assign to an instance variable inside the class, it crashes.

I'm about to give up on converting my model to Swift for now and just try my luck at the controller layer.

You've posted no example code, so we can only spitball and hope we don't run into the same issue. If you could please share?

Doctor w-rw-rw-
Jun 24, 2008

eschaton posted:

Core Data really shouldn't be throwing an exception for anything that isn't programmer error; if it is, report it as a bug and send me the bug number for followup if you can.

If programmer error will happen, then it follows that exceptions will happen. I think it was implicit in his statement that if you're using Core Data, you're probably going to misuse it at some point and trigger an exception.

Doctor w-rw-rw-
Jun 24, 2008

Moogs posted:

Really, really new to programming (some HTML, JavaScript, CSS, but no real languages) guy here, jumping headfirst into Swift. Surely this is a stupid question, but I'm running the below code from Chapter 1 of the book in a playground (which is a neat thing!) -- why does largeKind need to be optional to not have the console throw errors?

code:
let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
interestingNumbers["Prime"]

var largest = 0
var largeKind: String?
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
            largeKind = kind
        }
    }
}
largest
largeKind


Because there's no initial value, and String isn't nullable.

Doctor w-rw-rw-
Jun 24, 2008

Psst: your submodule isn't specified!

Doctor w-rw-rw-
Jun 24, 2008

Ender.uNF posted:

Added ThreadLocalSlot<T> to support thread-local storage. Tests seem to be OK but don't rely on it for production code :v:

Thread-locals are bad on modern iOS/OS X platforms in any case, IMO. With increasing use of GCD queues, and no guarantee that a queue will schedule on a consistent thread, thread-local storage isn't that useful. IMO, a wrapper for dispatch_queue_set_specific would be more useful instead.

Also, if you don't mind the Objective-C baggage, you can just use +[NSThread threadDictionary] for thread-locals (not queue-locals), anyhow. Probably not an option if you're not dealing with non-NSObject subclasses.

Ender.uNF posted:

Next priorities for heavy-lifting: decent GCD abstraction and/or futures, then apply that to sequences to give seq.parallel() which will yield a sequence that automagically does its work in parallel on background queues. For light weight, some of the easier methods just need to be filled in (possibly using existing Swift library methods).

Re: parallel collection enumeration - perhaps a wrapper around a dispatch_apply onto a concurrent queue would do nicely.

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

This is actually already in the works, although I'm not sure how we're going to spell the property yet. (Other than definitely not using C# casing.)

I'm a fan of Guava's Optional's .isPresent(), or alternatively .present() for brevity if that is desired.

Doctor w-rw-rw-
Jun 24, 2008

fleshweasel posted:

Question about conventions: what do people tend to call a class designed to deserialize objects from a JSON API into strongly typed objects? Do people say "service adaptor" in the iOS world? Sorry if this is a dumb question.

I'd probably call it an unmarshaller or deserializer.

Doctor w-rw-rw-
Jun 24, 2008
Apologies if this has already been covered, but the docs appear incorrect:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html

Using Swift with Cocoa and Objective-C, Working with Cocoa Data Types posted:

Swift bridges NSUInteger and NSInteger to Int. Both of these types come over as Int in Foundation APIs. Int is used for consistency whenever possible in Swift, but the UInt type is available if you require an unsigned integer type.

How do I bridge the NSUInteger as Int? I built something which is interface-compatible with UITabBarController in Objective-C, but the selectedIndex method is translated as UInt, not Int.

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

There's an initializer on Int that should do it, I don't remember the name.

Not sure I understand. Is the suggested solution to pass in Int(foo) for all Swift calls to that method? Is there any Objective-C I can write (i.e. add an attribute or something) that will cause the NSUInteger parameter in the Objective-C method signature to resolve as an Int in the Swift method signature, as is the case for the tab bar controller?

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

Oh, I see. Can you not just change the parameter to NSInteger? ObjC isn't too picky about mismatches there.

I believe the rule we're applying is that (1) we consider our own headers to be too inconsistent about it and so always import as Int but (2) want to honor your code's choices, in part because user code uses such types in a much broader variety of ways than system headers do.

I want to be consistent with that inconsistency, because I'm mimicking another class's interface. That, and NSUInteger makes semantic sense where NSInteger does not. I'm happy to annotate/attribute my Objective-C code in whatever way I need to emulate it, but I'd appreciate the option.

Doctor w-rw-rw-
Jun 24, 2008

fleshweasel posted:

It's really more like a 1-time crunch job that takes 6 or so seconds on an iPhone 4. It is data that I need to perform really basic stuff (it's information about bus stops and routes being shown on a map). The data is in a lovely form for what I need so I am doing a fair amount of transformation.
GVFS is actually a pretty decent and easy to read format (having written a parser for it before). And if you're not working with GFVS...start? Many transit agencies offer it.

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

My cold, performance-optimizing heart doesn't want me to tell you this, but I am fairly certain that end-users can call reflect.

Serializable in Java is the worst, though. Combining reflection and saving objects to cold storage is pitfall city. IMO Swift-native NSCoding-like serialization would be ideal, not unlike Parcelable on Android, one of their good ideas.

Doctor w-rw-rw-
Jun 24, 2008
Okay, finally diving into Swift, and using an API familiar to me to do so. Dumb question time:

Swift code:
public protocol JSONParseable {
    init?(dictionary: [String: AnyObject])
}

public enum Kind : String {
    case Link = "Link"
    case Listing = "Listing"
    // ...
}

public struct Wrapper<T: JSONParseable> {
    let data: T?
    let kind : Kind?

    init?(dictionary: [String: AnyObject]) {
        guard let kindStr = dictionary["kind"] as? String else {
            return nil
        }

        // Is this right?
        kind = Kind(rawValue: kindStr)
        if kind == nil {
            return nil
        }

        guard let dataDict = dictionary["kind"] as? Dictionary<String, AnyObject> else {
            return nil
        }
        // Want to check T's type based on value of kind variable before attempting to parse. How to do this?
        data = T(dictionary: dataDict)
    }
}

public struct Link : JSONParseable {
    // ...
}
The wrapper initializer looks kind of messy.

Basically, the API returns JSON objects that envelop the data object and the data's kind (only a small handful, and known ahead of time), and I want the initializer for a Wrapper<Link> to fail if kind is not .Link, and Wrapper<Listing> to fail if kind is not .Listing, and so on. How do I need to change my approach / code to accomplish this?

Doctor w-rw-rw-
Jun 24, 2008
Any chance that we can get swift code formatting support (a la clang-format)? I like being sloppy with my spaces, and lament its loss.

Doctor w-rw-rw-
Jun 24, 2008

pokeyman posted:

In the meantime, there's SwiftLint, which doesn't do quite what you want but might give you some ideas if you get antsy.

Neat, I'll take a look soon. Currently investigating how feasible it is to adapt ComponentKit to Swift.

Definitely enjoying Swift 2.0 quite a bit after having gone down the C++ rabbit hole for a couple of months. Thanks rjmccall + eschaton!

Doctor w-rw-rw-
Jun 24, 2008
Am I missing something here?

Swift code:
struct Foo {
  let min : CGSize
  let max : CGSize

  // ...

  func clamp(size : CGSize) -> CGSize {
    let clampedWidth = max(min.width, min(max.width, size.width))
    // ...
  }
}
pre:
Cannot invoke 'max' with an argument list of type '(CGFloat, CGFloat)'
EDIT: Duh, name collision.
EDIT 2: I didn't want to rename the variables, so I fixed it by using Swift.min and Swift.max to refer to the global functions. Sweet.

Doctor w-rw-rw- fucked around with this message at 00:03 on Jun 18, 2015

Doctor w-rw-rw-
Jun 24, 2008

fleshweasel posted:

If nothing else I would like to see the API improved. NSRegularExpression seems a little bit clunky to me.

Improved how? I don't expect NSRegularExpression to have all that much flexibility, since NSDataDetector derives from it and afaik it's used in a ton of text code.

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

(snip)
right now async is kindof a callback-hell situation, and it really needs a more holistic solution.

rjmccall posted:

Yes. It's just a question of API design, i.e. whether you're willing to split the future type in two. Or you could have a future that produces a Result<T>, or whatever we end up calling it.

IMO Promise or Future style APIs are easy to abuse really, really badly. In one of my previous projects, a coworker wrote chains of promises with multiple branches which statefully changed a view controller (for example, showing/hiding the loading UI). It was a huge mess, and naturally, everything was crashy and hard to reason about. My takeaway was that without one of: a very strong convention of purity (mutating only locally within the code block), an in-language facility to help enforce purity, or a great deal of discipline, Futures and Promises seem to have a high risk of codebase devastation.

I also think that they tend to be a poor fit for implementing frequent or complex UI mutations. I wrote a channel/pipeline framework very (very) loosely resembling Netty's and an application on top of it, and came away from it feeling that overall, it's just really hard to beat just writing code sequentially. Being able to do so and also punt control to the background for long-running tasks and pick up where you left off would be really good.

That said, pausing the main thread and resuming it isn't exactly an option since UIKit requires the main thread to be continually running and minimally blocked for decent performance.

tl;dr: What would adding a async/await abstraction to the language would look like? Would it have a clearer story for exception handling? I don't pretend to know how much of a pain in the rear end that would be to implement. Maybe some way to make a continuation passing style not look awkward as hell instead?

Doctor w-rw-rw-
Jun 24, 2008
IMO, a literal for raw strings (like with Python) that uses different escaping rules would be preferable to integrated regex functionality.

Doctor w-rw-rw-
Jun 24, 2008
NS*WindowLevel constants don't seem to be imported into Swift.

Is this an appropriate workaround?

Swift code:
window.level = Int(CGWindowLevelForKey(CGWindowLevelKey.FloatingWindowLevelKey))
(CGWindowLevelForKey returns an Int32; window.level expects an Int)

EDIT: reported as rdar://21640539

Doctor w-rw-rw- fucked around with this message at 22:46 on Jul 1, 2015

Doctor w-rw-rw-
Jun 24, 2008
Possibly dumb question:

code:
// Obviously incomplete implementation
extension CollectionType where Generator.Element: Equatable {
    func delta(otherSequence: Self) -> Delta {
        for (otherIndex, otherItem) in otherSequence.enumerate() {
            let foo = self[otherIndex] // Errors with: "Cannot subscript a value of type 'Self' with an index of type 'Int'"
        }
        return Delta()
    }
}
What am I doing wrong here? Why can't I subscript lowercase-s 'self' when CollectionType's protocol is explicitly extended with "subscript (position: Self.Index) -> Self.Generator.Element { get }"? Index(otherIndex) also doesn't work.

Doctor w-rw-rw-
Jun 24, 2008
Well, this errors with: Type 'Index' constrained to non-protocol type 'Int'

code:
extension CollectionType where Index : Int, Generator.Element: Equatable {
    func delta(otherSequence: Self) -> Delta {
        for (otherIndex, otherItem) in otherSequence.enumerate() {
            let foo = self[otherIndex]
        }

        return Delta()
    }
}

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

Maybe you should just extend Array unless you have a need to be more generic?
Nope, don't need to be more generic. I was just trying to learn what the most appropriate extension point was. My reasoning for trying this first before going for the "boring" solution was that I figured that if there's ever an ordered set, it probably wouldn't subclass Array, so I should check my mileage on the more generic solutions first.

Thanks!

Doctor w-rw-rw-
Jun 24, 2008
Why does this succeed:

code:
extension Array {
    func delta<T: Equatable>(otherSequence: [T]) -> Delta {
        var unchangedIndices : [Int] = []

        for (otherIndex, otherItem) in otherSequence.enumerate() {
            let item = self[otherIndex] as! T
            if (item == otherItem) {
                unchangedIndices.append(otherIndex)
            }
        }

        // ...

        return Delta(unchangedIndices: unchangedIndices)
    }
}
and this fail?
code:
        // ... same

        for (otherIndex, otherItem) in otherSequence.enumerate() {
            let item = self[otherIndex]
            if (item == otherItem) {
                unchangedIndices.append(otherIndex)
            }
        }

        // ... same
Xcode already tells me item is of type T, but adding as! T prevents "Could not find an overload for '==' that accepts the supplied arguments".

EDIT: I think I'm dumb and need to use Element, not T.
EDIT 2: Nope. "'T' is not convertible to 'Element'" for "let item : Element = self[otherIndex]"
EDIT 3: Okay, using 'T' as a name is foolish, because it collides. When you're being told "'T' is not convertible to 'T'" best to use a different parameter name.
EDIT 4: All I really want is to define an operation (for calculating array diffs) on an Array where the elements are equatable. What the hell am I doing wrong?! :(

Doctor w-rw-rw- fucked around with this message at 18:23 on Jul 2, 2015

Doctor w-rw-rw-
Jun 24, 2008

Flobbster posted:

That'll teach me to fall behind on my betas :)

Same. I was trying stuff, not realizing I was on an old Xcode 7.0 beta.

Doctor w-rw-rw-
Jun 24, 2008


Both in the project, and even in a barebones playground (rdar://21673413). Huh.

(Yes, I've changed Element to T, and it's fine.)

Doctor w-rw-rw-
Jun 24, 2008
New Xcode beta. Thanks for the fixes!

Doctor w-rw-rw-
Jun 24, 2008

toiletbrush posted:

I'm really enjoying Swift, I still love c# but I'm finding myself wishing I could do swift-thing in C# a lot more than the other way round, which I'm kinda suprised about.

The only thing that I'm still not comfortable with is extensions and generics, using typealiases in code like this:

code:
extension SequenceType where Generator.Element == Int {
    var sum: Int {
        return reduce(0) { $0 + $1 }
    }
}
It makes sense, but seems a bit a odd in the sense that it feels like I'm peering into the class I'm extending a bit too much.

Seconded. I'm finding the combination of classes, protocols, and generics pretty confusing. Nearly all of my difficulties in the past two to three weeks of learning swift have been with debugging generics and protocols. It kind of feels like two different generics systems, and the occasional compiler crashes when dealing with them don't help either (I file it when I can reliably reproduce outside of my project).

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

I'm not hiding anything big, but I'm not annoyed, either. The right way to address that particular problem is definitely with variadic generics, but as you say, we don't have that right now, and it's probably a ways out. Honestly, the rate of new language features is probably going to drop to nearly zero for a while, because we need to focus on solving some hard implementation problems that I'm not proud to say we've been putting off. That will let us lift some unnecessary language restrictions, especially around generics, but mostly it should result in a faster and more stable compiler, and possibly faster code.

Also, open-sourcing is going to take a lot of work; it is sadly not as easy as just pushing our current repository to github.

Honestly, fewer crashes and generics with fewer surprises are on the top of my list of desired improvements to Swift anyways, so that's wonderful news as far as I'm concerned! :)

Thanks for your continued work on Swift.

Adbot
ADBOT LOVES YOU

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:)

  • Locked thread