{"id":21633755,"url":"https://github.com/dgroomes/swift-playground","last_synced_at":"2026-07-22T06:31:56.991Z","repository":{"id":146628147,"uuid":"519865307","full_name":"dgroomes/swift-playground","owner":"dgroomes","description":"📚 Learning and exploring the Swift programming language","archived":false,"fork":false,"pushed_at":"2025-02-12T03:39:47.000Z","size":634,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-03T23:50:05.221Z","etag":null,"topics":["swift","swift-concurrency"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dgroomes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-31T19:10:42.000Z","updated_at":"2025-02-12T03:39:50.000Z","dependencies_parsed_at":"2025-02-12T04:27:11.414Z","dependency_job_id":"8171c90a-779c-4550-a337-053cff405c6e","html_url":"https://github.com/dgroomes/swift-playground","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dgroomes/swift-playground","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroomes%2Fswift-playground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroomes%2Fswift-playground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroomes%2Fswift-playground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroomes%2Fswift-playground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dgroomes","download_url":"https://codeload.github.com/dgroomes/swift-playground/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroomes%2Fswift-playground/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266602783,"owners_count":23954694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["swift","swift-concurrency"],"created_at":"2024-11-25T03:13:43.272Z","updated_at":"2025-10-12T09:02:51.237Z","avatar_url":"https://github.com/dgroomes.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# swift-playground\n\n📚 Learning and exploring the Swift programming language.\n\n\u003e Swift. The powerful programming language that is also easy to learn.\n\u003e\n\u003e -- \u003ccite\u003ehttps://developer.apple.com/swift\u003c/cite\u003e\n\n\n## Description\n\n**NOTE**: This project was developed on macOS. It is for my own personal use.\n\nThis project is for me to explore the Swift programming language, which is quite rich and at times difficult for me to\nwrangle. By contrast, my codebase \u003chttps://github.com/dgroomes/macos-playground\u003e is designed to explore macOS platform\nAPIs and macOS operating system concerns like process management. \n\nThis project is implemented as a multi-module Swift project. I use the term \"multi-module\" in the general programming\nsense. Programming languages and their toolchains use specific language to describe modular program design. Swift programs\nbuilt with the Swift Package Manager have an impressive amount of options when it comes to modularity. Just read the later\nsection [Making Sense of the Swift Package Manager](#making-sense-of-the-swift-package-manager).\n\n\n## Xcode Notes\n\nThis project is a good fit for me to learn Xcode and take some notes. While Swift doesn't necessarily need to be\ndeveloped in Xcode, nor does it even need to be developed on a Mac or even target an Apple system, I'm doing the\nmainstream thing and using Xcode. But I'm a newbie at Xcode. I'd like at least to understand the basics of the \"power\ntools\" when it comes to using Xcode. I want the familiar leverage of Intellij features like \"Search everywhere\",\nback/forward controls, \"go to implementation\", \"refactor/rename\". The big ones.\n\nHere are some miscellaneous notes/observations:\n\n* Xcode's markdown smarts doesn't parse/recognize code fences on the first line of a bullet point or numbered bullet.\n  It makes all the text below it gray. It looks like a workaround is to keep the contents of the first line empty and\n  and put the code fence on the next line. This seems like it's still legal markdown syntax because I see the numbers\n  render when I use a markdown renderer (and strangely, can't get Xcode to show a markdown render/preview? it's stuck in\n  a source code mode)\n* I can't use refactorings, they were greyed out. I had to resort to the tacky \"delete internal files\" trick and\n  thank you very much to [this StackOverflow Q\u0026A](https://stackoverflow.com/a/47425586). To be fair, I have to do stuff\n  like that in Intellij too, so it's normal, although it's a head scratcher. UPDATE: it's grayed out again.. so\n  frustrating. I use 'extract variable' to make sense of the return types and break the code down so I can learn it. \n\n\n## Instructions\n\nFollow these instructions to build and run a demo Swift program:\n\n1. Pre-requisite: Swift\n   * I'm using Swift 6.0.3\n2. Build and run the \"file and logging\" program:\n   * \n     ```shell\n     swift run SwiftPlaygroundFileLogging\n     ```\n   * It should look something like this:\n     ```text\n     $ swift run\n     Building for debugging...\n     [9/9] Applying SwiftPlaygroundFileLogging\n     Build of product 'SwiftPlaygroundFileLogging' complete! (2.49s)\n     Welcome to my 'swift-playground'! Let's write some Swift code that writes to a file.\n     The 'log' function is convenient. Calling code can use 'log' and the message gets printed to the screen and written to the log file.\n     ```\n   * The `run` command is convenient because it builds and runs the program. In the next step, let's try only building\n     the program, and not running it.\n   * Let's check the contents of the log file using the following command.\n     ```shell\n     cat ~/Library/Logs/swift-playground.log\n     ```\n   * The output will look something like this:\n     ```text\n     13:21:50: Welcome to my 'swift-playground'! Let's write some Swift code that writes to a file.\n     13:21:50: The 'log' function is convenient. Calling code can use 'log' and the message gets printed to the screen and written to the log file.\n     ```\n3. Build a binary\n   * Link the program into a binary executable file with the following command.\n   * \n     ```shell\n     swift build\n     ```\n   * Run the program from the binary with the following command.\n   * \n     ```shell\n     .build/arm64-apple-macosx/debug/SwiftPlaygroundFileLogging\n     ```\n   * Tip: if you want to clean up old build files just to \"make sure things are working\" then use the following clean command.\n   * \n     ```shell\n     swift package clean\n     ```\n4. Build and run the \"async/await\" program:\n   * \n     ```shell\n     swift run SwiftPlaygroundAsyncAwait\n     ```\n   * It should look something like this:\n     ```text\n     $ swift run SwiftPlaygroundAsyncAwait\n     Building for debugging...\n     Build complete! (0.13s)\n     \n     Let's explore concurrency by way of executing multiple simulated 'data fetch' operations.\n     Fetching 'inbox' data from an external source...\n     Fetching 'photos' data from an external source...\n     Fetching 'news' data from an external source...\n     Data fetch of 'inbox' complete!\n     Data fetch of 'photos' complete!\n     Data fetch of 'news' complete!\n     Found Fake data for 'inbox'\n     Found Fake data for 'photos'\n     Found Fake data for 'news'\n     All data fetches completed in 3.005929541 seconds.\n     ```\n5. Build and run the \"actors\" program:\n   * \n     ```shell\n     swift run SwiftPlaygroundActors\n     ```\n   * The output will look something like this:\n     ```text\n     [\u003c_NSMainThread: 0x6000017040c0\u003e{number = 1, name = main}] Let's implement something with actors and level up our Swift concurrency skills.\n     [\u003c_NSMainThread: 0x6000017040c0\u003e{number = 1, name = main}] \n     [\u003cNSThread: 0x600001704340\u003e{number = 2, name = (null)}] 📢 Welcome to the 42nd annual Swift Track \u0026 Field competition.\n     [\u003cNSThread: 0x600001704340\u003e{number = 2, name = (null)}] We have 5 contestants running in the event. Let's see who is the fastest runner.\n     [\u003cNSThread: 0x600001704340\u003e{number = 2, name = (null)}] ... and they're off and running!\n     [\u003cNSThread: 0x600001704340\u003e{number = 2, name = (null)}] \n     [\u003cNSThread: 0x60000170c040\u003e{number = 3, name = (null)}] Zoom 🏆 finished in position 1 with a time of 1.345394458 seconds. They are the winner!\n     [\u003cNSThread: 0x60000170c040\u003e{number = 3, name = (null)}] Speedster finished in position 2 with a time of 1.611739541 seconds. [isStopped: false]\n     [\u003cNSThread: 0x60000170c040\u003e{number = 3, name = (null)}] Blaze finished in position 3 with a time of 3.345048375 seconds. [isStopped: false]\n     [\u003cNSThread: 0x60000170c080\u003e{number = 4, name = (null)}] \n     [\u003cNSThread: 0x60000170c080\u003e{number = 4, name = (null)}] ⚡️ Lightning was spotted! The race is stopped due to severe weather.\n     [\u003cNSThread: 0x60000170c080\u003e{number = 4, name = (null)}] The race went on for 5.328475375000001 seconds.\n     [\u003cNSThread: 0x60000170c080\u003e{number = 4, name = (null)}] \n     [\u003cNSThread: 0x60000170c080\u003e{number = 4, name = (null)}] Flash made a good attempt, but did not finish the race. They ran for 5.32886775 seconds.\n     [\u003cNSThread: 0x60000170c080\u003e{number = 4, name = (null)}] Bolt made a good attempt, but did not finish the race. They ran for 5.328921791000001 seconds.\n     ```\n   * Concurrent programming is tricky. Here is what happened when I didn't have the check for `isStopped`.\n   * \u003cimg alt=\"concurrency-programming-error.png\" src=\"concurrency-programming-error.png\" width=\"1200\"/\u003e\n\n\n## Making Sense of the Swift Package Manager\n\nThe [Swift Package Manager](https://www.swift.org/package-manager/) is really cool. I really like the `Package.swift`\nfile. It is similar to Gradle in the way that it's a project manifest descriptor but not written in a configuration\nlanguage but written in a full weight programming language: Swift for `Package.swift` and Groovy for `build.gradle` or\nKotlin for `build.gradle.kts`. Similarly to Gradle, it's on the higher side of complexity (please note: no build system\nmatches the gigantic feature set of Gradle). I'm trying to understand the following concepts which are listed in the\ndocs and how they relate to one another:\n\n* *Modules*\n* *Namespaces*\n* *Programs*\n* *Dependencies*\n* *Packages*\n* *Targets*\n* *Products*\n* *Libraries*\n* *Executables*\n\nHere are some notable quotes from those docs:\n\n\u003e Swift organizes code into *modules*.\n\n\u003e Each module specifies a namespace and enforces access controls on which parts of that code can be used outside of the\n\u003e module.\n\n\u003e A program may have all of its code in a single module, or it may import other modules as *dependencies*.\n\n\u003e A *package* consists of Swift source files and a manifest file.\n\n\u003e A package has one or more targets. Each target specifies a product and may declare one or more dependencies.\n\n\u003e A target may build either a library or an executable as its product.\n\n\u003e A *library* contains a module that can be imported by other Swift code.\n\n\u003e An *executable* is a program that can be run by the operating system.\n\n\u003e A target’s dependencies are modules that are required by code in the package.\n\n\u003e By convention, a target includes any source files located in the `Sources/\u003ctarget-name\u003e` directory.\n\n\n## Swift Language Notes\n\nSwift is far more feature-rich than I expected. I had heard it compared to Kotlin, but I've found the type system to be\nin the stratosphere of complexity like TypeScript and Rust. Kotlin is not like this. On the other hand, I might be\nunderestimating Kotlin's complexity especially when it comes to Coroutines, because I've found Swift concurrency language\nfeatures to also be sophisticated (not a bad thing; just a learning curve). I have an especially hard time with\n`async let`, because I don't know how to think of this in terms of a type. It makes me appreciate how you can just `await`\na `Promise` in JavaScript.\n\n\n## Wish List\n\nGeneral clean ups, TODOs and things I wish to implement for this project:\n\n* [x] DONE (it turns out a Swift project has things like a `Package.swift` file) Structure the project in the way that the Swift *Package Manager* would. Swift has an impressive life outside of\n  Apple. Just visit the [Swift website](https://www.swift.org/) to see extensive guides, reference, and community things\n  and notice that this information is presented outside the context of Apple. (Of course Apple is still there but not in an overt way)\n  This is pretty cool. Can I eject this project from Xcode (well, I'm using AppCode)?. Answer: no, this is not possible.\n  [AppCode is not considered a lightweight IDE](https://intellij-support.jetbrains.com/hc/en-us/community/posts/360005062659-Can-I-get-Swift-code-completion-and-syntax-highlighting-in-IntelliJ-).\n* [x] DONE Implement something just a bit more interesting than \"hello world\"\n* [x] DONE How do you implement multi-module Swift projects? What does the directory layout look like? Where do I start?\n* [x] DONE Implement something that starts another process\n* [ ] Heed the warning described by the [`FileManager.fileExists` docs](https://developer.apple.com/documentation/foundation/filemanager/1415645-fileexists)\n   * \u003e Attempting to predicate behavior based on the current state of the file system or a particular file on the file\n       system is not recommended. Doing so can cause odd behavior or race conditions. It’s far better to attempt an\n       operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully\n       than it is to try to figure out ahead of time whether the operation will succeed.\n   * This is not something I've taken seriously in my Java code, but I'm happy to write my Swift more robustly in\n     this regard.\n* [x] DONE Compile/link/whatever a Swift program into a binary executable file\n* [x] DONE Write to a file. I want to know the boilerplate to write a new file and append to an existing one.\n* [x] DONE Concurrency examples. Specifically, I'll start with `async/await`.\n* [x] DONE Clean up the logging stuff. Rebrand it as something like `FileLogger`\n  * I'm going to make a logger class.\n* [x] DONE Consolidate the example code in `main.swift`.\n* [x] DONE (Partially; I'm not satisfied in my experience with continuations and futures, and the features of async in Swift like `async let`, but this will do for now.) Do more concurrency examples. I want to take APIs that I wish supported `async/await`, and adapt them for use with\n  `async/await`. The `Process` API is a good candidate for this. However, I may be better off with simulated examples\n  using `sleep` or something, to reduce the scope of the project.\n* [x] DONE Move the process stuff to \u003chttps://github.com/dgroomes/macos-playground\u003e. The `Process` API is really a concept\n  of the operating system APIs and not the Swift language. I want to keep this project focused on the Swift language.\n* [x] DONE Re-organize with multiple `main` entrypoints. I like that style better, especially if there are 3+ things to\n  showcase, it's awkward putting them in the same main.\n* [x] DONE Do something with actors. I want something like the racing demo I previously implemented. I think I can just use\n  `Task` and it will be interesting enough. One goal is to actually learn some terms (correctly) and relate them to the\n  code example. \n* [x] DONE Showcase task cancellation. The value proposition of `Task` is that they let you move on to other\n  code paths and then later *revisit* the `Task` to await its completion or to cancel it. I don't really grok how\n  cancellation looks in the code yet. Let's try it in the actors/racing demo.\n* [x] DONE Push more of the race management into the RaceManager actor. I think I need to synchronize the 'print'\n  statements because the program techically can race if the 'raceTask.cancel' literally triggers the other tasks to\n  unsuspend on a different/available core (I'm 80% sure).\n* [x] DONE (Yeah straight Tasks with a wrapper Task is great) I'm still confused about the purpose of tasks groups. Can you get the same effect as a task group by just using\n  an outer Task?\n* [ ] Defect. When the lightning strikes, runners don't stop. This is a regression and after a `git bisect` I found that it happened in https://github.com/dgroomes/swift-playground/commit/3c6dc889c12b16249e9903ef46aa5aa8552bac02.\n   It looks like I wrote off task groups when I shouldn't have. Nice.\n\n\n## Reference\n\n* [Swift website](https://www.swift.org/)\n* [The Swift Package Manager](https://www.swift.org/package-manager/)\n  * This page is required reading. You'll have to read it a few times to grok packages, targets, products, libraries,\n    executables, etc.\n* [Apple Developer Docs: *Target*](https://developer.apple.com/documentation/packagedescription/target)\n  * \u003e You can vend targets to other packages by defining products that include the targets.\n    \u003e \n    \u003e A target may depend on other targets within the same package and on products vended by the package’s dependencies. \n* [Apple Developer Docs: *FileManager*](https://developer.apple.com/documentation/foundation/filemanager)\n  * \u003e A convenient interface to the contents of the file system, and the primary means of interacting with it.\n* [Apple Developer Docs: *Process*](https://developer.apple.com/documentation/foundation/process)\n* [*The Swift Programming Language: Concurrency*](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency)\n  * \u003e The concurrency model in Swift is built on top of threads, but you don’t interact with them directly.\n* [Apple Developer Docs / Swift Standard Library: *CheckedContinuation*](https://developer.apple.com/documentation/swift/checkedcontinuation)\n  * \u003e A mechanism to interface between synchronous and asynchronous code, logging correctness violations.\n* [Apple WWDC video: *Protect mutable state with Swift actors*](https://developer.apple.com/videos/play/wwdc2021/10133)\n  * Note: I had to look for this video because the word \"actors\" is not in the [language book](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators). That's a language feature. The video is quite nice, there's even a transcript!\n  * UPDATE: I did find it in the Swift book, it's in \"Concurrency\", it's just that \"actors\" can't be found from the\n    search feature or from a \"Cmd + F\" on the main page. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgroomes%2Fswift-playground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdgroomes%2Fswift-playground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgroomes%2Fswift-playground/lists"}