Skip to content

Instantly share code, notes, and snippets.

View groue's full-sized avatar

Gwendal Roué groue

View GitHub Profile
@groue
groue / SinglePublisher.swift
Last active October 8, 2021 13:34
SinglePublisher
import Combine
import Foundation
// MARK: - SinglePublisher
/// The protocol for "single publishers", which publish exactly one element, or
/// an error.
///
/// `Just`, `Future` and `URLSession.DataTaskPublisher` are examples of
/// publishers that conform to `SinglePublisher`.
@groue
groue / ScopedFunctions.md
Last active March 13, 2021 15:16
Pitch: Scoped Functions

Pitch: Scoped Functions

Introduction

Scoped Functions are functions that enhance the leading dot syntax inside their body, so that it gives short-hand access to the members of a specific value. Such functions exist so that API designers and their consumers can collaborate towards a way to write focused code where an agreed implicit and obvious context does not have to be spelled out.

Motivation

This pitch considers that developers often want to use short-hand identifier resolution in particular contexts, and api designers often want to make it possible.

@groue
groue / ContainerView.swift
Last active April 18, 2022 17:29
Exploring @‍Query initializers
import SwiftUI
/// A Container view which uses various techniques
/// for controlling RequestView.
struct ContainerView: View {
@State var parameter = 0
var body: some View {
List {
Section {
@groue
groue / Database+withDeferredUniqueIndexes.swift
Last active August 23, 2022 14:43
Deferred unique indexes with GRDB
import GRDB
extension Database {
/// Executes the provided closure with deferred unique indexes
func withDeferredUniqueIndexes(_ execute: () throws -> Void) throws {
try inSavepoint {
// Fetch all unique indexes, but primary keys.
let uniqueConstraints: [(table: String, index: IndexInfo)] = try String
.fetchAll(self, sql: "SELECT name FROM sqlite_master WHERE type = 'table'")
.filter { !Database.isGRDBInternalTable($0) }

Explicit Protocol Fulfillment

Introduction

This pitch introduces of a new keyword in front of declarations: conformance.

The conformance keyword means: "this declaration is intended by the programmer to fulfill a protocol requirement". Its presence is never required. However, when present, the program is ill-formed unless the declaration does match a protocol requirement.

For example:

import SwiftUI
struct MyCollection: RandomAccessCollection {
let startIndex = 0
let endIndex = 1000
subscript(index: Int) -> Int {
print("Access \(index)")
return index
}
}
@groue
groue / Playground.swift
Last active September 28, 2022 15:54
Semaphore.swift
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
Task {
do {
print("Start, 1 concurrent task")
let semaphore = Semaphore(value: 1)
await withThrowingTaskGroup(of: Void.self) { group in
for i in 0..<10 {
group.addTask {
@groue
groue / TimestampedRecord.swift
Last active February 21, 2023 07:09
TimestampedRecord: an example protocol for GRDB records that track their creation and modification dates.
/// A type that tracks its creation and modification dates, as described in
/// <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/recordtimestamps>
protocol TimestampedRecord {
var creationDate: Date? { get set }
var modificationDate: Date? { get set }
}
extension TimestampedRecord where Self: MutablePersistableRecord {
/// Sets `modificationDate` to the transaction date.
mutating func touch(_ db: Database) throws {
@groue
groue / transcript.md
Last active March 26, 2023 13:05
ChatGPT attempts at implementing a counting semaphore with Swift Concurrency

Is it possible to implement a classical counting semaphore with Swift concurrency (async/await)? I wish I could call an async method await semaphore.wait() and a sync method semaphore.signal() with the same semantics as a classical semaphore, but without blocking any thread.

Yes, it is possible to implement a classical counting semaphore with Swift concurrency using async/await without blocking any thread. Here is an example implementation: swift

class Semaphore {
    private var count: Int
    private let lock = NSLock()
    private var waiters: [Task<Void, Never>] = []
@groue
groue / opinion.md
Last active September 7, 2023 14:59
Swift key paths are not coding keys, JSON keys, or SQLite columns

Swift key paths are not coding keys, JSON keys, or SQLite columns

(Copy-pasted from groue/GRDB.swift#1423 (comment), edited for clarity)

And if I remember correctly, you had some good reasons for not using key paths in the GRDB query builder

My reluctance about key paths is based on the fact that record types do frequently, but not always, exactly reflect their database representation. The reality is that record types are a Swift interface to their inner database representation. And it's the same for "json records" as well.

That's how people use them. They'll replace a text database value with a Swift string-based enum value. They'll publicly expose a price: Decimal property instead of the priceCents database integer. They'll publicly expose a location: CLLocationCoordinate2D property instead of two latitude and longitude database doubles.