sorry for the rant, but i was recently writing some python scripts, and had to fill in the swift-side parts, and i’m becoming aware of just how much less productive i am using SystemPackage
’s APIs, compared to os.path
.
put simply, FilePath
is just too safe. the amount of boilerplate needed for the simplest operations just feels excessive. it’s like String
indexing, but taken to an extreme.
to walk through an example of a simple task that’s way over-complicated by FilePath
, i had a text file with a list of directories, one on each line:
directories.txt
foo
bar
baz
i read the file contents, and split on newlines, to get an array of [Substring]
:
func loadDirectoryList(from path:FilePath) throws -> [Substring]
{
try self.read(from: path).split(whereSeparator: \.isWhitespace)
}
next, i try to iterate over the list of directories, constructing a relative path with each directory as the last path component:
for directory:Substring in loadDirectoryList(
from: .init(root: nil, components: "workspace", "directories.txt"))
{
let directory:FilePath =
.init(root: nil, components: "workspace", .init(String.init(directory)))
}
first, why do i have to write root: nil
to get a relative path? why can’t there just be a static constructor like .relative("workspace", "directories.txt")
?
second, why do i have to copy directory:Substring
to a String
in order to construct a FilePath.Component
? why can’t it just take some StringProtocol
like everything else?
finally, it doesn’t even compile, because FilePath.Component.init(_:)
is failable:
error: value of optional type 'FilePath.Component?' must be unwrapped
to a value of type 'FilePath.Component'
at the same time, FilePath.Component
is ExpressibleByStringLiteral
, which strikes me as inconsistent. if i want to refactor say the "workspace"
directory into something configurable, i can’t just drop in a .init(workspaceName)
, since that would become optional.
pretty much all of this feels completely pointless to me. the text file will never contain empty lines or '/'
characters, and nobody besides SystemPackage
accepts FilePath
anyway, they would all inevitably be converted back into String
. for example, all of SwiftNIO’s file-based APIs take String
, not FilePath
.