Skip to content

Instantly share code, notes, and snippets.

View rnapier's full-sized avatar

Rob Napier rnapier

View GitHub Profile
@rnapier
rnapier / StringEncode.swift
Created July 20, 2018 00:50
JSONEncoder().stringEncode()
extension JSONEncoder {
func stringEncode<T>(_ value: T) throws -> String where T : Encodable {
guard let string = String(data: try self.encode(value), encoding: .utf8) else {
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Could not UTF-8 encode string"))
}
return string
}
}
@rnapier
rnapier / retain.swift
Last active July 3, 2018 20:55
Laundering retain loops
// With functions/methods you can "launder" your code so it doesn't require self references anymore,
// but you wind up with retain loops that are very non-obvious. I'm having trouble finding good coding
// styles that reliably avoid this kind of problem.
class B {
// A retain loop waiting to happen
var completionHandler: () -> Void = {}
}
class C {
@rnapier
rnapier / stream.swift
Last active June 3, 2021 09:16
Newer stream-based ideas on observables
/*
Updated ideas on observation. Much more powerful and composeable than previous Observable approach.
Simpler, but less powerful, than RxSwift
*/
import Foundation
public class Disposable {
private var isDisposed = false
private let _dispose: () -> Void
let xs = [0,1,2,3,4,5]
let double: (Int) -> Int = { $0 * 2 }
let isEven: (Int) -> Bool = { $0 % 2 == 0 }
// Goal: [0,2,4,6,4,10]. Double all but the last even element.
// This impl makes me sad. Lots of state and copies the entire collection twice (once during transforming, and once to unreverse)
extension Collection {
@rnapier
rnapier / observable.swift
Created May 16, 2018 18:51
New Observable idea
import Foundation
class Disposable {
let dispose: () -> Void
init(dispose: @escaping () -> Void) { self.dispose = dispose }
deinit {
dispose()
}
}
@rnapier
rnapier / main.swift
Created March 30, 2018 16:14
vvsqrtf performance tests
// swift -O main.swift
import Foundation
import Accelerate
let N = 100_000_000
let x = (0...N).map { _ in Float(drand48() * 1_000_000) }
func test(_ f: () -> [Float], name: String) {
@rnapier
rnapier / ClassSet.swift
Last active February 3, 2018 20:57
SetAlgebra for classes
//
// ClassSet.swift
// audio
//
// Created by Rob Napier on 1/25/18.
// Copyright © 2018 Jaybird LLC. All rights reserved.
//
/// Unordered set of unique class objects. Does not require Equatable or Hashable.
struct ClassSet<Element> where Element: AnyObject {
@rnapier
rnapier / json.swift
Last active January 31, 2024 12:49
Generic JSON Decodable
import Foundation
@dynamicMemberLookup
enum JSON: Codable, CustomStringConvertible {
var description: String {
switch self {
case .string(let string): return "\"\(string)\""
case .number(let double):
if let int = Int(exactly: double) {
return "\(int)"
@rnapier
rnapier / error-propagation.swift
Last active April 27, 2017 14:01 — forked from nicklockwood/error-propagation.swift
Typed error use-case example
// I know you meant it to be exaggerated, but I still think this is the better approach in practice:
enum ClassError: Error {
case propertyNotFound(name: String)
case typeMismatch(propertyName: String)
}
class Foo {
var properties: [(String, Any)] = []
private func validateValue(_ value: Any, for property: String) throws { // Note that I pass the name just for the error; that's ok IMO
public typealias JSON = [String:Any]
public enum JSONInitializableError: Error {
case initializationError(key: String)
}
public protocol JSONInitializable {
associatedtype Key: RawRepresentable
init(with json: JSON) throws
}