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
Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
Honestly, these days, I'd much rather we never see optional methods in protocols. Now that we can pass around closures as first-class objects in variables, I can't actually think of a use case where I'd want to conform to a protocol but not have to implement all the protocol's methods.

Adbot
ADBOT LOVES YOU

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

Kallikrates posted:

How are you guys handling the optional protocol pattern in swift? I want to make it a rule that if you need this pattern in swift to not use @objc, but to use inheritance or composition of different protocols and optionals. But I'm getting push back because of what I think is a crufty reason.

"It's a useful pattern and thats why apple gave us @objc"

Outside of IBOutlets, and Vending to objc I want to remove as much @objc as possible.

Strictly speaking? Multiple protocols, possibly inheriting from each other if necessary.

Bigger picture? Apple's delegate pattern (and use of protocols in general) conflate different concerns: a potentially unbounded stream of async event notifications and querying for values when they are needed. I have the option to ignore valueChanged. I cannot ignore tableView:cellForRowAtIndexPath: and still have a useful table view.

I'm starting to lean toward stuff like ReactiveCocoa 3.0 (Signal/SignalProducer) because honestly, why try to cram an Objective-C pattern into a wholly new language?

Echo Video
Jan 17, 2004

cellForRow is a data source method, not a delegate one. People super-abuse the delegate pattern for communication (it should be for extension of functionality, bagawd) but it has a good place in the list of techniques.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
Forgive my ignorance, but what does putting "import Foundation" or "import UIKit" at the top of a given Swift file inside a project actually do? I understand that in say, C, you provide header files in #import statements in order to let the linker do its job, but that was at a per-file level, not a per-module level.

Following up on that, is there any compelling reason not to be able to say "just consider every file in this project to `import Foundation`"? It just seems odd to me that for Foundation, UIKit, or even any module that touches much of my code, I have to clearly define that I'm importing it.

I guess what I'm saying is, is there a compelling reason not to have a Swift version of Prefix.pch to do this for us?

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?

Axiem posted:

Forgive my ignorance, but what does putting "import Foundation" or "import UIKit" at the top of a given Swift file inside a project actually do? I understand that in say, C, you provide header files in #import statements in order to let the linker do its job, but that was at a per-file level, not a per-module level.

Header files in C-family languages aren't for the linker, they're for the compiler: In order to use functions or variables the compiler needs to see declarations for them, so it knows how to generate code to access them. This is done via direct text inclusion, which has its pluses and minuses. And it's the generated code (along with a list of libraries to look in for external definitions) that gets fed to the linker, not the headers.

With Swift you can effectively treat module imports as the same sort of thing, just fancier. The compiler is basically doing the equivalent of precompiled prefix headers for you behind the scenes, because it doesn't have to worry about the language semantics specifying that literal text inclusion happens. (This also applies to @import in Objective-C.)

quote:

Following up on that, is there any compelling reason not to be able to say "just consider every file in this project to `import Foundation`"? It just seems odd to me that for Foundation, UIKit, or even any module that touches much of my code, I have to clearly define that I'm importing it.

I guess what I'm saying is, is there a compelling reason not to have a Swift version of Prefix.pch to do this for us?

It helps the modularity of your code to be explicit about what it's using. As an example, if a class doesn't truly depend on anything from UIKit, it shouldn't import UIKit, and that means it'll be portable to OS X too.

As an example, a couple years back I experimentally extracted an Awful.framework from Awful.app that would work on OS X. 99% of it didn't need UIKit and came right over, so it should have all just imported Foundation. (The only thing that didn't was something that triggered the network activity indicator, which was easily just abstracted behind a delegate.)

In general, you'll find that lots of oldschool NeXT developers treat development as an exercise in putting together a bunch of frameworks that then get composed into one or more apps. Part of doing this is clearly defining the boundaries between the different parts of your app, which includes considering their dependencies.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

eschaton posted:

Part of doing this is clearly defining the boundaries between the different parts of your app, which includes considering their dependencies.

This is so very much gold packed into such a simple sentence.

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'

eschaton posted:

In general, you'll find that lots of oldschool NeXT developers treat development as an exercise in putting together a bunch of frameworks that then get composed into one or more apps. Part of doing this is clearly defining the boundaries between the different parts of your app, which includes considering their dependencies.

I come from the C++ tree of OOP semantics, and have been wondering why the internal access control works as it does, and not like protected. Is this the answer to the question I didn't ask?

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do

eschaton posted:

Part of doing this is clearly defining the boundaries between the different parts of your app, which includes considering their dependencies.

This does make sense to me, and is something I miss about the header-file-inclusion-tree from C (but not enough to want it back). It does make sense to me not to make all these non-UI things use UIKit (although, if they need CGFloats...). But Foundation? A logging framework (like CocoaLumberjack) that's used everywhere?

Honestly, Foundation and XCTest are the two that I'm just getting tired of typing in all of my files (all my test files, in the latter case, at least). And also in my test files telling them all to import my main module (because why would I not want to do this?). Many of the rest of the modules, like UIKit, I'm totally cool with not allowing this for the reasons you mentioned.

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

dupersaurus posted:

I come from the C++ tree of OOP semantics, and have been wondering why the internal access control works as it does, and not like protected. Is this the answer to the question I didn't ask?

internal works like it does because that's how internal works in every language that has the concept (e.g. C#)

The reason why it's in Swift but protected isn't is probably related to that, though. Here's the Swift blog post on the reasoning for not having protected.

toiletbrush
May 17, 2010
Is there a possibility of being able to assign from switch statements? I'm writing a Chip-8 interpreter in Swift, decoding instructions using tuples in a switch statement, but each operator needs to return a value. Right now I set a 'result' value in every case statement, but it would be nice if I could do this...

code:
let result = switch opcode {
            case (0x0, 0x0, 0xe, 0x0) : clearScreen()
            case (0x0, 0x0, 0xe, 0xe) : returnFromSubroutine()
            case (0x1, let n1, let n2, let n3) : jump(decodeThreeBytes(n1, n2: n2, n3: n3))
            case (0x2, let n1, let n2, let n3) : callSubroutine(decodeThreeBytes(n1, n2: n2, n3: n3))
           ......
            case (0x8, let x, let y, 2) : logicallyCombineRegister(x, withRegister: y, operation: .And)
            case (0x8, let x, let y, 3) : logicallyCombineRegister(x, withRegister: y, operation: .Xor)
            default: .Failed(reason: "Invalid instruction ")
}
Does this approach even work?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
code:
let result = {
    switch opcode {
            case (0x0, 0x0, 0xe, 0x0) : return clearScreen()
            case (0x0, 0x0, 0xe, 0xe) : return returnFromSubroutine()
            case (0x1, let n1, let n2, let n3) : return jump(decodeThreeBytes(n1, n2: n2, n3: n3))
            case (0x2, let n1, let n2, let n3) : return callSubroutine(decodeThreeBytes(n1, n2: n2, n3: n3))
            ......
            case (0x8, let x, let y, 2) : return logicallyCombineRegister(x, withRegister: y, operation: .And)
            case (0x8, let x, let y, 3) : return logicallyCombineRegister(x, withRegister: y, operation: .Xor)
            default: return .Failed(reason: "Invalid instruction ")
    }
}()

toiletbrush
May 17, 2010
Oh, well thats quite nice isn't it! Thanks!

Edit to add: that works but you have to be explicit about the return type, type inference doesn't seem to be able to figure it out.

I've got another question, would it be possible to have a 'strict' version of typealias that means that the alias is treated as it's own distinct type, rather than just an alias? So something like this would create a compiler error:

code:
typealias Gram = Int

var g = Gram(5)
g = Int(2) // compiler error 'Int' is not convertible to 'Gram'

toiletbrush fucked around with this message at 17:09 on May 26, 2015

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'
What's the intended use differentiation between tuples and structs? I know that on the extremes, if you have a single function with multiple returns use a tuple, and if you need methods and such use structs. But what about that grey area where the same two bits of information appear in many places -- call it (balls:Int, strikes:Int) -- so writing that tuple signature everywhere gets tedious, but everything that uses the data is external so there's no need for any methods. Do I typealias the tuple, make a struct, or does it not really matter?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Typealiasing a tuple is probably not ever a sensible thing to do. Outside of generic programming scenarios where you can't use a struct with meaningful names, the main reason to use a tuple is where a struct would be pointless boilerplate. If you're using a specific type of tuple enough places to justify a type name, then defining a struct instead is not massively boilerplate-inducing.

There's definitely nothing wrong with a struct with zero methods.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

dupersaurus posted:

What's the intended use differentiation between tuples and structs? I know that on the extremes, if you have a single function with multiple returns use a tuple, and if you need methods and such use structs. But what about that grey area where the same two bits of information appear in many places -- call it (balls:Int, strikes:Int) -- so writing that tuple signature everywhere gets tedious, but everything that uses the data is external so there's no need for any methods. Do I typealias the tuple, make a struct, or does it not really matter?

Tuples also have the unique ability to be trivially unwrapped into method parameters, so there's that.

There's no shame in a methodless struct.

Other than that, I think it's just a matter of style. If I bother to come up with a name for my typealiased tuple, I'm probably just going to make a struct anyway.

edit: beaten like a named tuple

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'
Yeah my instinct was a struct, but I didn't know if the language had a different intent. Thanks.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

dupersaurus posted:

Yeah my instinct was a struct, but I didn't know if the language had a different intent. Thanks.

That's pretty much it. Tuples are nice for one-off aggregates, but yeah, a typealias is a pretty clear point at which you should be using a struct.

Doh004
Apr 22, 2007

Mmmmm Donuts...
How're folks handling functions in Enums?

Basically, I'm trying to grasp how "big" I allow some of my enums to get.

For example, I have an activity tracker:

code:
public enum Activities : String
{
    // Login/Out
    case Login = "Login"
    case Logout = "Logout"
 }
To which I'd normally pass into a singleton:

code:
ActivityTracker.trackActivity(Activities.Login, properties: ["Hello" : "World"])
I was thinking I could actually prevent access to this all by adding a function in the Activities enum to do just that
code:
public enum Activities: String
{
    public func trackWithProperties(properties: [String: AnyObject]?) -> Void
    {
        ActivityTracker.trackActivity(self, properties: properties)
    }
}
// Then I could do
Activities.Login.trackWithProperties(["Hello" : "World"])

Does this just come down to personal preference?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
I don't see the benefit. You haven't actually reduced the amount of code at the call site or factored anything out.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Perhaps that wasn't the best example ever. I guess I'm more curious to people's thoughts as to when enums should own responsibility of more than just their values.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doh004 posted:

Perhaps that wasn't the best example ever. I guess I'm more curious to people's thoughts as to when enums should own responsibility of more than just their values.

I'm struggling to come up with a convincing reason for the enum to have anything unrelated to its value. You can certainly have methods, computed properties, and so on, but I reckon they shouldn't involve much beyond the enum itself.

Doh004
Apr 22, 2007

Mmmmm Donuts...

pokeyman posted:

I'm struggling to come up with a convincing reason for the enum to have anything unrelated to its value. You can certainly have methods, computed properties, and so on, but I reckon they shouldn't involve much beyond the enum itself.

I could see that. Maybe for example I could do:

code:
public enum Activities: String
{
    case Login = "Logged in"
    case Logout = "Logged out"
    case ForgotPassword = "Forgot password"
    
    case OrderCompleted = "Completed an order"
    
    public func isAuthenticationActivity() -> Bool
    {
        return self == .Login || self == .Logout || self == .ForgotPassword
    }
}
I guess that keeps all of that logic within the Activities.

toiletbrush
May 17, 2010
I got another 'expression was too complex to be solved in reasonable time' compiler exception...
code:
extension Array {
    func sum() -> Int {
        return self.reduce(Int(0)) { Int($0) + Int($1) }
    }
}
I'm gonna file a Radar, but I'd be really interested to hear why it causes issues for type inference?

Also, it compiles fine if I do '$0 as Int', although you don't get any compiler warnings if you pass an array of non-Ints, and instead the app crashes...will this be possible in the future?

jawbroken
Aug 13, 2007

messmate king
Presumably it causes inference issues because the compiler starts by expanding the list of all the things that an Int can be initialised from. What you're trying to do, i.e. extend Array in a way that only applies to Arrays of things that can initialise an Int, isn't possible in Swift at the moment, and your code wouldn't compile even if it wasn't “too complex”. The right way for now is usually to made a function, instead of a method, that takes an array as an argument and has a suitable generic constraint.

brap
Aug 23, 2004

Grimey Drawer
Consider doing one of the following.

code:

[1,2,3].reduce(0, +)
listOfSomeType.map(toNumberType).reduce(0, +)

I think I have the syntax right there...

Sadly generic type constraints and extensions don't really mix yet in Swift.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
In this matter, I counsel patience.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

rjmccall posted:

In this matter, I counsel patience.

So excited. Have an awesome week.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

rjmccall posted:

In this matter, I counsel patience.

I am super excited; looking forward to meeting the Swift team.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Wish I could be there!

Dewgy
Nov 10, 2005

~🚚special delivery~📦
Congrats on open source, doods! :toot:

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah, pretty thrilled about it. It's been a long time coming.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Had to be a ton of work, too. Great stuff.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Maintaining the port actually hasn't been too bad. It's scrubbing the repository that's going to be a pain, because I don't think we want to just cut a snapshot.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Very cool news, congratulations rjmccall!

lord funk
Feb 16, 2004

Biggest applause break 2 years running :toot:

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Congrats; can't wait for the Platform SotU

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

rjmccall posted:

Maintaining the port actually hasn't been too bad. It's scrubbing the repository that's going to be a pain, because I don't think we want to just cut a snapshot.

Ah, you still have to pass that stone. :rip:

Toady
Jan 12, 2009

The Swift blog has a post on 2.0 with a summary of new things. try-catch has arrived.

Edit: More on the Swift marketing page.

Toady fucked around with this message at 22:13 on Jun 8, 2015

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

rjmccall: would love to know more about why you chose Go-style defer over try-finally. I'd have expected the latter!

Adbot
ADBOT LOVES YOU

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Defer puts the cleanup code next to the code creating the thing which needs to be cleaned up rather than as far away as possible (and is pretty useful even in the absence of exceptions).

  • Locked thread