콘텐츠로 건너뛰기
Home » swift » Page 14

swift

Swift :: 1.2의 커리드함수와 함수 합성에 대해

커링

Swift 1.2부터는 커리드 함수를 만들 때 파라미터 이름을 생략할 수 있게 되었다.1 함수를 커리드함수로 정의할 때

func f(a:Int)(b:Int)(c:Int) -> Int {
    return a * 2 + b * 3 + c * 5
}
let a = f(1)
let b = a(b:2)
let c = b(c:3)

이런식으로 커리드된 함수에서는 파라미터 이름을 반드시 넣어야 했는데, 이렇게 부분적용함수의 나머지 인자에 대해 반드시 이름을 쓰는 것만 허용이 됐었다. 이 경우에는 부분적용함수를 실제로 호출하는 경우, 반드시 해당 파라미터 이름을 기술해야하므로, 원 함수의 시그니쳐를 알지못하면 쓰기가 어렵기 때문에 활용할만한 곳이 많이 않았다. 하지만 Swift 1.2에서부터 이런 제한이 없어지고, 아래와 같이 2차 이후 부터의 인자 외부 이름을 생략하는 것이 허용됐다.더 보기 »Swift :: 1.2의 커리드함수와 함수 합성에 대해

Swift :: @autoclosure explained

#@autoclosure 인자로 클로저를 받는 함수를 하나 생각해보자. func f(pred: () -> Bool) { if pred() { println("It's true") } } 이 함수를 호출할 때에는 클로져 자체를 넘겨주게 된다. f({ 2 > 1}) // 혹은 f{2 > 1} @autoclosure는 함수의 파라미터를 자동으로 클로져로 감싸면서 호출한 시점의 문맥에서 동작하게 한다. 따라서 f(2 > 1) 로 호출할 수 있다. 이 기능의 의미는 인자로 전달되는 표현식의 평가 시점에 있다. 일반적인 함수 호출 흐름에서는 표현식이 함수의 인자로 들어가게 될 때, 함수는 값을 전달받게 되므로 표현식이… 더 보기 »Swift :: @autoclosure explained

Swift :: Encode and Decode a value type’s instance

임의의 Struct, Enum 타입을 인코딩하라.

임의의 값 타입을 인코딩하는 법을 찾아보자. (클래스의 경우에는 NSCoding이 있으니…) 먼저 인코딩이 필요한 함수를 생각해보자. NSData는 특정 포인터와 그 길이를 가지고 데이터를 만들 수 있다. NSData(bytes:UnsafePointer<T>, length:Int) 여기서 크기는 타입의 크기인데, C와 같이 Swift도 sizeof() 함수를 제공한다. (C에서는 연산자이다.)
Swift에서 inout T 타입과 UnsafePointer<T> 타입은 구분되므로 (T가 옵셔널인 경우에는 포인터로 간주될 수 있다.) 보조 함수인 withUnsafePointer<T>(_:_:) 함수를 사용하여 inout 으로 넘긴 T 타입을 포인터로 바꿀 수 있다.
따라서 인코드 함수는 다음과 같이

func encode<T>(var value:T) -> NSData {
    let data = withUnsafePointer(&value){
        (p:UnsafePointer<T>) -> NSData in
        return NSData(bytes:p, length:sizeof(T.Type))
    }
    return data
}

작성할 수 있다. 디코드하는 함수는? 이건 영락없이 포인터를 만들어서 메모리를 신규로 할당하고 여기에 바이트를 채워넣는 수 밖에 없어보인다. (물론 NSValue로 만들어서 내놓는 방법이 있는데, Swift는 아직 @encode를 쓸 수 없다.)
그래서 UnsafeMutablePointer<T> 타입을 이용해서 실제로 포인터를 다뤄보자.더 보기 »Swift :: Encode and Decode a value type’s instance

Swift – Access Control

Swift – Access Control

액세스 컨트롤은 다른 모듈이나 다른 소스파일로부터 코드의 일부에 접근하는 것을 제한하는 것을 의미한다. 이 기능을 사용하면 구현 코드를 숨기거나, 다른 곳에서 액세스할 수 있는 API를 선별적으로 지정할 수 있다.
액세스 레벨은 개별타입(클래스, 구조체, 열거체)에 대해서 프로퍼티, 메소드, 이니셜라이저, 서브스크립팅등에 대해 적용할 수 있다. 프로토콜은 특정한 컨텍스트에 대해 제한될 수 있는데 이는 전역 상수나 변수, 함수와 유사한 특성을 가진다. 그외에도 Swift는 명시적인 액세스 컨트롤을 할 필요가 그리 많지 않다. 만약 단일 타깃 앱을 개발하고 있다면 명시적으로 액세스 컨트롤을 정의할 필요가 없다.더 보기 »Swift – Access Control

WWDC의 자동 메모이제이션 코드 분석

소수 판별이나 소인수분해와 같이 시간이 오래 소요될 수 있는 연산량이 큰 작업이 있고, 이 연산을 반복해서 수행할 일이 많을 때 성능을 개선할 수 있는 가장 손쉬운 방법으로는 연산 결과를 캐싱하는 것이 있을 수 있다. 즉 함수의 외부에 사전과 같은 캐시 저장소를 하나 준비해 두고 입력값을 키로 캐시값을 감사하여 있으면 사용, 없으면 원래 함수 코드를 실행하여 캐시값을 기록하고 리턴하는 방식을 사용하는 것이다. 이는 일일이 그러한 함수를 작성하기 보다는 클로저를 인자로 받아 클로저를 리턴하는 함수를 사용하여 조금 더 유연하게 사용할 수 있다.… 더 보기 »WWDC의 자동 메모이제이션 코드 분석

Swift :: 문자열로부터 Int/Double 타입 값 얻기

문자열의 숫자를 값으로 변환하기 Int 타입의 경우에는 String.toInt() 메소드가 있어서 Int? 타입의 값을 얻을 수 있다. 당연히 toDouble() 메소드가 있을 줄 알았는데, swiftstub.com에서는 이런 멤버가 없다는 에러가 나왔다.  Swift 2.0 부터는 문자열의 toInt()가 제거되고, Int, Double의 생성자에 문자열을 넣어 옵셔널 타입을 얻을 수 있게 되었다.   let str = "123456" let strInt = Int(str) // Optional(123456) let strDouble = Double(str) // Optional(123456) 하지만 아래의 방법 역시 여전히 유효하긴하다. NSString의 -doubleValue를 이용한다. (2.0에서 제거됨) NSNumberFormatter를 이용한다.   let str = "123.456"… 더 보기 »Swift :: 문자열로부터 Int/Double 타입 값 얻기

오일러 프로젝트 14

우박수 양의 정수 n에 대하여, 다음과 같은 계산 과정을 반복하기로 합니다. n → n / 2 (n이 짝수일 때) n → 3 n + 1 (n이 홀수일 때) 13에 대하여 위의 규칙을 적용해보면 아래처럼 10번의 과정을 통해 1이 됩니다. 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1 아직 증명은 되지 않았지만, 이런 과정을 거치면 어떤 수로 시작해도 마지막에는 1로 끝나리라 생각됩니다. (역주: 이것은 콜라츠 추측 Collatz Conjecture이라고 하며, 이런… 더 보기 »오일러 프로젝트 14

enum in Swift

Enumerations

Enumeration(열거) 타입은 서로 연관을 맺고 있는 특정한 값들의 그룹을 의미한다. C의 enum과 비슷하다고 할 수 있는데, 그것보다는 하스켈의 대수타입과 보다 더 닮아있다.
C의 enum의 개념에 익숙하다면, C에서는 enum이 일련의 정수에 대해서 고유의 이름을 붙이는 것과 같다는 것을 알 수 있다. 하지만 Swift에서는 보다 유연한데, 각각의 멤버에 대해서 고유한 값을 붙일 수 있으며(물론 붙이지 않아도 상관없다) 이 값은 정수 뿐만 아니라 실수나 문자열, 유니코드 문자가 될 수도 있다.
또한, 열거 멤버 하나하나가 대수 데이터 타입으로 쓰일 수도 있다. 연관이 있는 멤버들을 하나의 열거 타입에 정의하되, 각각의 멤버는 다시 멤버를 구성하고 있는 하나 혹은 그 이상의 다른 값의 세트를 가질 수 있다.
열거 타입은 Swift에서 일급 객체이며, computed property 라든지, 인스턴스 메소드를 가질 수 있다. 또 initializer를 정의하여 기본적인 초기값을 가지고 생성될 수도 있다.더 보기 »enum in Swift

두 수 사이의 구간을 만드는 stride 함수 (Swift)

stride() 함수는 파이썬의 range() 함수처럼 특정한 닫힌 구간에서 임의의 간격으로 나열된 숫자들을 표현하는 시퀀스 타입을 생성하는 함수이다. func stride<T: Strideable>(from start:T, to end: T, by stride: T.Stride) -> StrideTo<T> 혹은 func stride<T:Strideable>(from start:T, through end: T, by stride: T.Stride) -> StrideThrogh<T> to: 를 쓰면 최종값이 범위에 포함되지 않으며, through:를 쓰면 최종값이 범위에 포함된다. 업데이트: Swift3로 넘어오면서 다시 자유함수로 넘어오게 되었다. is unavailable: Use stride(from:to:by:) free function instead for i in 1.stride(to:22, by:7) { print(i) } ^~~~~~ Swift.Strideable:3:17: note: 'stride(to:by:)' has… 더 보기 »두 수 사이의 구간을 만드는 stride 함수 (Swift)