Re: [swift-corelibs-dev] [swift-evolution] Proposal: Conforming NSDate to Comparable

2015-12-05 Thread Brent Royal-Gordon via swift-corelibs-dev
> I think it's a good idea to conform NSDate to the Comparable protocol, so 
> instead of using:
> 
> if someDate.compare(today) == .OrderedAscending { }
> 
> Developers can easily compare using compare dates using comparison operators:
> 
> if someDate < today { }

I would also suggest we add Strideable, which would allow you to add and 
subtract NSTimeIntervals, plus subtract two NSDates to get the NSTimeInterval 
between them.

https://gist.github.com/brentdax/11b3275424d0833cfd99

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] [swift-evolution] Proposal: Conforming NSDate to Comparable

2015-12-05 Thread Brent Royal-Gordon via swift-corelibs-dev
> NSDate (and dates/timestamps in general) is a poor choice for Strideable, 
> because, DST.
> A Calendar using this interface for a repeating event would be broken using 
> this. Or you would break anyone who really wants to iterate every fixed 86400 
> seconds.

Sometimes you want to add an interval of time according to the user’s clock; 
NSTimeInterval/NSDate math will do the wrong thing there. But sometimes you 
just want to get an NSDate thirty seconds from now, and for all you care the 
user can fly to Timbuktu during that time. That’s the sort of thing I’m using 
this for:

// Don’t add to undo manager if we’re too close to the last change
guard now - lastChangeDate > undoCoalescingTimespan else { return } 

It is simply not the case that *all* arithmetic on NSDates is incorrect unless 
it involves NSCalendar and NSDateComponents.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] NSAttributedString attributesAtIndex return an optional.

2015-12-08 Thread Brent Royal-Gordon via swift-corelibs-dev
> Been playing around with NSAttributedString and cannot decide on the best way 
> to implement the (attributesAtIndex: effectiveRange) and other methods with 
> similar functionality.
> 
> In the ObjC world I would expect an empty NSDictionary even in cases where 
> the location is greater than the length of the string.

Personally, if I indexed past the end of an attributed string, I would expect a 
precondition to fail and (since Swift can't catch assertion failures) my app to 
crash. (And from what I can tell, the Apple Foundation versions of these APIs 
do not return an optional.)

(Sorry about the duplicate, James—didn’t hit Reply All when I should have.)

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] NSAttributedString attributesAtIndex return an optional.

2015-12-08 Thread Brent Royal-Gordon via swift-corelibs-dev
> This may be better for the swift-evolution list, but I really do not like the 
> fact that subscripting is a "hard" error. I think the language should have as 
> little hard errors as possible to improve on how much the compiler can check 
> for you.

I think the idea is that, if you’re subscripting incorrectly, chances are you 
didn’t anticipate the possibility that your subscript might fail and probably 
didn’t write code that’s prepared to handle that error. If you did anticipate 
that possibility, you would have made sure there was a range check in the first 
place.

Ultimately, since Swift.org Foundation is meant to present the same interface 
as Apple Foundation, I don’t think we have much of a choice about this anyway. 
Apple Foundation’s version of this method is non-optional and non-throwing. If 
we deviate from that, we lose compatibility.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] NSDecimal & NSDecimalNumber

2015-12-11 Thread Brent Royal-Gordon via swift-corelibs-dev
> This may be better suited to swift-evolution or users list, but regarding 
> fatalError do you have any techniques for testing this behavior?

I believe the Swift compiler’s tests run code it expects to trap in a separate 
process and verify that the other process trapped. We may want to think about 
extending XCTest in some way to offer this behavior.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] KVC dependent classes

2016-03-19 Thread Brent Royal-Gordon via swift-corelibs-dev
> Sorry, I said NSProgress but I meant NSPredicate. I personally can't even 
> imagine what a alternative API for NSPredicate would look like 🤔

Use reflection.

Match against only dictionaries with string keys.

Match against only objects conforming to some dictionary-with-string-keys-like 
protocol.

Match against only objects conforming to an NSKeyValueCoding protocol with a 
`value(forKey:)` requirement.

Don't actually implement matching; just use it as an abstraction for things 
like CloudKit and Core Data.

There are options.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] [swift-users] String manipulation (replacingOccurrences) in Linux swift

2016-05-26 Thread Brent Royal-Gordon via swift-corelibs-dev
> #if os(Linux)
> print("Let's change those carriage returns...")
> processedString = string.replacingOccurrences(of: "\r\n", with: 
> "\n")
> #else
> processedString = string.replacingOccurrences(of: "\r\n", with: 
> "\n")
> #endif
> And it compiles flawlessly in linux, but when it’s time to execute, it throws 
> an error message like:
> Let's change those carriage returns...
> Illegal instruction (core dumped)

I don't have a Swift on Linux box, so I can't really run Corelibs Foundation 
myself. But looking at the source code 
,
 I'm not sure that it will behave correctly when you replace a string with a 
differently-sized string and .backwardsSearch is not set. Maybe there's 
something I'm missing, but it looks to me like each replacement will shift the 
characters in the string, but the ranges won't move with them. The replacements 
will miss their targets more and more, and eventually—if the replacement is 
shorter than the original and one of the matches is near enough to the end—they 
might run past the end of the string.

Carlos: Try passing `options: .backwardsSearch` to `replacingOccurrences`. If 
I'm right about this being a bug, doing that should work around it, and you 
ought not to notice any difference in your code's behavior. (This is not 
something you should have necessarily figured out yourself; you haven't missed 
anything obvious.)

swift-corelibs-dev (who I've cc'd on this thread): Am I correct that this is a 
bug? Should it be/has it been filed? (A quick-and-dirty search of the bug 
tracker seems to indicate it hasn't been, but I don't have that much experience 
with it.)

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Foundation Renaming Question

2016-07-03 Thread Brent Royal-Gordon via swift-corelibs-dev
> In the past bare strings were acceptable for postNotificationName and 
> addObserverForName.  Yet now constructing a Notification and 
> Notification.Name seem to be a bit unwieldy.  Example:
> 
> let ConnectedNotification= 
> Notification(name:Notification.Name(rawValue:"ConnectedNotification"))
> 
> That seems to be quite convoluted and I'm not sure why there isn't a 
> convenience init that allows for
> 
> let ConnectedNotification= Notification(name:"ConnectedNotification")

You're running into trouble because you're not following the typical pattern 
for these types. The intended usage is:

* You assign the Notification.Name to a constant.

class ChatConnection {
static let didConnect = 
Notification.Name("ChatConnection.didConnect")
…
}

* You create Notification instances on demand, or preferably let the 
NotificationCenter make them for you.

extension ChatConnection {
func connectionCompleted() {
NotificationCenter.default().post(name: 
ChatConnection.didConnect, object: self)
}
}

Individual Notifications are meant to be one-off instances. If you follow this 
pattern, you'll find that the API design suddenly makes a lot more sense!

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Swift Shims

2016-08-03 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Aug 3, 2016, at 8:39 PM, Fernando Rodríguez via swift-corelibs-dev 
>  wrote:
> 
> I'm having some trouble  understanding what on Earth SwiftShims are. The name 
> probably makes it obvious to native English speakers, but it's not helping 
> me...
> 
> Could someone please enlighten me?

"Shim" is a relatively common programming term; it means a lightweight 
compatibility layer which corrects for differences between platforms. For 
instance, if you're supporting three different OSes with three different random 
number calls, you might write a `randomNumber()` shim function which calls 
whichever one is correct for that platform.

(Outside of programming, a "shim" is a thin piece of material, often wood, 
which you put under the leg of a piece of furniture if it's crooked or wobbly.)

SwiftShims specifically contains functions written in C, C++, or Objective-C++ 
which the Swift standard library's internals need to call. These functions 
often translate the parameter types of calls into forms which are easier to 
call from Swift, or fill in functionality that's missing on certain platforms. 
For instance, the I/O in the standard library's `readLine()` function is 
handled by a C++ function called `swift_stdlib_readLine_stdin()`. That function 
is part of SwiftShims; on most platforms, it calls through to a C standard 
library `getline()` function, but on a few it emulates that function's behavior.

Unless you're working on the standard library (or Foundation, which I believe 
uses a couple of SwiftShims calls), you shouldn't ever interact with or care 
about SwiftShims. It's a private implementation detail of Swift.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Asynchronous Operations

2017-01-21 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Jan 20, 2017, at 7:55 AM, Ian Partridge via swift-corelibs-dev 
>  wrote:
> 
> Is there any way that we could support asynchronous operations in 
> swift-corelibs-foundation, in the absence of KVO?

Could we add `willChangeValue(forKey:)` and `didChangeValue(forKey:)` methods 
just to `Operation` which only handle an `isFinished` key? Presumably they'd 
just look like:

public func willChangeValue(forKey key: String) {
// do nothing
}
public func didChangeValue(forKey key: String) {
if key == "isFinished" && isFinished {
finish()
}
}

I believe that would make existing code just work without needing to do 
anything special.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Cancelable DispatchQueue.concurrentPerform

2017-02-24 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Feb 23, 2017, at 8:35 AM, Karl Wagner via swift-corelibs-dev 
>  wrote:
> 
> Would it be possible to make a cancelable version of 
> DispatchQueue.concurrentPerform, allowing you to abort any 
> yet-to-be-scheduled blocks?
> 
> The use-case is for when you’re concurrently performing a job and one of them 
> sets a flag or fails in a way which already defines the result. Further 
> execution wouldn’t affect the outcome, so it would be nice if an operation 
> could flag back to concurrentPerform that it doesn’t have to schedule any 
> more jobs.
> 
> For a real-world example, see this concurrent RandomAccessCollection wrapper 
> I was building: https://gist.github.com/karwa/43ae838809cc68d317003f2885c71572

Your example is:


var _error: Error?
DispatchQueue.concurrentPerform(iterations: numericCast(count)) {
  do{ try body($0)   }
  catch { _error = error } // TODO: lock. Would be cool if we could cancel 
future iterations, too...
}
if let error = _error {
  try rescue(error)
}

So how would cancelability be superior to saying this?

var _error: Error?
DispatchQueue.concurrentPerform(iterations: numericCast(count)) {
  guard _error == nil else { return }
  do{ try body($0)   }
  catch { _error = error } // TODO: lock. Would be cool if we could cancel 
future iterations, too...
}
if let error = _error {
  try rescue(error)
}

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Bring NSString functions to String

2017-05-10 Thread Brent Royal-Gordon via swift-corelibs-dev
> On May 8, 2017, at 9:39 AM, Eric Blachère via swift-corelibs-dev 
>  wrote:
> 
> I was just wondering if there are plans to bring NSString functions 
> manipulating paths into the native String class. (such as lastPathComponent, 
> pathComponents etc...)
> Because even if we can always make an extension of String to easily cast it 
> into NSString, it's still a bit of a shame to have to do it ;) 

Unfortunately, it seems like the decision not to include these methods on 
String was quite deliberate.

Here's the revision where that happened: 

 As you can see, they had that working and chose to disable it, presumably 
because they want you to manipulate paths through `URL`. (I wish the radar 
referenced in the commit message were public, but alas, it's not.)

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-17 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Nov 17, 2017, at 11:34 AM, Tony Parker via swift-corelibs-dev 
>  wrote:
> 
> It does seem like there is a possibility of some better convenience API here.
> 
> Any ideas on what form it would take? A class method on Process that returns 
> the output, maybe?

`Process.run(_:arguments:terminationHandler:)` is not a bad basis for this, 
other than the first argument being a URL. I might add a variant which does a 
$PATH search and expands tildes:

extension Process {
class func runInPath(_ commandName: String, with arguments: 
[String], terminationHandler: ((Process) -> Void)? = nil) -> Process
}

(I would *not* add a variant which simply shells out, or at least I wouldn't 
make it the only option. Every scripting language I can think of has this 
feature, and every one of them discourages its use and pushes people towards 
something else with pre-split arguments and no shell attack surface.)

And then add a method which gathers all stdout output and returns it, along 
with the termination status (throwing if it's a signal):

extension Process {
func outputAfterExit() throws -> (output: String, status: Int32)
}

The result is not *as* convenient as PHP, but it's a lot safe than running 
things through a shell, too.

let (output, _) = try Task.runInPath("find", with: ["~/Desktop", 
"-name", "*.png"]).outputAfterExit()

The biggest problem I see with this design is that expanding tildes in the 
arguments, but *not* globbing them, happens to be right for this case, but may 
not be in the general case. One interesting possibility would be to go the 
custom operator route:

/// Returns an absolute path placing `relativePath` in the user's home 
directory.
prefix func ~ (relativePath: String) -> String {
return 
FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(relativePath).path
}

let (output, _) = try Task.runInPath("find", with: [~"Desktop", 
"-name", "*.png"]).outputAfterExit()

But I'm not sure we'd want that available in million-line Mac apps.

On the other hand, maybe Foundation's APIs in general are too verbose for 
scripting. I could imagine a "Foundation.Script" module which added some 
unprincipled but convenient shortcuts:

extension URL: ExpressibleByStringLiteral { // Should be 
interpolatable too, but we need to redesign that.
public init(stringLiteral value: String) {
self.init(fileURLWithPath: value)
}
}
public var FS { return FileManager.default }
public var ENV { return ProcessInfo.processInfo.environment }

That might be a good place for a leading tilde operator, too.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-19 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Nov 19, 2017, at 7:01 PM, Abhi Beckert  wrote:
> 
> First of all, I disagree with Brent's assessment that we shouldn't have a 
> variant that "simply shells out". Even though this use case is "discouraged" 
> in other languages, I think in practice it definitely has a place.

If you really want to do this, you can do it through the array-based API by 
calling `sh` with the arguments `["-c", yourCommand]`. This makes it slightly 
less convenient than the safe API, which is a *feature*, because we want people 
to reach for the safer API.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-27 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Nov 27, 2017, at 3:50 PM, Tony Parker via swift-corelibs-dev 
>  wrote:
> 
> I was thinking of perhaps a completion handler version, with the expectation 
> that once async/await style completions land it would be pretty easy to use 
> in a kind of straight-line mechanism.

A completion handler only makes sense if we're running under the control of a 
runloop. We aren't today, and I don't believe the most recent async/await stuff 
I've seen included mechanisms to start a runloop if needed.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-27 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Nov 27, 2017, at 11:01 PM, Brent Royal-Gordon  
> wrote:
> 
> We aren't today


Sorry, this part of the sentence got mangled in editing. What I meant to say 
is, script-style programs currently don't run under a runloop, so if this API 
is being designed for scripting use, a completion handler—even with 
async/await—might not be the right design.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


Re: [swift-corelibs-dev] Better integration with UNIX tools

2017-11-28 Thread Brent Royal-Gordon via swift-corelibs-dev
> On Nov 28, 2017, at 8:00 AM, Tony Parker  wrote:
> 
> Why does it imply a run loop rather than one of many multithreading 
> possibilities (dispatch queue, starting one more thread, etc)? And even if it 
> did use run loops, why is that a problem?


The problem is simply that we're discussing using this feature in Swift 
*scripts*. Swift scripts don't typically invoke `RunLoop.run()` or 
`dispatch_main()`, and without changing the way they generate main() functions 
to intrinsically do so (and then schedule main.swift's body on the main 
runloop/queue), I don't see a good way for it to do so. So an async API would 
be inconvenient to use from a Swift script.

-- 
Brent Royal-Gordon
Architechies

___
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev