Last active
August 29, 2015 14:07
-
-
Save BestKora/f1c9d453b1f43a4a6fd3 to your computer and use it in GitHub Desktop.
Код к серии статей "Управление ошибками в Swift: магия и реальность. http://www.bestkora.com/SwiftLearning/upravlenie-oshibkami-v-swift-magiya-i-realn/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Playground - noun: a place where people can play | |
import Foundation | |
// ДЛЯ СТАТЬИ http://nomothetis.svbtle.com/error-handling-in-swift | |
// Управление ошибками в Swift: магия и реальность - Часть 2 | |
// http://www.bestkora.com/SwiftLearning/upravlenie-oshibkami-v-swift-magiya-i-realn/ | |
// ============= Обычная функция =========== | |
func divide0 (a: Float, by: Float ) -> Float { | |
return a/by | |
} | |
// ------Тестовый пример 1 | |
let result0 = divide0(2.5, 3) | |
// ============ Возврат ошибки NSError ====== | |
// Для упрощения работы с классом NSError создаем "удобный" инициализатор в расширении класса | |
extension NSError { | |
convenience init(localizedDescription: String) { | |
self.init(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: localizedDescription]) | |
} | |
} | |
func divide1 (a:Float, by:Float, inout error:NSError) -> Float?{ | |
switch by{ | |
case 0: | |
error = NSError(localizedDescription: "Деление на нуль") | |
return nil | |
default: | |
return a/by | |
} | |
} | |
var err = NSError(localizedDescription: "OK"); | |
// ------Тестовый пример 1 | |
var result1 = divide1(2.5, 3, &err) | |
println("\(result1)") | |
println("\(err.localizedDescription)") | |
// ------Тестовый пример 2 | |
result1 = divide1(2.5, 0, &err) | |
println("\(result1)") | |
println("\(err.localizedDescription)") | |
//======== Результат в виде перечисления Result<T>============ | |
enum Result<T> :Printable { | |
case Success(Box<T>) | |
case Failure(NSError) | |
var description : String { | |
get { | |
switch self{ | |
case .Success(let value): | |
return "\(value.unbox)" | |
case .Failure(let err): | |
return "\(err.localizedDescription)" | |
} | |
} | |
} | |
func map<P>(f: T -> P) -> Result<P> { | |
switch self { | |
case .Success(let value): | |
return .Success(Box(f(value.unbox))) | |
case .Failure(let err): | |
return .Failure(err) | |
} | |
} | |
func flatMap<P>(f:T -> Result<P>) -> Result<P> { | |
switch self { | |
case .Success(let value): | |
return f(value.unbox) | |
case .Failure (let err): | |
return .Failure(err) | |
} | |
} | |
} | |
final class Box<T> { | |
let unbox: T | |
init(_ value: T) { self.unbox = value } | |
} | |
func divide (a:Float, by:Float) -> Result<Float>{ | |
switch by{ | |
case 0: return .Failure(NSError(localizedDescription: "Деление на нуль")) | |
default: | |
return .Success(Box(a/by)) | |
} | |
} | |
// ------Тестовый пример 1 | |
var result = divide(2.5, 0.3 ) | |
println(result.description) | |
// ------Тестовый пример 2 | |
result = divide(2.5, 0 ) | |
println(result.description) | |
//======== map ============ | |
func magicNumber(quotient:Float) -> Float { | |
let lpf = sin(quotient) | |
return log(lpf) | |
} | |
func spelling(quotient:Float) -> String { | |
let lpf = quotient.description | |
return lpf | |
} | |
// ------Тестовый пример 1 | |
result = divide(2.5, 0.3 ) | |
var result2 = result.map(magicNumber).map(spelling) | |
println(result2.description) | |
// ------Тестовый пример 2 | |
result = divide(2.5, 0 ) | |
result2 = result.map(magicNumber).map(spelling) | |
println(result2.description) | |
// ------Тестовый пример 3 | |
result = divide(2.5, 0.3 ) | |
result2 = result.map(sin).map(log).map(spelling) | |
println(result2.description) | |
// ДЛЯ СТАТЬИ http://nomothetis.svbtle.com/error-handling-in-swift-part-ii | |
// Управление ошибками в Swift: магия и реальность - Часть 2 | |
// http://www.bestkora.com/SwiftLearning/upravlenie-oshibkami-v-swift-vozmozhnosti-i/ | |
//======== flat map ============ | |
func log1 (a:Float) -> Result<Float>{ | |
switch a { | |
case let x where x <= 0: return .Failure(NSError(localizedDescription: "Логарифм отрицательного числа")) | |
default: | |
return .Success(Box(a)) | |
} | |
} | |
func magicNumber1(quotient:Float) -> Result<Float> { | |
let sinus = sin(quotient) | |
return log1(sinus) | |
} | |
// ------Тестовый пример 1 | |
result = divide(2.5, 0.3 ) | |
var result3 = result.map(sin).flatMap(log1).map(spelling) | |
println(result3.description) | |
// ------Тестовый пример 2 | |
result = divide(2.5, 0.3 ) | |
result3 = result.flatMap(magicNumber1).map(spelling) | |
println(result3.description) | |
// ------Тестовый пример 3 (деление на нуль) | |
result = divide(2.5, 0 ) | |
result3 = result.flatMap(magicNumber1).map(spelling) | |
println(result3.description) | |
// ------Тестовый пример 4 (логифм отрицательного числа) | |
result = divide(2.5, -2.0 ) | |
result3 = result.flatMap(magicNumber1).map(spelling) | |
println(result3.description) | |
// БОНУС ======== curried function ============ | |
func divide3 (a:Float) (by:Float) -> Result<Float>{ | |
return divide (a,by) | |
} | |
// ------Тестовый пример 1 -- просто curry | |
var result4 = divide3(2.5)(by: 3) | |
println(result4.description) | |
// ------Тестовый пример 2 -- curry и map, flatMap | |
var result5 = divide3(2.5)(by: 0.3).map(sin).flatMap(log1).map(spelling) | |
println(result5.description) | |
// ------Тестовый пример 3 -- 1/result4 интересный вариант | |
var result6 = divide3(2.5)(by: 0.3).map(sin).flatMap(log1).flatMap(divide3(1)).map(spelling) | |
println(result6.description) | |
//.map({$0/3}) | |
println( divide(1.0, 0.887294232845306).description) | |
// ------Тестовый пример 4 -- 1/result4 /3 и closure {$0/3} | |
var result7 = divide3(2.5)(by: 0.3).map(sin).flatMap(log1).flatMap(divide3(1)).map({$0/3}).map(spelling) | |
println(result7.description) | |
//==== Для статьи http://nomothetis.svbtle.com/understanding-optional-chaining | |
// Понимание Optional Chaining | |
// http://www.bestkora.com/SwiftLearning/ponimanie-optional-chaining/ | |
infix operator |- { associativity left precedence 150 } | |
func |-<T, U>(opt:T?, f: T -> U?) -> U? { | |
switch opt { | |
case .Some(let x): | |
return f(x) | |
case .None: | |
return .None | |
} | |
} | |
public class Demo { | |
public let subDemo:SubDemo? | |
init(subDemo sDemo:SubDemo? = nil) { | |
self.subDemo = sDemo | |
} | |
} | |
public class SubDemo { | |
public let count:Int = 1 | |
public func two() ->Int {return 2} | |
} | |
// ----- Тестовый пример 1 оператор |- | |
let aDemo:Demo? = nil | |
let bDemo:Demo? = Demo() | |
let cDemo:Demo? = Demo(subDemo: SubDemo()) | |
let aCount = aDemo |- { $0.subDemo } |- { $0.count } // {None} | |
let bCount = bDemo |- { $0.subDemo } |- { $0.count } // {None} | |
let cCount = cDemo |- { $0.subDemo } |- { $0.count } // {Some 1} | |
let dCount = cDemo |- { $0.subDemo } |- { $0.two() } // {Some 2} | |
println("\(aCount) \(bCount) \(cCount) \(dCount)") | |
//===== flatMap для Optional ====== | |
extension Optional { | |
func flatMap<Z>(f:T->Z?) -> Z? { | |
switch self { | |
case .Some(let a): | |
return f(a) | |
case .None: | |
return .None | |
} | |
} | |
} | |
// ----- Тестовый пример 2 flatMap | |
let aCount1 = aDemo.flatMap { $0.subDemo }.flatMap { $0.count } // {None} | |
let bCount1 = bDemo.flatMap { $0.subDemo }.flatMap { $0.count } // {None} | |
let cCount1 = cDemo.flatMap { $0.subDemo }.flatMap { $0.count } // {Some 1} | |
println("\(aCount1) \(bCount1) \(cCount1)") | |
// ----- Тестовый пример 3 ?. | |
let aCount2 = aDemo?.subDemo?.count // {None} | |
let bCount2 = bDemo?.subDemo?.count // {None} | |
let cCount2 = cDemo?.subDemo?.count // {Some 1} | |
println("\(aCount2) \(bCount2) \(cCount2)") | |
// ----- Тестовый пример 4 flatMap | |
let a:Int? = 9 // some optional | |
if let a = a { | |
println("\(a)") | |
} | |
a.flatMap { println("\($0)") } | |
//==== Для статьи http://nomothetis.svbtle.com/implicitly-unwrapped-optionals-in-depth | |
// Подробнее об Implicitly Unwrapped Optionals (IUO) | |
// http://www.bestkora.com/SwiftLearning/podrobnee-ob-implicitly-unwrapped-optionals-iuo/ | |
// ----- Тестовый пример 1 | |
let arr:[String]! = ["hello", "world"] | |
let val = find(arr, "hello") | |
// ----- Тестовый пример 2 | |
let str = "hello" | |
let a8 = str.stringByAppendingString("!") | |
let b8 = String.stringByAppendingString(str)("!") | |
let method = String.stringByAppendingString(str) | |
let c8 = method("!") | |
// ----- Тестовый пример 3 | |
infix operator +- { associativity left precedence 150 } | |
func +-<T,Z>(obj:T, f:T->Z) -> Z { | |
return f(obj) | |
} | |
let happyHello1 = "hello" +- { | |
String.stringByAppendingString($0)("!") | |
} | |
// ----- Тестовый пример 4 оператор +- | |
infix operator +-= { associativity left precedence 150 } | |
func +-=<T,Z>(obj:ImplicitlyUnwrappedOptional<T>, f:T->Z) | |
-> ImplicitlyUnwrappedOptional<Z> { | |
switch obj { | |
case .Some(let x): | |
return f(x) | |
case .None: | |
abort() | |
} | |
} | |
let maybeHello:String! = "hello" | |
let happyHello8 = maybeHello +-= { | |
String.stringByAppendingString($0)("!") | |
} +-= { | |
String.stringByAppendingString($0)("!") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment