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
rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Flobbster posted:

I was excited yesterday to find a situation where a particular combination of property declarations in a harmless looking generic struct compiled fine, but deadlocked at runtime when I tried initializing the struct (rdar://21664816) :v:

code:

public struct Foo<T> {
  public var thing1: T?
  public var thing2: (Foo -> Void)?
}

let foo = Foo<String>(); // nope nope nope

Yeah, this one is kindof embarrassing. When struct layout is at all dynamic, the dynamic struct layout code thinks it needs real type metadata for all the members, even when (like a function type) the member is actually fixed-layout.

Flobbster posted:

Will we one day be able to add stored properties to extensions, pretty please? If this was Objective-C I would just use associated objects, but I live in a Swift-only structful world whenever possible. Since I've been writing these things where certain structs have additional methods based on their associated types, there are some cases where it would be nice for them to have their own data too.

Storage and memory layout requirements aside, I guess one big blocker would be that initializers on the main struct wouldn't be able to initialize properties in an extension, so non-optional things would be broken.

I think for structs this is just a bad idea. We could consider allowing them within the module, or at least the file, that defines the struct, but that still poses a lot of nasty design problems — and that goes especially for conditional extensions. Stored properties are part of what defines the value of the struct, there really should be one place that knows everything that goes into them.

Also, if structs are arbitrarily dynamically extensible, I don't know how to implement them efficiently anymore.

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!"
Makes sense—I figured there were plenty of good reasons not to allow that. Maybe I should just suck it up and make them different structs...

Meanwhile, as much as I love the way Swift deals with the strings/characters/code points relationships (only language I've used that gets it even remotely right), I was doing some text processing and trying to deal with optional carriage returns and ended up spinning my wheels way longer than I should have because of this:

code:
let s = "ab\r\nc"
Array(s.characters)                    // ["a", "b", "\r\n", "c"]
s[advance(s.startIndex, 2)]            // "\r\n"
Definitely wasn't expecting those to be coalesced! That being said, it makes me code a lot cleaner because I don't have to special case \r followed by \n :)

Doh004
Apr 22, 2007

Mmmmm Donuts...
Playing with Swift 2 and I need to upgrade some code. Why can't I add @availability to stored properties?

code:
@available(iOS 8, *)
private var alertController: UIAlertController!

quote:

Stored properties cannot be marked potentially unavailable with 'introduced='

Thanks!

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Doh004 posted:

Playing with Swift 2 and I need to upgrade some code. Why can't I add @availability to stored properties?

code:
@available(iOS 8, *)
private var alertController: UIAlertController!
Thanks!

Not sure, but it probably has something to do with the storage actually needing to exist and be initialized independent of the runtime OS version. I mean, it's not that these are unsolvable problems, but it's something that hasn't been done.

Doh004
Apr 22, 2007

Mmmmm Donuts...

rjmccall posted:

Not sure, but it probably has something to do with the storage actually needing to exist and be initialized independent of the runtime OS version. I mean, it's not that these are unsolvable problems, but it's something that hasn't been done.

Okay! Just wanted to ask as it is something that I'd really like to be able to do. I have a wrapper that is a compatible UIAlertController for iOS 7. I can't state that the entire class is only available to iOS 8 (therefore defeating the purpose) so I'm kinda unsure of how to proceed with Swift 2. Looks like I might need to refactor it out to a separate subclass?

It's just confusing, because XCode offers this solution for the UIAlertControllerStyle:


It looks like you should be able to do it.

Doh004 fucked around with this message at 15:10 on Jul 8, 2015

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
If we're offering an illegal fix-it, that's always a bug.

Doh004
Apr 22, 2007

Mmmmm Donuts...

rjmccall posted:

If we're offering an illegal fix-it, that's always a bug.

Filed a bug on radar 21726433 :)

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

Kallikrates
Jul 7, 2002
Pro Lurker
We made a thing: https://itunes.apple.com/us/app/the-washington-post/id938922398?mt=8

Articles and their Ingestion are Obj-c (new dev there is swift)
Everything else is swift.
It's very much a 1.0, hopefully 1.0.1 sails through review.

lord funk
Feb 16, 2004

Will enum values ever autocomplete in the shorthand form? I've been hoping for this since the syntax was first shown.

I want

code:
let button = UIButton(type: .cu
to autocomplete to

code:
let button = UIButton(type: .Custom

Kallikrates
Jul 7, 2002
Pro Lurker
I think something might be wrong with your module cache or build target, those things have always auto completed for me.

dizzywhip
Dec 23, 2005

I've never seen enum values autocomplete without prefixing them with the type name.

Kallikrates
Jul 7, 2002
Pro Lurker
methods typed func fooable(foo:FooType) have always auto completed for me where FooType is an enum. I have seen often when a dependent build target(Test) not building or not mirroring all the same build sources, can cause weird havoc on auto completion.

its HIM
Oct 22, 2013
I have yet to see an enum autocomplete either, and that probably the biggest headache left for me in Swift. I'm constantly having to look the values up manually. Xcode's autocomplete is pretty terrible in general when using Swift, but I have no doubt that'll improve with time. The pace at which things are moving is crazy and I have to wonder if rjmccall & co ever actually sleep.

After 14 years of Objective C I just started writing my first app in Swift and I must say (despite the autocorrect issue) I find using Swift is loving fantastic.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Swift is fantastic. The only thing (obviously generalizing here) holding it back is XCode, compilation times, and debugging randomly not working. It's just drat tiring.

toiletbrush
May 17, 2010
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.

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

Kallikrates
Jul 7, 2002
Pro Lurker
Drawing a blank, but given the idea: Either<T,U> ,I want to return something: Both<T,U> in some languages this is called a tuple (different from a swift tuple?).

return (foo, foo) seems clumsy and this would be the case where I might not have a custom T defined as subclassing, or conforming to U. I can do this with swift2 I think but how about swift1.2?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I have no idea what you are talking about. Write the function as you think you'd want to write it in a different language, and maybe we can work from there.

Kallikrates
Jul 7, 2002
Pro Lurker
I think I figured it out when writing the example. I was looking for Protocol Composition. Here it is simplified.

Swift code:
class Selecter: NSObject {
    func select() {}
    //opening this for modifications is dragons:
}

protocol Selectable {
    func nextSelectableSingle() -> NSObject<Selectable> //one return not allowed, what I was trying
    func nextSelectableTuple() -> (NSObject, Selectable) //tuple return allowed but is there a better way?
    func nextSelectableMultiProtocol() -> protocol<SelecterProtocol, Selectable> //yes...
}

protocol SelecterProtocol {
    func select()
    //only methods I am interested in, that exists for Selector
}

extension Selecter: Selectable {
    func nextSelectableSingle() -> NSObject<Selectable> {
        //... 
        return Selecter() // what id like maybe the wrong use of categories
    }
    func nextSelectableTuple() -> (NSObject, Selectable) {
        //...
        let foo = Selecter()
        return (foo, foo) //what im trying to avoid
    }
}

extension Selecter: SelecterProtocol {
    func nextSelectableMultiProtocol() -> protocol<SelecterProtocol, Selectable> {
	//... oh
        return Selecter()
    }
}

Selecter().nextSelectableMultiProtocol().nextSelectableMultiProtocol().select()
I haven't done much swift2 yet so maybe there is an even better way.

Kallikrates fucked around with this message at 18:52 on Jul 17, 2015

brap
Aug 23, 2004

Grimey Drawer
I'm so confused. Are you inventing a linked list because you don't like the way tuples look?

Kallikrates
Jul 7, 2002
Pro Lurker
No, names changed to protect the innocent and distill the idea.

The real thing routes URLs through UIViewControllers, where not all View Controllers are custom subclasses, but have common behavior in an extension. Navigation Controllers and Tab Bar Controllers also mean I have collections of ViewControllers lacking some type information I want.

Maybe the idea of "SelecterProtocol/ViewControllable" is redundant in a world with "Selectable/URLRoutable" but not all ViewControllers need to know about routing URLs.

chaosbreather
Dec 9, 2001

Wry and wise,
but also very sexual.

I think this whole thing is because you don't know about downcasting?

if let chair = furniture as? Chair

Kallikrates
Jul 7, 2002
Pro Lurker
Using your example not really - because I don't have a Chair subclass. The furniture framework is closed to extension and I'm vended Furniture Items only. For now I've applied the Sittable Protocol to Furniture via an extension. But I was thinking of the case where not all pieces of furniture support sitting.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
I'm doing horrible things with tuples :v:

I love that you can pass a tuple like (A, B, C) into a function that expects those three parameters and it just works; this gives a lot of power. But tuples are still pretty limited right now in the kind of metaprogramming magic I can do because Swift doesn't have a clean way to do arbitrary compile-time transforms from what I can tell (e.g., take tuple types (A, B) and (C, D) and produce (A, B, C, D)). I haven't done any serious modern C++ but variadic generics would help out here, I imagine.

I can write a bunch of generic functions that take, say, a tuple (A, B) and an argument C and return (A, B, C), but I'd have to write a separate one for each tuple size (or pair of tuple sizes!). I can do this, it's just repetitive. Will we ever get primitives that might make this cleaner for tuples of arbitrary size?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Heh. Who knows?

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
You're getting more coy with your replies lately, which means you're either annoyed or there's something big coming :v:

I choose to believe the latter!

Doh004
Apr 22, 2007

Mmmmm Donuts...
He was the same way before WWDC and Swift 2.0 soooo.... :iiam:

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
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.

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.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Beta 4 is out!

I'm curious what the reason for requiring the indirect keyword is... why not just detect recursive enums and handle it automatically? I assume there is a performance or space cost for it?

On the Objective-C nullability qualifiers (and this applies to __block, et al as well): Why can't the compiler contextually handle these as keywords and drop the leading underscores? In the extremely rare case you have functions or variables named "nullable" surely the compiler can determine "NSString * nullable x;" is a declaration? It still bothers me every time I see it. Is it the preprocessor? Some ambiguous case in the grammar?


P.S. Thank you for 21718497. It was killing me.

Flobbster
Feb 17, 2005

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

Doctor w-rw-rw- posted:

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.

Agreed 100%, thanks to you and your team :) As much as I'd love to have every useful feature known to man in the language, I'd much rather have faster compiles and fewer segfaults when I try to push the language past it's breaking point with some bizarre design. (E.g., the reason I needed the tuple tricks is because I'm trying to splat an array of arbitrary runtime size into the argument list of a block. I'm a sadist. I have it working in a marginally safe way, limited only by how many of times I want to C&P the code for each possible number of arguments.)

Swift is still the most fun I've had using any programming language for a long time and it's amazing how powerful and elegant it is even a year after it launched (but tell your Xcode colleagues to fix their drat formatting :argh: ).

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Ender.uNF posted:

Is it the preprocessor?

Maybe there's also some better reason, but the preprocessor is the usual reason for lovely names. Doing #define nullable const before including the Foundation headers was previously legal (if insane) so adding nullable would be a breaking change, while #define _Nullable const is not legal.

Mathlete
Nov 30, 2005

It's hip to be a squared square.
What would be the benefit from Apple's perspective of making the language open-source? I don't mean this in a snarky way at all, I'm just ignorant of the advantages.

Sinestro
Oct 31, 2010

The perfect day needs the perfect set of wheels.
The goal'd be to maybe get it used on other platforms. And gently caress, I hope it does, because it's about as good as a language can be while still being "bad" enough (allowing mutable values, using OOP, that kind of grognardy stuff) that it could really take off.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Ender.uNF posted:

I'm curious what the reason for requiring the indirect keyword is... why not just detect recursive enums and handle it automatically? I assume there is a performance or space cost for it?

Okay, so let's tackle that last question first. Swift's normal representation for an enum is to allocate all the payloads "inline", like a C union, and then figure out some way to tell them apart, using extra storage as necessary. So if you have an enum with four cases, and two of them have payloads, and both payloads are Int32s, then it's basically going to be represented as 4 bytes for the Int32 plus an extra byte to store a "discriminator", i.e. the index of the active case.† If you add a fifth case whose payload is a tuple with 1000 Int32s, then guess what, the enum's going to be 4000 bytes, plus a discriminator, even if in practice it's rarely storing that case. Whether we really guarantee that is up for debate, but that's how it works right now. And this has problems with recursive enums for the obvious reason that a recursive case allocated inline recursively would require infinite space.††

† Int32 is, in some sense, an extreme example: it occupies 4 bytes, and every single single bit-pattern of those 4 bytes is a valid Int32 value. For other types, like class references, we can sometimes be smarter about how we store the discriminator because not every bit-pattern is a valid class reference. But that's not really important to this explanation, because it doesn't affect the basic question of whether the payload is stored inline.

†† Technically, it's either infinite or impossible to construct a value of, as in enum A { case F(A) }.

An indirect case is just a case whose "real" payload is, essentially, a class reference storing the formal payload. Therefore, constructing that case requires a heap allocation. This then solves the infinite-layout problem because the layout of the case's payload is always fixed, regardless of what's actually stored there.

Okay, so. There are two dimensions of design here, and they aren't completely orthogonal. The first is static vs. dynamic: do we decide to use an indirect case during compilation, or do we detect that we need it at runtime? The second is explicit vs. implicit: if we can see that an indirect case will obviously be required to prevent a type from being infinite, do we require the programmer to acknowledge that explicitly, or do we just make it work?

Some formalism for a second. One way to think about values in a programming language (ignoring references for a second) is that you've got a set of primitive constants, and then you've got named "constructors" that just lists out some number of other values. Every value in the language is a tree of these things with finite depth, e.g. A(B(0, C), D("help", E)). Now, that's an untyped formalism, and a type system tells you stuff about these constructors: each constructor has a type, and that type constrains the list of values in various ways, e.g. to be a fixed size and to have values of fixed types at each position. All this typing restricts you somewhat, but you can still make a value-tree with an arbitrary shape as long as you have four elements in your type system: conjunction, disjunction, recursion, and top.

Now, enums (ADTs) give you all four of those: conjunction via cases with multiple payloads, disjunction via multiple cases, recursion via payloads of the enum type, and top via cases with no payload. And it's straightforward to design an efficient representation for a single, non-generic enum which ensures that its full range of structure is expressible. The trouble is that enums aren't the only way to get those four elements, and any structure that introduces one of those elements at all can be used to emulate its full generality. So, for example, optionals provide disjunction and top, and structs provide conjunction, and generics can create recursion where it wasn't statically obvious, and optionals are generic; so I can theoretically write:

code:
struct Pair<A,B> { var fst: A; var snd: B }
struct List { var pair: Pair<Int, List?> }
and a maximally expressive language would have to allow this.

However, when you start talking about how to organize values in memory, this really disrupts the representation; simple ideas like "structs and enums just contain all of their fields and cases inline" don't work. The easiest way to solve this is to say that all enum cases are stored indirectly, and then maybe teach the implementation to try to prove that storing a particular case inline wouldn't make an infinite type. This is a static+implicit solution. Another solution would be to figure out dynamically whether you have an infinite type, potentially per-instantiation for a generic type. Both of these a pretty "magical", where you have to understand not just how a type is written but how it's being actually instantiated and/or used, potentially at runtime; and in Swift, we really do want to support a more "systems" level of programming by enabling developers to reason about representations and allocations when they need to. So instead, we decided that the right solution is to simply not support general, non-obvious recursion through enums, and require the programmer to mediate that explicitly with indirect. That is, a static+explicit solution.

Now, you can argue that some recursion is obvious, and that we should just automatically infer indirect cases when, say, the payload directly contains a value of the enum type. That was actually exactly my stance: we should require indirect for the general case but make direct recursion implicitly indirect. There were a few different arguments against it. The first is that it's better to be consistent and always require indirect; but I don't really accept this, because in practice I think that inferring direct recursion would effectively erase indirect from the language for normal users and so there'd be no perceived inconsistency. The other arguments were harder to dispute, though: there are some hard questions about where exactly to draw the line (tuples? optionals? structs in the same file?), and it's easier to revisit the decision to conservatively require indirect than the other way around. So that's how we ended up where we are.

Ender.uNF posted:

On the Objective-C nullability qualifiers (and this applies to __block, et al as well): Why can't the compiler contextually handle these as keywords and drop the leading underscores? In the extremely rare case you have functions or variables named "nullable" surely the compiler can determine "NSString * nullable x;" is a declaration? It still bothers me every time I see it. Is it the preprocessor? Some ambiguous case in the grammar?

Partly the preprocessor, partly concern about ambiguity which may or may not be warranted. People have been burned by contextual keywords before. Hell, we've been burned by using things from the reserved namespace before, just because other people had the same idea. We've actually changed the formal keyword to _Nullable because people were #defining __nullable; we didn't notice because it was a function-like macro, so it didn't bite us until somebody wrote void * __nullable (*)() or something like that.

__block is actually a macro that expands to an attribute, and it's the same with several other of these things, so picking something that's a valid identifier would have been disastrous for those. At some point, there's a consistency/flexibility argument, too.

Ender.uNF posted:

P.S. Thank you for 21718497. It was killing me.

I'll pass that on.

rjmccall fucked around with this message at 10:17 on Jul 22, 2015

Mr Shiny Pants
Nov 12, 2012
More of a general question, I saw the Swift playground presentation and I was wondering if the showing of output while you type was influenced by Brett Victor's work?

He has done some awesome presentations about "making stuff easier to see". Well done!

toiletbrush
May 17, 2010
Is something like 'yield' in the pipeline for Swift? Also assigning to vars directly from switch statements? Someone mentioned before that you can wrap the switch in a closure, but type inference doesn't seem able to infer the type unless you annotate the var you are assigning to, and it feels a bit clunky.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Am I just mistaken, but do I need to add my UIViewControllers (and subsequent dependencies) to my test targets in order to unit test them? Particularly in the instance where I would like to instantiate my viewController from a Storyboard.

This is for 1.2 of course. 2.0 can't come soon enough :)

Adbot
ADBOT LOVES YOU

Meat Street
Oct 17, 2004

knowin' nothin' in life but to be legit
That's one way, or you can make the methods you want to test (and the classes they're declared in) public. Either way the issue you're running into is that your classes aren't exposed outside the app module, so your test target can't see them.

  • Locked thread