diff --git a/Package.swift b/Package.swift index ce9e7e8..1865429 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.8 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -7,20 +7,15 @@ let package = Package( name: "Composer", platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6)], products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. .library(name: "Composer", targets: ["Composer"]), .library(name: "ComposerCombine", targets: ["ComposerCombine"]), ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - ], + dependencies: [], targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. .target(name: "Composer", dependencies: []), .testTarget(name: "ComposerTests", dependencies: ["Composer"]), - - .target(name: "ComposerCombine", dependencies: [.init(stringLiteral: "Composer")]), - ] + + .target(name: "ComposerCombine", dependencies: [.init(stringLiteral: "Composer")]), + ], + swiftLanguageVersions: [.v5] ) diff --git a/Playground.playground/Contents.swift b/Playground.playground/Contents.swift index 0245243..9fbf5aa 100644 --- a/Playground.playground/Contents.swift +++ b/Playground.playground/Contents.swift @@ -1,8 +1,151 @@ import Foundation -import Combine -import Composer +import UIKit -let str = ["1", "2", "3", "4"] +//indirect enum List { +// case empty +// case cons(head: T, tail: List) +//} +// +//func listOf(_ t: T...) -> List { +// func go(array: [T]) -> List { +// if array.isEmpty { +// return .empty +// } else { +// return .cons( +// head: array[0], +// tail: go (array: Array (array.dropFirst ())) +// ) +// } +// } +// return go(array: t) +//} +// +//extension List { +// func head() -> T? { +// switch self { +// case .empty: return .none +// case .cons(head: let h, tail: _): return .some(h) +// } +// } +//} +// +//extension List { +// func drop (n: Int) -> List { +// switch self { +// case .empty: return self +// case .cons (head: _, tail: let t): +// if n == 0 { +// return self +// } else { +// return t.drop (n: n-1) +// } +// } +// } +// func dropWhile(_ f: (T) -> Bool) -> List { +// switch self { +// case .empty: return self +// case .cons (head: let h, tail: let t): +// if f(h) { +// return t.dropWhile(f) +// } else { +// return self +// } +// } +// } +// +// func append(_ n: T) -> List { +// switch self { +// case .empty: +// return .cons (head: n, tail: .empty) +// case .cons(head: let h, tail: let t): +// return .cons (head: h, tail: t.append (n)) +// } +// } +// +// func foldLeft (_ initialValue: C, _ f: (C, T) -> C) -> C { +// switch self { +// case .empty: +// return initialValue +// case .cons(head: let h, tail: let t): +// return t.foldLeft(f(initialValue, h), f) +// } +// } +// +// func foldRight (_ initialValue: B, _ f: (T, B) -> B) -> B { +// switch self { +// case .empty: +// return initialValue +// case .cons(head: let h, tail: let t): +// return f(h, t.foldRight(initialValue, f)) +// } +// } +// +// func appendInTermsFoldRight(_ n: T) -> List { +// foldRight(listOf(n)) { t, c in +// return .cons(head: t, tail: c) +// } +// } +// +// func appendInTermsFoldLeft(_ n: T) -> List { +// foldLeft(listOf(n)) { c, t in +// switch c { +// case .empty: return .empty +// case .cons(let head, let tail): +// return .cons( +// head: head, +// tail: tail.appendInTermsFoldLeft(t) +// ) +// } +// } +// } +// +// func print() { +// Swift.print(self.foldLeft(Array.init()) { b, t in +// return b + [t] +// }) +// } +//} +// +//var list = List.cons( +// head: 10, +// tail: .cons( +// head: 20, +// tail: .cons( +// head: 30, +// tail: .empty +// ) +// ) +//) +// +//list = list.appendInTermsFoldLeft(0) +// +//list.print() -str |> join(with: " ") - +import Foundation +import os + +final class Atomic { + + private let accessQueue = DispatchQueue(label: "ru.tinkoff.accessQueue") + private var _value: A + + init(_ value: A) { + self._value = value + } + + var value: A { + self._value + } + + func mutate(_ work: @escaping (A) -> A) { + accessQueue.sync { + self._value = work(value) + } + } +} + +var x = Atomic(0) +DispatchQueue.concurrentPerform(iterations: 100) { _ in + x.mutate { $0 + 1 } +} +print(x.value) diff --git a/Playground.playground/timeline.xctimeline b/Playground.playground/timeline.xctimeline new file mode 100644 index 0000000..cf2a2a9 --- /dev/null +++ b/Playground.playground/timeline.xctimeline @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Sources/Composer/Core/Alternative.swift b/Sources/Composer/Core/Alternative.swift index 64ca612..8c8d8e3 100644 --- a/Sources/Composer/Core/Alternative.swift +++ b/Sources/Composer/Core/Alternative.swift @@ -24,6 +24,7 @@ precedencegroup AlternativePrecedence { infix operator <|> : AlternativePrecedence + public func <|> (_ a: A?, _ alt: @autoclosure @escaping () -> A) -> A { return a ?? alt() } diff --git a/Sources/Composer/Core/Applicative.swift b/Sources/Composer/Core/Applicative.swift index 4ddd5d6..4dab81a 100644 --- a/Sources/Composer/Core/Applicative.swift +++ b/Sources/Composer/Core/Applicative.swift @@ -31,44 +31,8 @@ public func |> (_ t1: T1, _ f: @escaping (T1) -> T2) -> T2 { return f(t1) } -@inlinable -public func |> (_ t1: T1, _ f: @escaping (T1) throws -> T2) rethrows -> T2 { - return try f(t1) -} - -@inlinable -public func |> (_ t1: inout T1, _ f: @escaping (inout T1) throws -> Void) rethrows -> T1 { - try f(&t1) - return t1 -} - -@inlinable -@discardableResult -public func |> (_ t1: T1, _ f: @escaping (T1) throws -> Void) rethrows -> T1 { - try f(t1) - return t1 -} - /// MARK: Inverted @inlinable public func <| (_ f: @escaping (T1) -> T2, _ t1: T1) -> T2 { return f(t1) } - -@inlinable -public func <| ( _ f: @escaping (T1) throws -> T2, _ t1: T1) throws -> T2 { - return try f(t1) -} - -@inlinable -public func <| (_ f: @escaping (inout T1) throws -> Void, _ t1: inout T1) rethrows -> T1 { - try f(&t1) - return t1 -} - -@inlinable -@discardableResult -public func <| (_ f: @escaping (T1) throws -> Void, _ t1: T1) rethrows -> T1 { - try f(t1) - return t1 -} diff --git a/Sources/Composer/Core/Monoid.swift b/Sources/Composer/Core/Monoid.swift index 5f57b49..b777393 100644 --- a/Sources/Composer/Core/Monoid.swift +++ b/Sources/Composer/Core/Monoid.swift @@ -20,8 +20,16 @@ import Foundation -// MARK: - Monoid Definition - +/// Monoid procotol declaration +/// +/// Reducing extra syntax +/// +/// ## Usage +/// ``` +/// extention Int: Monoid { +/// static var empty: Self { 0 } +/// } +/// ``` public protocol Monoid: Semigroup { static var empty: Self { get } } diff --git a/Sources/Composer/Core/OptionalChaining.swift b/Sources/Composer/Core/OptionalChaining.swift index 90c0321..edc8536 100644 --- a/Sources/Composer/Core/OptionalChaining.swift +++ b/Sources/Composer/Core/OptionalChaining.swift @@ -27,6 +27,10 @@ precedencegroup OptionalChainingPrecedence { infix operator : OptionalChainingPrecedence +/// Optional chaingin operator +/// +/// ## Usage +/// public func (_ a2b: @escaping (A) -> B, _ b2c: @escaping (B) -> C) -> (A?) -> C? { return { $0 .map(a2b) diff --git a/Sources/ComposerCombine/Sink.swift b/Sources/ComposerCombine/Sink.swift index be47091..123cdea 100644 --- a/Sources/ComposerCombine/Sink.swift +++ b/Sources/ComposerCombine/Sink.swift @@ -24,30 +24,96 @@ import Foundation import Combine public func fireOnce( - _ completion: @escaping (T) -> Void + _ receiveValue: @escaping (T) -> Void ) -> (P) -> Void where P: Publisher, P.Output == T, P.Failure == Never { return { publisher in var subsciption: AnyCancellable? subsciption = publisher - .handleEvents(receiveCompletion: { _ in + .sink(receiveValue: { + receiveValue($0) subsciption?.cancel() subsciption = nil }) - .sink(receiveValue: completion) } } -public func fireAndForget( - _ completion: @escaping (Subscribers.Completion) -> Void -) -> (P) -> Void where P: Publisher, P.Output == Void, P.Failure == E { +public func fireOnce( + _ recieveValue: @escaping (T) -> Void, + _ recieveError: ((P.Failure) -> Void)? = nil +) -> (P) -> Void where P: Publisher, P.Output == T, P.Failure == E { return { publisher in var subsciption: AnyCancellable? subsciption = publisher - .handleEvents(receiveCompletion: { _ in + .sink( + receiveCompletion: { competion in + switch(competion) { + case let .failure(error): + recieveError?(error) + fallthrough + case .finished: + subsciption?.cancel() + subsciption = nil + } + }, + receiveValue: { + recieveValue($0) + subsciption?.cancel() + subsciption = nil + } + ) + } +} + +public func fireAndForget(_ publisher: P) -> Void where P: Publisher, P.Failure == E { + var subsciption: AnyCancellable? + subsciption = publisher + .ignoreOutput() + .sink( + receiveCompletion: { _ in subsciption?.cancel() subsciption = nil - }) - .sink(receiveCompletion: completion, receiveValue: { _ in }) + }, + receiveValue: { _ in } + ) +} + +public func fireAndForget( + _ completion: @escaping (Subscribers.Completion) -> Void +) -> (P) -> Void where P: Publisher, P.Failure == E { + return { publisher in + var subsciption: AnyCancellable? + subsciption = publisher + .ignoreOutput() + .sink( + receiveCompletion: { + subsciption?.cancel() + subsciption = nil + completion($0) + }, + receiveValue: { _ in } + ) + } +} + +public func run( + _ recieveValue: @escaping (T) -> Void, + _ recieveError: ((P.Failure) -> Void)? = nil +) -> (P) -> Void where P: Publisher, P.Output == T, P.Failure == E { + return { publisher in + var subsciption: AnyCancellable? + subsciption = publisher + .sink( + receiveCompletion: { competion in + switch(competion) { + case .finished: + subsciption?.cancel() + subsciption = nil + case let .failure(error): + recieveError?(error) + } + }, + receiveValue: recieveValue + ) } }