Last active
August 29, 2015 14:02
-
-
Save akisute/538e3171d9e7d3bce0c1 to your computer and use it in GitHub Desktop.
Playing around with Swift
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
import Foundation | |
var l = [ | |
"abesi", | |
"hidebu", | |
"tawaba", | |
] | |
var m = [ | |
"abesi": 1, | |
"hidebu": 2, | |
"tawaba": 3, | |
//"tawaba": "3" | |
//is acceptable, but causes implicit type inference malfunction | |
//(looks like swift uses the lastObject to infer types) | |
] | |
m["itterebo"] = 4 | |
m | |
var mm:Dictionary<String, Int> = [ | |
"abesi": 1, | |
"hidebu": 2, | |
"tawaba": 3, | |
] | |
mm | |
let emptyArray = String[]() | |
let emptyArray2 = Array<String>() | |
let emptyDict = Dictionary<String, String>() | |
// Here's how to deal with types! | |
// Array.Type is a MetaType of Array. | |
// Dictionary.Type is a MetaType of Dictionary. | |
// MetaType means type of type. Wow I hate this kind of abstract liddles. | |
// For Protocols, use UIApplicationDelegate.Protocol or something like this. | |
// Tried Array.self to access MetaType of Array but it caused infinite crashes... | |
// Looks like we should keep away from fidddling with types XD | |
l.dynamicType // Returns Array<String>.Type | |
m.dynamicType // Returns Dictionary<String, Int>.Type | |
typealias MyTimeInterval = NSTimeInterval | |
typealias Point = (Int, Int) | |
let 千五百秒:MyTimeInterval = 1_500.0 | |
let origin:Point = (1, 2) | |
// Void is a typealias for (), the empty tuple type | |
// Type of (Int) will be Int because there's only a single element | |
// Type of (Int, Int) will be (Int, Int) tuple | |
let namedTuple = (abesi:"abesi", hidebu:"hidebu") | |
// Looks like function params and retvars are just tuples! | |
// @auto_closure wraps the Bool argument as a closure! | |
func simpleAssert(condition:@auto_closure()->Bool, message:String) -> String { | |
if !condition() { | |
return message | |
} | |
return "" | |
} | |
simpleAssert(4%2==0, "YOU ARE AN EVEN NUMBER!!") | |
simpleAssert(5%2==0, "YOU ARE NOT AN EVEN NUMBER!!") | |
simpleAssert(false, "YOU ARE FALSE!") | |
// Here's a comparison | |
func simpleAssertWithoutAutoClosure(condition:()->Bool, message:String) -> String { | |
if !condition() { | |
return message | |
} | |
return "" | |
} | |
simpleAssertWithoutAutoClosure({4%2==0}, "YOU ARE AN EVEN NUMBER!!") | |
simpleAssertWithoutAutoClosure({5%2==0}, "YOU ARE NOT AN EVEN NUMBER!!") | |
simpleAssertWithoutAutoClosure({false}, "YOU ARE FALSE!") | |
// Curried Functions, um I like curries but not curried functions | |
func addTwoNumbers(a:Int)(b:Int) -> Int { | |
return a + b | |
} | |
addTwoNumbers(4)(b:5) // OMG! Document Lies!!!! | |
func addTwoNumbers2(a:Int) -> (Int -> Int) { | |
func addTheSecondNumber(b:Int) -> Int { | |
return a + b | |
} | |
return addTheSecondNumber | |
} | |
addTwoNumbers2(4)(5) | |
// Optional Types | |
// VERY confusing with Ruby's ? (boolean getter) and ! (destrutive method) | |
// Contains tons of unique features, I should take some time to learn them | |
//var thisIsErrorInteger:Int = nil | |
var optionalInteger:Int? = nil | |
var optionalInteger2:Optional<Int> = nil | |
var optionalIntArray:(Int[])? = nil // OMG! Document says Int[]? would be an error but it isn't!!! | |
var implicitlyUnwrappedOptionalInteger:Int! = 111 | |
var implicitlyUnwrappedOptionalInteger2:ImplicitlyUnwrappedOptional<Int> = 111 | |
// Basically Optional types contains 2 inner types: None and Some<T> | |
// (nil is a special value to indicate that optionals doesn't contain value. Not a typealias of None or something) | |
// (nil cannot be used on non-optional types) | |
// (You can see the Playground shows {Some 42} instead of 42) | |
// No operator = Some<T> if available, None when not available | |
// ! = force unwrap Some<T> (actually returns ImplicitlyUnwrappedOptional<T>, but it almost doesn't matter), error when not available | |
// ? = Some<T> if available, cancel any following operations when not available | |
//optionalInteger! // fatal error: Can't unwrap Optional.None | |
optionalInteger | |
optionalInteger? | |
optionalInteger.description // Nothing happens. Wow. nil is still safe! Congrats guys!!! | |
//optionalInteger?.description // WTF! This is error because description method is ambiguous between Int/Optional<T>! | |
optionalInteger = 42 | |
optionalInteger! // Now fine since we got a value. | |
optionalInteger | |
optionalInteger? | |
optionalInteger.description | |
// Conditional statements (where it takes Bool value) can take optionals, then | |
// return true if there's a value else false. | |
// Use let to unwrap values from optionals like this: | |
if let value = optionalInteger { | |
optionalInteger // {Some 42}, still optional, still Int? | |
value // Unwrapped! It IS Int | |
} | |
// Use is to type check, as to cast | |
// But won't use that much, since compiler warns like (m is Dictionary) always true | |
// She's so smart.... | |
// Perhaps we'll use this when casting UIView/UIViewController around? | |
/* | |
if (m is Dictionary<String, Int>) { | |
"m is a Dictionary!" | |
} | |
*/ | |
// Handling types make Playground really unstable | |
// Following example caused my Playground fatal error: EXC_BREAKPOINT | |
/* | |
class SomeSuperType {} | |
class SomeType: SomeSuperType {} | |
class SomeChildType: SomeType {} | |
let someType = SomeType() | |
let cast1 = someType as SomeSuperType // Guaranteed success, cast1 is SomeSuperType | |
//let cast2 = someType as Int // Compile error. So smart. | |
let cast3 = someType as SomeChildType // Unknown cast, cast3 is SomeChildType? | |
let cast11:SomeSuperType = someType // This is same as cast1 | |
//let cast33:SomeChildType = someType // Compile error, only available for guaranteed casts | |
//let cast33:SomeChildType? = someType // Ditto. | |
*/ | |
func hasAnyMatches(list:Array<Int>, condition:Int->Bool) -> Bool { | |
for i in list { | |
if condition(i) { | |
return true | |
} | |
} | |
return false | |
} | |
var numbers = [20, 19, 7, 12] | |
var b = hasAnyMatches(numbers, {$0 < 10}) | |
b | |
b = hasAnyMatches(numbers, {$0 > 100}) | |
b | |
var numbers2 = numbers.map({(i:Int) -> Int in // Can't omit () around i:Int | |
return i*3 | |
}) | |
numbers2 | |
numbers2 = numbers.map({i -> Int in | |
return i*4 | |
}) | |
numbers2 | |
numbers2 = numbers.map({i in | |
return i*5 | |
}) | |
numbers2 | |
numbers2 = numbers.map({i in i*6}) | |
numbers2 | |
numbers2 = numbers.map({$0 * 7}) | |
numbers2 | |
numbers2 = numbers.map({i in i % 2 == 0 ? i : 0}) // Prefers named variables than $0 heh | |
numbers2 | |
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
import Foundation | |
enum ServerResponse { | |
case Success(code:Int, jsonString:String) | |
case Error(code:Int) | |
case Cancelled(String) | |
} | |
let success = ServerResponse.Success(code: 200, jsonString: "tekitou") | |
let failure = ServerResponse.Error(code: 404) | |
let cancelled = ServerResponse.Cancelled("cancelled") | |
switch success { | |
case let .Success(code, jsonString): | |
"Success: \(code) Response is \(jsonString)" | |
case let .Error(code): | |
"Error: \(code)" | |
case let .Cancelled(message): | |
message | |
default: | |
"Default" | |
} | |
protocol Descriable { | |
var simpleDescription:String {get} | |
//@optional var something:String {get set} // Error: Optional is only available on @objc protocol... WTF!? Apple uses this!!! | |
} | |
enum Rank:Int, Descriable { | |
case Ace = 1 | |
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten | |
case Jack, Queen, King | |
var simpleDescription:String { | |
get { | |
switch self { | |
case .Ace: | |
return "Ace" | |
case .Jack: | |
return "Jack" | |
case .Queen: | |
return "Queen" | |
case .King: | |
return "King" | |
default: | |
return String(self.toRaw()) | |
} | |
} | |
} | |
// Here's an undocumented trick: How to enumerate enums using Generator! | |
// I wish I could use yield though ;( | |
class EnumGenerator:Generator { | |
var i = 1 | |
func next() -> Rank? { | |
let e = Rank.fromRaw(i) | |
i++ | |
return e | |
} | |
} | |
static func enumerate() -> SequenceOf<Rank> { | |
return SequenceOf<Rank>({EnumGenerator()}) | |
} | |
} | |
let ace = Rank.Ace | |
ace.simpleDescription | |
let jack = Rank.fromRaw(11) // Returns Rank? instead of Rank | |
//jack.simpleDescription // Error: Rank? doesn't have simpleDescription | |
jack?.simpleDescription // OK: String? | |
jack!.simpleDescription // OK: String, could be unsafe | |
if let v = jack { | |
v.simpleDescription // OK: String, safe | |
} | |
/* | |
enum Suit:Descriable { | |
case Spades, Hearts, Diamonds, Clubs | |
var simpleDescription:String { | |
get { | |
switch self { | |
case .Spades: | |
return "Spades" | |
case .Hearts: | |
return "Hearts" | |
case .Diamonds: | |
return "Diamonds" | |
case .Clubs: | |
return "Clubs" | |
} | |
} | |
} | |
} | |
*/ | |
enum Suit:String, Descriable { | |
case Spades = "Spades" | |
case Hearts = "Hearts" | |
case Diamonds = "Diamonds" | |
case Clubs = "Clubs" | |
var simpleDescription:String { | |
get { | |
return self.toRaw() | |
} | |
} | |
// Well the compiler should handle Suit? and Suit more better... like not adding full name... | |
// Why does she say .Spades is not a Suit? XD | |
// And give me a yield right nowwwwww | |
class EnumGenerator:Generator { | |
var current:Suit? = Suit.Spades | |
func next() -> Suit? { | |
let e = self.current | |
if let c = self.current { | |
switch c { | |
case .Spades: | |
self.current = Suit.Hearts | |
case .Hearts: | |
self.current = Suit.Diamonds | |
case .Diamonds: | |
self.current = Suit.Clubs | |
default: | |
self.current = nil | |
} | |
} | |
return e | |
} | |
} | |
static func enumerate() -> SequenceOf<Suit> { | |
return SequenceOf<Suit>({EnumGenerator()}) | |
} | |
} | |
struct Card:Descriable { | |
var rank:Rank | |
var suit:Suit | |
var simpleDescription:String { | |
get { | |
return "The \(self.rank.simpleDescription) of \(self.suit.simpleDescription)" | |
} | |
} | |
static func fullSetOfCards()->Array<Card> { | |
// use let to make an immutable array/dict | |
// use var to make a mutable array/dict | |
var result = Array<Card>() | |
for suit in Suit.enumerate() { | |
for rank in Rank.enumerate() { | |
let card = Card(rank: rank, suit: suit) | |
result.append(card) | |
} | |
} | |
return result | |
} | |
} | |
let threeOfSpades = Card(rank:.Three, suit:.Spades) | |
threeOfSpades.simpleDescription | |
let deck = Card.fullSetOfCards() | |
let deckString = deck.map({card in card.simpleDescription}) | |
deckString | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment