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
Choadmaster
Oct 7, 2004

I don't care how snug they fit, you're nuts!
I tried writing a little OS X app in Swift last week and ran into too many roadblocks to make it worth the effort. Nothing significantly wrong with Swift itself - I rather like it - but there are many areas where it just isn't ready yet (to be expected, as it isn't even at 1.0) and where translating Objective-C frameworks into the Swift paradigm just isn't smooth. The worst roadblock was being utterly unable to use NSWindowController to load a nib, because init(windowNibName:) is a convenience initializer and thus it simply cannot be called from a subclass initializer. Praying that gets fixed soon.

In the mean time, I'm playing around with Swift by teaching my friend's kid programming. He's been asking to forever and playgrounds seemed like the perfect learning tool - and really, they're great. I understand now why my hopes to use standard input in the playground were silly given the way it is constantly running/compiling.

Here's something I just ran into that I was surprised didn't work:

code:
var response = readln()					// Obviously not doing this one in the playground
if let result = response.toInt() && result > 0 {	// Error: unresolved identifier 'result'
	max = result
}
The second use of 'result' in that if statement doesn't work. I'd expect it to, since the only way to get to the second condition is if the first succeeds. Bug? Intended behavior?

Adbot
ADBOT LOVES YOU

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
It's parsed as let result = (response.toInt() && result > 0), not (let result = response.toInt()) && result > 0

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

Choadmaster posted:

The worst roadblock was being utterly unable to use NSWindowController to load a nib, because init(windowNibName:) is a convenience initializer and thus it simply cannot be called from a subclass initializer. Praying that gets fixed soon.

You filed a bug, right? :)

Choadmaster
Oct 7, 2004

I don't care how snug they fit, you're nuts!

Plorkyeran posted:

It's parsed as let result = (response.toInt() && result > 0), not (let result = response.toInt()) && result > 0

That's quite unfortunate, because
code:
if (value exists) && (validation of value) {
    // Use value
}
else {
    // Error / fallback code
}
would seem to be a common use case.

Dessert Rose posted:

You filed a bug, right? :)

1) I don't file bugs anymore, I've had too many blatantly ignored (and worse, closed as "fixed" even when the detailed steps I gave to reproduce them on a fresh system still demonstrate the bug... Hello Mail) and it's a waste of my time, and 2) I know this bug is already filed, and the Swift team does not use dupes as a priority hint (understandable at this stage, as they presumably have a detailed roadmap for what needs to be completed already).


VVV Edit: If you've had more positive interactions with the bug reporter, more power to you. I'm not asking you not to use it.

Choadmaster fucked around with this message at 23:01 on Jul 5, 2014

Toady
Jan 12, 2009

Choadmaster posted:

1) I don't file bugs anymore, I've had too many blatantly ignored (and worse, closed as "fixed" even when the detailed steps I gave to reproduce them on a fresh system still demonstrate the bug... Hello Mail) and it's a waste of my time

:rolleyes:

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?

Choadmaster posted:

2) I know this bug is already filed, and the Swift team does not use dupes as a priority hint (understandable at this stage, as they presumably have a detailed roadmap for what needs to be completed already).

I think that was referring to filing intentional duplicates to try to inflate priority, like "this bug is a duplicate of 12345, here's some text copied and pasted from a web site, I vote for this feature too!"

If you are yourself running into a bug or other difficulty, you should always file it, and not worry about whether what you're filing is a dup of something else. (Only don't if you know your exact issue is already known and you've been asked not to—like, say, for access control in Swift.)

Also, don't get caught up spending hours putting together a bug report, a couple sentences is fine if that's all you actually need to specifically describe the issue. If an engineering team needs more detail they'll ask. And push back if a bug comes back to you as fixed but from your perspective it's not.

Finally, if you would like to see a feature/enhancement/change, you should also always file it yourself, and explain your needs clearly; they may not be addressed the way you requested, but they will be taken into account. (This is the reason "why" matters, not just "what.") An example of that from early OS X history was when some developers asked for the Enterprise Objects Framework to be brought forward; what they got was Core Data instead, as a model-level persistence framework for Cocoa.

Toady
Jan 12, 2009

eschaton posted:

I think that was referring to filing intentional duplicates to try to inflate priority, like "this bug is a duplicate of 12345, here's some text copied and pasted from a web site, I vote for this feature too!"

That was my impression. It was starting to show up on the developer forums ("here's my radar so you can dupe it").

Toady
Jan 12, 2009

Also, more than once in a thread about something seemingly obvious, I've seen Corbin or some other Apple engineer say they saw no radars for it. Ever since, I always submit one unless I know I don't need to, and I make sure to explain what exactly I'm trying to do and what workarounds I've been using.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
Looks like a beta version of Xcode has dropped--and in this one, arrays are fixed!

Still no access control, though :(

dizzywhip
Dec 23, 2005

I'm pretty sure they said that access control won't be in for 1.0.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

dizzywhip posted:

I'm pretty sure they said that access control won't be in for 1.0.

That or the complete opposite:

rjmccall posted:

Everything is public for now. We expect to have basic access control for 1.0.

ljw1004
Jan 18, 2005

rum
The release notes for Xcode beta 3 say "The online Swift Programming Language documentation and book has been updated. See: https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11"

But that link only shows that the book was "published June 2nd, updated June 12th"

Any ideas on how to get the updated book? or ideas when it will be released?



edit: my iBook apparently hasn't been updated - it still shows things like "String[]" - and I'm not sure how to force an update.

ljw1004 fucked around with this message at 20:12 on Jul 7, 2014

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

ljw1004 posted:

The release notes for Xcode beta 3 say "The online Swift Programming Language documentation and book has been updated. See: https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11"

But that link only shows that the book was "published June 2nd, updated June 12th"

Any ideas on how to get the updated book? or ideas when it will be released?

I'm guessing that's just a caching thing. My iBook appears to be updated (chagelog please?) based on the file's modified date, but the iBooks store shows the old date. Based on how long it takes App Store releases to propagate, it seems like it's similar iTunes weirdness that'll fix itself eventually.

Based on those XCode release notes, I'm liking the changes.

dizzywhip
Dec 23, 2005

ultramiraculous posted:

That or the complete opposite:

:saddowns:

I could have sworn I heard an engineer on the developer forums say that it's definitely planned but wouldn't be in for 1.0. I must be misremembering though.

dizzywhip fucked around with this message at 19:58 on Jul 7, 2014

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

eschaton posted:

I think that was referring to filing intentional duplicates to try to inflate priority, like "this bug is a duplicate of 12345, here's some text copied and pasted from a web site, I vote for this feature too!"

If you are yourself running into a bug or other difficulty, you should always file it, and not worry about whether what you're filing is a dup of something else. (Only don't if you know your exact issue is already known and you've been asked not to—like, say, for access control in Swift.)

Also, don't get caught up spending hours putting together a bug report, a couple sentences is fine if that's all you actually need to specifically describe the issue. If an engineering team needs more detail they'll ask. And push back if a bug comes back to you as fixed but from your perspective it's not.

Finally, if you would like to see a feature/enhancement/change, you should also always file it yourself, and explain your needs clearly; they may not be addressed the way you requested, but they will be taken into account. (This is the reason "why" matters, not just "what.") An example of that from early OS X history was when some developers asked for the Enterprise Objects Framework to be brought forward; what they got was Core Data instead, as a model-level persistence framework for Cocoa.

A few of my Swift bugs were closed as dupes (see below). I'd have to login to check but the other ~20 are sitting there, unexamined, with zero information since the day I filed them. It's been nearly a month. This includes swift compiler hard crash and eternal loop bugs with attached repro cases and crash reports. A simple "tested and reproduced" acknowledgement would be at least minor encouragement. For compiler bugs, Apple should have had some interns whip up a code submission system linked to the bug reports that would allow us to upload sample projects, then run them inside a VM snapshot to immediately verify that the code crashes or loops eternally, roll back the snapshot, then move on to the next submission. A farm of a hundred machines could churn their way through the submissions, probably even at night using spare cycles in existing data centers. Any bug that reproduces a crash could then be cross-checked with existing crashes automatically to determine hot fault paths. The ways the system could be improved are endless.

* The big problem with duplicates is that since radar is not public, there is an intermediate window in which a bug is not widely known enough to show up on stackoverflow in google searches, but is far more than a one-off, leading to thousands / tens of thousands (or more) wasted effort by we non-Apple folks to create reproducible test cases and fill out bug reports. That experience is highly demotivating.


I endure Apple's bug tracker because it's the one small way I can repay rjmccall's kindness and awesome technical postings over the years. There is nothing positive or pleasant about the experience.

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...
Ugh. This doesn't work:

code:
enum QueryResult
{
    case Error(error: NSError)
    case Results(results: [NSObject])
}

let bar = QueryResult.Results(results: [])

switch(bar)
{
case .Error(let error):
    abort()
    
case .Results(let results):
    for s in results
    {
    }
}
which really puts a cramp in my Core Data querying style, let me tell you.

(You can do it if you explicitly cast "results" to an array type, but it's still frustrating.)

Also, I dislike not being able to explicitly specialize generic methods. I'd prefer "fetchObjects<Quest>(...)" to "fetchObjects(...) as QueryResult<Quest>" by far, and it would let me do stupid tricks like have the entity name in an object property.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
You can pass the explicit types as a regular parameter:

code:
func fetchObjects<T: IntegerLiteralConvertible>(_: T.Type) -> [T] {
    return [1,2,3]
}

println(fetchObjects(Int))
println(fetchObjects(Float))

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

Plorkyeran posted:

You can pass the explicit types as a regular parameter:

code:
func fetchObjects<T: IntegerLiteralConvertible>(_: T.Type) -> [T] {
    return [1,2,3]
}

println(fetchObjects(Int))
println(fetchObjects(Float))

Oh, that's clever (and fits my use case perfectly). Thanks!

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Ender.uNF posted:

* The big problem with duplicates is that since radar is not public, there is an intermediate window in which a bug is not widely known enough to show up on stackoverflow in google searches, but is far more than a one-off, leading to thousands / tens of thousands (or more) wasted effort by we non-Apple folks to create reproducible test cases and fill out bug reports. That experience is highly demotivating.

Does OpenRadar help at all? I don't really know how it relates to Radar.

Most people filing bugs, IME, don't search for duplicates, but it does indeed help the people who file the best bugs. If there's a good feedback loop then filing without a reproduction case (just snippets) can work, since the engineer can ask for more detail if they don't already have it on file with such a case.

It is a pretty bad experience, though. Even filing exploitable bugs in core system libraries was generally met with radio silence, as with bugs that affected millions of users via widely-used apps. It seems like you really need to escalate through a relationship to get traction in most cases.

Meat Street
Oct 17, 2004

knowin' nothin' in life but to be legit
New Apple Blog, three words I never thought I'd type together:

https://developer.apple.com/swift/blog/

Toady
Jan 12, 2009

I was hoping for this. Apple also has a WebKit blog.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
I am getting a weird problem, and I want to make sure I'm not crazy.

Here is the relevant code.

code:
    func testWhenBeginAddTrainThenObserverIsNotified() {
        var selectFromMapCount = 0
        
        testObject.whenSelectFromMap {
            selectFromMapCount++
        }
        
        testObject.beginAddTrain()
        
        XCTAssertEqual(selectFromMapCount, 1)
        
    }
On the `selectFromMapCount++`, it is giving me an error that "'Int' is not identical to 'Float'". Alt-clicking on selectFromMapCount tells me that it is being considered an Int, and I have no idea where the Float is coming from. If I change it to `selectFromMapCount += 1`, it's fine and works as expected.

For reference, the function `whenSelectFromMap` takes as an argument ()->() and has no return, so its signature is more properly ( ()->() ) -> (), just to be confusing.

Am I running into something weird with the trailing block syntax, or is this an actual bug?

dizzywhip
Dec 23, 2005

I'm not sure where it's getting the Float from either, but the error messages in Swift seem to still be really buggy. I had something similar where I was comparing the result of a function that returned an NSComparisonResult to a value from that enum, and it thought that the function was returning a completely unrelated enum that I'd declared in another file.

Anyways, I'm fairly certain that the error is due to implicit returns of single-expression closures. Since the ++ operator returns the variable's pre-incremented value, and that expression is the only one in the closure, that value is implicitly returned, and the signature of that closure is implicitly changed to () -> Int, which is incompatible with the method that you're calling. I filed a bug about this the other day -- I really think that implicit returns should be disabled when the closure is being used in a context that expects no return value.

You should be able to fix the error by putting an empty return statement at the end of the closure.

Axiem
Oct 19, 2005

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

dizzywhip posted:

Anyways, I'm fairly certain that the error is due to implicit returns of single-expression closures.

Yep, that's the thing about closure syntax I completely forgot. Adding the return does indeed make it work as expected. I'll remember all of these things eventually!

ufarn
May 30, 2009
Do we know for sure an update has been issued for the iBook? I too am struggling to follow the code examples where a bunch are now outdated, but I can't find any update to the iBook anywhere.

Axiem
Oct 19, 2005

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

ufarn posted:

Do we know for sure an update has been issued for the iBook? I too am struggling to follow the code examples where a bunch are now outdated, but I can't find any update to the iBook anywhere.

I had to literally delete it and re-download it to get the updated text. Though only on OSX. On iOS, I haven't been able to get the new iBook for some reason.

Axiem fucked around with this message at 20:02 on Jul 12, 2014

ljw1004
Jan 18, 2005

rum
What is AnyClass?

In WWDC talk 407 "Swift Interoperability in Depth" it lists Objective-C types and their Swift equivalents, about 6:15 minutes in...
code:
   BOOL   ...   Bool
   NSInteger  ...  Int
   SEL  ...   Selector
   id   ...   AnyObject!
   Class   ...   AnyClass!
   NSString*   ...   String!
   NSArray*   ...   AnyObject[]!
I haven't been able to find any mention of "AnyClass".

I'm also puzzled by the final line. I thought NSArray* points to an immutable array, while [AnyObject]! is mutable. I guess it wouldn't matter for parameters to Objective-C APIs. But if an Objective-C API returns an NSArray*, and the Swift caller gets back an [AnyObject]!, and the Swift caller then tries to add an item -- it seems odd!

ljw1004
Jan 18, 2005

rum
I'm having trouble with the playground. I'm following through WWDC talk 408 "swift playgrounds". By about 24 minutes in the speaker has created this code, which runs fine in my playground:

code:
import UIKit

class DataSource : NSObject, UITableViewDataSource {
    
    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let cell = UITableViewCell(style: .Default, reuseIdentifier: nil)
        cell.textLabel.text = "Text"
        if let detailTextLabel = cell.detailTextLabel { detailTextLabel.text = "subtext" }
        return cell
    }
}

let ds = DataSource()
let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 312, height: 240), style: .Plain)
tableView.dataSource = ds
tableView.reloadData()
However, when I change the final few lines to construct DataSource inline, it crashes...

code:
let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 312, height: 240), style: .Plain)
tableView.dataSource = DataSource()
tableView.reloadData()
code:
Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0x5a4d0, 0x000000010c21d00b libobjc.A.dylib`objc_msgSend + 11, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x000000010c21d00b libobjc.A.dylib`objc_msgSend + 11
    frame #1: 0x000000010dc48ba4 UIKit`-[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 2414
    frame #2: 0x000000010dc4cad3 UIKit`-[UITableViewRowData numberOfRows] + 97
    frame #3: 0x000000010dabeac8 UIKit`-[UITableView noteNumberOfRowsChanged] + 131
    frame #4: 0x000000010dabe213 UIKit`-[UITableView reloadData] + 1303
Am I doing something wrong, or is it a bug in Playground?



One random guess was that tableView.dataSource is only a weak reference, so my instance of DataSource is being collected before it's ready. But this guess was wrong: command-clicking on dataSource shows it to be a normal (strong) reference.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
It's odd that it would report it as a strong reference because datasources, delegates, and action targets are all documented to be weak references:

https://developer.apple.com/library...ataSources.html

quote:

As with delegates, data sources are objects that must be present to receive messages from the objects requesting data. The application that uses them must ensure their persistence, retaining them if necessary in memory-managed code.

ljw1004
Jan 18, 2005

rum

Flobbster posted:

It's odd that it would report it as a strong reference because datasources, delegates, and action targets are all documented to be weak references

I see. Thanks. I might have been misunderstanding... when I command-clicked on dataSource it showed it like this:

code:
class UITableView : UIScrollView, NSCoding {
    ... 
    var dataSource: UITableViewDataSource!
    ...
I had thought that all references in Swift are strong unless they have the "weak" or "unowned" modifiers on them. Maybe the "view-ObjectiveC-as-Swift" feature doesn't yet display weak/unowned?

ljw1004
Jan 18, 2005

rum
I stumbled on a "gotcha" with integer literals... In the WWDC "swift playgrounds" talk at about 27:30 it shows this code:
code:
data.append(Int(arc4random()) % 100)
The "Int" type, like in C++, is either Int32 or Int64 depending on your target. Now arc4random returns unsigned ints in the range 0 ..< 0x100000000 - the above code will therefore produce positive and negative numbers on iPhone4, and only positive numbers on 64bit iPhone5 apps.

It seems like pretty bad practice!

In addition, it seems that the compiler's out-of-bounds errors only ever report errors as if Int were an "Int64". (This might have something to do with my project's build targets, but even when I set the sole valid architecture to "armv7" it still reported errors as if Int were an Int64). Also, the playground only ever seems to operate as 64bit.

code:
let a = 4294967290         // 32bit = -6, 64bit = 4294967290
let b = 4294967296         // 32bit =  0, 64bit = 4294967296
let c = 0x00000000FFFFFFFF // 32bit = -1, 64bit = 4294967295
let d = 0x000000AAFFFFFFFF // 32bit = -1, 64bit = 734439407615
let e = 0x0FFFFFFFFFFFFFFF // 32bit = -1, 64bit = 1152921504606846975
It gets even more odd... I can't convert an Int32 to Int, even thought the conversion is guaranteed to always be safe!

code:
let a = Int(arc4random())  // happily reinterpret uint as int
let b:Int = Int32(5)  // error: Int32 is not convertible to Int

ljw1004 fucked around with this message at 04:31 on Jul 15, 2014

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
I might have missed this somewhere along the way, but if I wanted to refer to a closure (/function) in the type of a generic declaration, what type do I use?

In other words, I want to do:

code:
class thingOfClosures<T: Closure> {
    ...
}
But they're not called "Closure" or "Function" or anything else that I can find. Any ideas, or is this not something I can do yet?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I don't understand. You have a generic type parameter, and you want to constrain it to always be a function type? That's not expressible. You could have the class be generic over two types, T and U, and then use the function type T->U within the declaration, though.

All functions with the same signature have the same type, though. Any closure information is erased.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
What would Closure even be? An empty protocol? To be able to call it you'd need to know the function's signature, and there's only one type for each signature.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

ljw1004 posted:

What is AnyClass?

It's a type which can hold a reference to any class type, like ObjC's Class type. Swift usually has better-typed alternatives, though.

ljw1004 posted:

I'm also puzzled by the final line. I thought NSArray* points to an immutable array, while [AnyObject]! is mutable. I guess it wouldn't matter for parameters to Objective-C APIs. But if an Objective-C API returns an NSArray*, and the Swift caller gets back an [AnyObject]!, and the Swift caller then tries to add an item -- it seems odd!

A Swift array is a value, like an Int. You can't directly add an item to an array result of a call, the same way that you can't directly ++ an Int result of a call; you can store values to your own variables and then change them there, but logically that means changing your own copy of the value.

This is a subtle point that's worth spending more time reading about. It does not work the way you're used to from ObjC, where NSArray and NSDictionary are reference types, and your intuitions will get you confused until you make an effort to really understand the model.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer
Speaking of arc4random, is there any plan for standard library functionality re: random numbers? arc4random being 32-bit in a 64-bit environment isn't great to start with, and the unsafe pointers stuff is kinda/intentionally gross but necessary when you're using arc4random_buf to get a bunch of random values.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

ljw1004 posted:

I see. Thanks. I might have been misunderstanding... when I command-clicked on dataSource it showed it like this:

code:

class UITableView : UIScrollView, NSCoding {
    ... 
    var dataSource: UITableViewDataSource!
    ...

I had thought that all references in Swift are strong unless they have the "weak" or "unowned" modifiers on them. Maybe the "view-ObjectiveC-as-Swift" feature doesn't yet display weak/unowned?

This is worth filing as a couple of bugs. The first bug is that, yes, viewing this as Swift should show it as unowned(unsafe). The second is that Swift should be able to warn you that you're obviously doing nothing with an object you just allocated except storing it to a non-strong reference.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

ultramiraculous posted:

Speaking of arc4random, is there any plan for standard library functionality re: random numbers? arc4random being 32-bit in a 64-bit environment isn't great to start with, and the unsafe pointers stuff is kinda/intentionally gross but necessary when you're using arc4random_buf to get a bunch of random values.

It's an obvious thing to improve, but there are a lot of more important things to do first.

Axiem
Oct 19, 2005

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

rjmccall posted:

You could have the class be generic over two types, T and U, and then use the function type T->U within the declaration, though.

I think this more or less answers my question, which is to say it's not possible.

The context is that I'd like to build essentially a dictionary of Strings to Closures, to implement the...I think it's a Visitor pattern?

Let's call this thing a VisitDictionary. A class (say, Alice) builds an instance of VisitDictionary<(Bob)->()>. Then Alice exposes a method whenCallSchoolRun((Bob)->()), which will take the (Bob)->() closure and add it to the VisitDictionary (the String being used for reference later in case it needs to be taken out of the dictionary).

Later, an Alice will end up doing a callSchool, and then wants to tell the VisitDictionary "hey, all of those closures you have, run them please" as a way of notifying objects interested in when Alice "calls school". It would also be awesome if Alice could tell the VisitDictionary "and please use this Bob I have here", but I don't know how feasible that is sans serious reflection.

Of course, that closure that a VisitDictionary is built with could be ()->() or (Bob, Carol)->(), or so on. But within the VisitDictionary, I wonder if it's possible to call that closure (hence the passing-in of Bob), instead of relying on Alice to call each closure. But that would clearly only be possible if I could constrain VisitDictionary<T> to only allow closures as T's.

Right now I have this more or less written out, except the "run these closures" is a method that takes a closure that actually calls each closure. It might be that's the best I can do, though still expressing in the VisitDictionary that it only wants to store closures and not other things (like arrays) would be nice from a semantic perspective.

...this is probably a completely inverted way of describing the reasoning behind how this came about. Let me approach from the other direction.

I mentioned off-handedly in the Apple dev thread that in Swift, I've been implementing an Observer pattern using closures. Alice will expose (I say despite the lack of private methods) a method whenCallSchoolRuns((Bob)->()). What I've been doing is just keeping those in an Array<(Bob)->()>, and when callSchool runs, I loop through that array and call each closure. That way, if a Deborah is interested in when an Alice calls the school, that Deborah can do:

code:
myAlice.whenCallSchoolRuns {myBob in
   myBob.tellToMowTheLawn()
   self.addToMessageBook(myBob)
}
And therefore a Deborah can observe an Alice.

The problem with this is that once Deborah is observing an Alice, there's no easy way for Deborah to stop observing that Alice. Hence, the Token idea. Whenever you call whenCallSchoolRuns, it'll pass you back a token, so if you want to stop observing, you just call like noLongerWhenCallSchoolRuns(token) and given that token, it can eliminate the closure from the now-Dictionary (to map the token to the closure)

But instead of repeating the boiler-plate code for generating the tokens (at the moment, a UUID, but it could be anything) or iterating through all of the values of the now-Dictionary, it would be nice to pull that out into a separate class that took care of some of that stuff (and was therefore testable as its own unit).

Hence where I'm at. I'm able to make a VisitDictionary<T>, but still to actually call each of those closures, the Alice has to do something like this:

code:
func callSchoolRan{ callSchoolRunsObservers.each { observer in observer(myBob) } }
And I'd rather shuttle that code into the VisitDictionary to avoid duplication.

For reference, the way the VisitDictionary is doing that at the moment (myDict is a Dictionary<String, T>):

code:
func each(visitor: (T)->()) { for thing in myDict.values { visitor(thing) } }
And really, I'm probably asking for my cake and wanting to eat it, too, and it's late enough here that I've probably gone a little crazy in what I want to do. But with the grand majority of my observer closures being of the ()->() type (enough so that I've typealiased it), it would be really nice if in the VisitDictionary, I could:

code:
func callEach() { for thing in myDict.values { thing() } }
Though I admit I don't know what that would look like when it needed to pass things to each of those closures.

And it's late enough I'm probably also getting incoherent (and likely screwing up the differences between closures, functions, and methods). Hopefully that made sense.

Axiem fucked around with this message at 05:55 on Jul 15, 2014

Adbot
ADBOT LOVES YOU

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

rjmccall posted:

It's an obvious thing to improve, but there are a lot of more important things to do first.

Yeah, that sounds reasonable to me. I threw up rdar://17674726 as a follow up.

  • Locked thread