Skip to content

Instantly share code, notes, and snippets.

@akisute
Last active August 29, 2015 14:02
Show Gist options
  • Save akisute/538e3171d9e7d3bce0c1 to your computer and use it in GitHub Desktop.
Save akisute/538e3171d9e7d3bce0c1 to your computer and use it in GitHub Desktop.
Playing around with Swift
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
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