2016-10-13 5 views
1

기능적 스타일에서 Swift를 사용하려면 목록의 headtail을 어떻게 처리해야합니까? ArrayArraySlice이 적절합니까 (ArraySlice은 하위 목록을 가져 오는 효율적인 메커니즘이므로) ArrayArraySlice으로 변환하고 .first!.dropFirst()headtail과 동등한 것으로서 변환하는 올바른 방법은 무엇입니까? 번호 목록을 추가하는 예를 들어Swift와 함께 첫 번째/머리와 나머지/꼬리를 사용하는 방법?

는 :

func add(_ nums: ArraySlice<Int>) -> Int { 
    if nums.count == 0 { 
     return 0 
    } else { 
     return nums.first! + add(nums.dropFirst()) 
    } 
} 
+0

귀하의 질문에 만족합니까? – Alexander

답변

3

Array는 이러한 ArraySlice 같은 임의 Sequence에서 Array 생산할 수 이니셜 라이저 (init(_:))을 갖는다.

func sum(_ nums: [Int]) -> Int { 
    guard let head = nums.first else { return 0; } //base case, empty list. 
    return head + sum(Array(nums.dropFirst())) 
} 

let input = Array(1...10) 
let output = sum(input) 
print(output) 

하지만 실제로는 matt이 말했듯이하지 마십시오. 프로그래밍에 대한 머리/꼬리 접근법은 패턴 매칭, 좋은 컴파일러 최적화, 꼬리 호출 최적화 등과 같은 언어에서 유용합니다. Swift의 디자인은 reduce을 사용하도록 장려합니다. 더 짧고 훨씬 더 읽기 쉬울뿐만 아니라 더 효과적입니다.

는 비교를 위해, 여기에 전형적인 신속한 접근이하는 것입니다 무엇 :

extension Sequence where Iterator.Element: Integer { 
    func sum() -> Iterator.Element { 
     return self.reduce(0, +) 
    } 
} 
  • 그것은 간단하고 짧은입니다. 그냥 어떤 Integer 유형뿐만 아니라 Int 이상 Array
  • 그것은 일반의에 한정되는 것이 아니라, 어떤 Sequence 도와 드리겠습니다 있도록

  • 그것은 다형성입니다. 그래서이 모든 작업은 :

    print(Array<UInt> (1...10).sum()) 
    print(Array<UInt8> (1...10).sum()) 
    print(Array<UInt16>(1...10).sum()) 
    print(Array<UInt32>(1...10).sum()) 
    print(Array<UInt64>(1...10).sum()) 
    print(Array< Int> (1...10).sum()) 
    print(Array< Int8> (1...10).sum()) 
    print(Array< Int16>(1...10).sum()) 
    print(Array< Int32>(1...10).sum()) 
    print(Array< Int64>(1...10).sum()) 
    

그러나이 헤드/테일 접근 방식을 가지고 주장하는 경우,이 시도 :

extension Array { 
    func HeadTail<ReturnType>(_ closure: (Element?, [Element]) -> ReturnType) -> ReturnType { 
     return closure(self.first, Array(self.dropFirst())) 
    } 
} 

func sum(_ nums: [Int]) -> Int { 
    return nums.HeadTail { head, tail in 
     guard let head = head else { return 0 } //base case, empty list 
     return head + sum(tail) 
    } 
} 

print(sum(Array(1...10))) 

HeadTail(_:)이 목록으로 분할 방법의 세부 사항을 멀리 추상화 머리 꼬리가있어서 sum이라고 쓰면, headtail에 대해서만 걱정할뿐입니다.

+0

흥미로운 'Array' 클래스의 확장. 'reduce'는 모든 반복과 재귀 요구를 해결하지 못하기 때문에 관련이 없습니다. –

+0

@at. 나는 당신의 질문에 대답 했습니까? – Alexander

+0

예, Swift에서 좀 더 우아한 '머리'와 '꼬리'메커니즘을 원했지만 어쩌면 이것은 우아한 것입니다. –

1

귀하의 예제와 문제는 당신이 하지 사용 headtail 숫자의 목록을 추가하는 것입니다. 당신은 reduce를 호출 할 것입니다 : 우리가headtail 필요

let nums = [1,2,3,4,5] 
let sum = nums.reduce(0,+) 

을 그래서, LISP의로 좋아 해요 동안/다음 사람이 같은 계획, 당신은 주어진,보다 설득력있는 사례가 필요합니다 우리는 map, filterreduce (등등)을 가지고 있습니다.

+0

이것은 교육용 샘플이었습니다. –

+1

그건 내가 말한거야. 좋은 샘플이 아니에요. 더 강력한 사건이 필요합니다. – matt

+0

@matt ok는'reduce'의 구현을 보여줍니다. 왜'reduce'가 존재하기 때문에리스트를 반복하는 기본 재귀 함수가 "강제적 인 경우"가 아닌지 알 수 없습니다. – naomik