5 ms·
Swift tries to be a jack of all trades, but I think as a scripting language (as in this example) it falls short. Having to start a run loop, write asynchronous
by rgovostes 8y ago
Swift tries to be a jack of all trades, but I think as a scripting language (as in this example) it falls short. Having to start a run loop, write asynchronous callbacks (completion handlers), and implement custom JSON decoders just to make a web request is introducing a ton of complexity that might make sense in an event-driven interactive GUI application, but not so much in a quick shell script.
Swift tools might be a good choice for use cases where you need to integrate with an existing Swift project, or if you need lower level APIs.
In this example, a Bash script would have been almost done by the time you worked out the `curl | jq` command. But in other similar cases I would suggest Python Requests, which will take perhaps 10% as much code and avoid issues of Linux compatibility and mistakes like forgetting to call `resume()` on your download task or `exit()` in some branch (there are five calls just to keep the program from looping forever).
That said, I think this blog post is very informative and well-made for a beginner interested in talking to a web-based JSON API from Swift.
- delinka 8y agoSwift as a (shell) scripting language has been terrible for me. To get us to Swift shell scripting, I think what's needed is the "syntax" for calling out to other executables directly instead of wrapping it in a task. Of course, plumbing follows immediately and I don't know if we can keep the shell plumbing syntax in a Swift environment.
- jph00 8y agoThat should be doable with a library, right? Is there any need for language syntax for this?
- jabl 8y agoIf all you're doing is calling external processes, well, it's hard to beat the shell piping syntax. The problem is of course that as the complexity of the script grows, the absolute dreadfulness of actual programming in the shell rears its ugly head. I haven't really found a good compromise here myself.
- delinka 8y agoFor the plumbing, maybe a library (of operator overloads) is all that's needed. For calling out to executables like a script (i.e. just put the exe name inline as if it were another symbol), you'd need first-class language support.
- rgovostes 8y agoI don't see that working very well. If you ever made a typo in a function name, the compiler would have to assume that you are referring to an external tool that would be available at runtime. Swift gives the programmer a lot of flexibility in overriding operators, though, so one could probably make a decent DSL that approximates shell syntax.
- delinka 8y agoFor scripts, you're not compiling an executable that you'll run later, you're having Swift execute the code "now" so "available at runtime" becomes "immadiately after you parse the code."
- terhechte 8y agoThe tricky part is that it is impossible to import any libraries in a script except: - The official libraries that ship with Swift - If you create a full-blown Swift package manager project and compile an executable. But this doesn't sound like a script anymore - If you use John Sundell's Marathon [https://github.com/JohnSundell/Marathon https://github.com/JohnSundell/Marathon] however it adds additional complexity around the writing of scripts I.e. none of the solutions are as simple as writing a bash script Edit: Just saw that Max Howell (creator of Homebrew) released this today https://github.com/mxcl/swift-sh https://github.com/mxcl/swift-sh This absolutely solves the issues. Fantastic.
- wool_gather 8y agoswift-sh definitely bears looking into, thanks for that!
- helge5 8y agoLike this? http://www.alwaysrightinstitute.com/swift-dynamic-callable/ http://www.alwaysrightinstitute.com/swift-dynamic-callable/
- jph00 8y agoSwift's APIs tend on the verbose side, but they can be wrapped up into much more concise versions. Since few people have been using Swift in this way, those wrappers haven't really appeared yet (and because Swift packaging is still in such poor shape) but it will come - just like the "requests" library made http so much more concise and easy in Python. The obvious question, of course, is: why bother? The answer is that this code runs at about the same speed as C. So if you're doing data munging of a big file, this is a really interesting approach. For data scientists, I think there is a lot of opportunity here.
- yxhuvud 8y agoBut then you might as well use Crystal instead, which already have scripting language usability while retaining the performance. I like the idea of swift and I want to like it, but everytime I look at APIs it seems they dropped the ball.
- coldtea 8y ago>But then you might as well use Crystal instead, which already have scripting language usability while retaining the performance. Without the libraries, documentation, maturity, and major support.
- yxhuvud 8y agoWell, assuming the plan is to run the program on something that is a server, the same basically holds true for swift as well. There simply isn't enough people using it for server stuff yet for it to have become battle proofed. But yes, if the plan is to run it locally on a mac, then your objection certainly hold.
- the_gipsy 8y agoExcuse me but swift libraries plain suck, because of the bad package management. Documentation is also poor and mostly “look at the example, tests, or source”.
- jabl 8y agoI'm bullish on the trend(?) to implement tools in languages like Rust, Go (and maybe Swift like in this article, although I'm not familiar with it, and it seems mostly unheard-of here in Linuxland). Being able to just deploy a binary with minimal dependencies (yes, I did read the article, but I'm assuming with swift you can also create a static binary) makes it a lot easier to get started than requiring the user to setup some virtualenv for python. And while not relevant in this particular case, native binaries are fast, and launch quickly as well.
- saagarjha 8y ago> I'm assuming with swift you can also create a static binary This is not possible yet, unfortunately: https://bugs.swift.org/browse/SR-648 https://bugs.swift.org/browse/SR-648
- BooneJS 8y agoIf you've got a mature, all-encompassing build flow (hierarchical Makefiles, Bazel, etc), then ensuring a required tool is up to date after a pull is very straightforward. The weaker your build system, the more you really depend on tools being interpreted scripts so they "just work".
- DeusExMachina 8y agoAs developer that does not know how to write Bash scripts at all but is well versed in Swift, if I have to write such a tool, I'd rather use such "suboptimal" option than have to learn a new language. It also has the advantage that, if later this solution needs to grow past a simple command line tool, I can just grab the Swift code from the script, put it in an Xcode project, and make a Mac app out of it.
- wool_gather 8y agoIt takes a while, like anything, to get comfortable with shell scripts, but it's absolutely a tool that every programmer should have basic familiarity with. It's universal glue. And in the domains where shell is a good choice, it's a far far better choice than Swift. Maybe that will change, but I doubt it. I've implemented a couple of medium-small tools over the last two years and as an exercise did them in both shell and Swift. The shell versions are simpler, more maintainable, and more robust than the Swift versions. Swift's verbose "correctness" is not an asset in the domain(s) where scripting is useful. Gluing programs together is one. Frankly, text processing is another. An invocation of sed with a simple regex becomes a monstrosity when translated to Swift. The less code you write, the less you have to maintain.
- saagarjha 8y ago> An invocation of sed with a simple regex becomes a monstrosity when translated to Swift. This is because Swift’s regex support is overly verbose, being lifted straight from Objective-C. It’s not an inherent problem when the language.
- bexsella 8y agoAgreed, along with basic familiarity with vi/vim this is almost required knowledge if you're deploying to or working on a system other than Windows or MacOS.
- wool_gather 8y agoIt definitely applies to Mac as well; it's got a full complement of BSD command line goodies.
- coldtea 8y ago>Swift tries to be a jack of all trades, but I think as a scripting language (as in this example) it falls short. Having to start a run loop, write asynchronous callbacks (completion handlers), and implement custom JSON decoders just to make a web request is introducing a ton of complexity that might make sense in an event-driven interactive GUI application, but not so much in a quick shell script. Well, you don't need to do any of those. You could make a synchronous web request. And you could decode JSON into a representation, instead of pre-creating a struct with the exact result.
- coldtea 8y agointo a representation -> into a generic representation
- the_gipsy 8y agoA generic representation I guess means primitives, dictionaries and arrays. Stringly typed.
- coldtea 8y agoNo -- "primitives, dictionaries, and arrays" typed, which is different from "stringly typed", and representative of what JSON actually is. JSON doesn't represent class hierarchies, but plain nested JS objects. And the types it supports are just dictionary, array, string, boolean, and float. So having all the ceremony in Swift (or similar in Go, etc) to parse into predefined structs is not really idiomatic to JSON. You can have all of those in the generic representation -- and this is exactly how any dynamic language does it (JS, Python, PHP, etc.) -- and any statically typed language when it wants to read arbitrary JSON.
- the_gipsy 8y agoJSON does not represent class hierarchies, but neither dictionaries. It represent structures, 99% of the time the exact shape and format is public. Parsing JSON into predefined structs is indeed very idiomatic. A dictionary is a key/value map, period. If you want to use that, because you don't want to do the encode/decode ceremony, then you are doing stringly-typed code in a statically typed language. This is not bad per-se, as you say dynamic languages always do this, but you should recognize what you are doing.
- josephg 8y agoI totally agree. I was curious how much typing overhead there is in the swift version so ported that blog post's code into nodejs. In node, the whole thing comes in under 30 lines with comments. (Compared with 86 lines in the final version from that blog post). https://gist.github.com/josephg/469ddbe71b7c515247b0db801325c511 https://gist.github.com/josephg/469ddbe71b7c515247b0db801325... The reality is you always have to do more work to interact with JSON data from a static language because you need to tell the compiler what type everything will be. The benefit you get from doing that can pay off in larger projects, but for quick and dirty scripts its a lot of wasted effort.