2015-05-05 3 views
3

Ниже приведен код, который я изо всех сил, чтобы понять:Swift: Снижение функции с закрытием

let rectToDisplay = self.treasures.reduce(MKMapRectNull) { //1 
    (mapRect: MKMapRect, treasure: Treasure) -> MKMapRect in //2 

    let treasurePointRect = MKMapRect(origin: treasure.location.mapPoint, size: MKMapSize(width: 0, height: 0)) //3 

     return MKMapRectUnion(mapRect, treasurePointRect) 
    } 

Мое понимание снижения функции является:

var people [] // an array of objects 
var ageSum = 0 
ageSum = people.reduce(0) { $0 + $1.age} 

//(0) = initial value 
//$0 = running total 
//$1 = an object in an array 

Мое понимание закрытия является:

{ (params) -> returnType in 
    statements 
} 

Мое понимание для кода на вершине:

// 1 = начальное значение для функции уменьшения устанавливается в (MKMapRectNull)

// 2 = Вместо нарастающим итогом и объект в массиве, замыкание передается с использованием двух аргументов, которая возвращает MKMapRect:

(mapRect: MKMapRect, treasure: Treasure) -> MKMapRect 

// 3 = Это где я застрял. На структуру, MKMapRect, вызывается с двумя параметрами origin: treasure.location.mapPoint и size: MKMapSize(width: 0, height: 0)

Вопрос 1: Как MKMapSize вычислить, если значения, передаваемые в это 0,0? Как получить последующие значения и добавить их?

Вопрос 2: Когда эта линия возвращается //2 closurereturn MKMapRectUnion(mapRect, treasurePointRect), как это стало нарастающим итогом и как он знает, чтобы добраться до следующего элемента self.treasures?

ответ

7

Ответ 2:

Первый аргумент второй (третий, четвертый) вызов к закрытию является результатом на выход предыдущего вызова к закрытию. Единственным исключением является первый вызов, у которого нет предыдущего вызова наследования, поэтому сокращение принимает значение 0 в качестве второго аргумента - это специальное значение для подачи на первый вызов.

Давайте представим себе следующий сценарий - у вас есть массив чисел:

let a = [1,2,3] 

И вы хотите, чтобы найти сумму с помощью уменьшения:

let sum = reduce(a,0) { (accumulator, nextValue) in accumulator + nextValue } 

Итак, давайте посмотрим, что происходит при каждом вызове:

call# acc next result 
1  0  1  0+1 -> 1  # the zero is from reduce's second arg 
2  1  2  1+2 -> 3  # the 1 is from the previous result 
3  3  3  3+3 -> 6 

Теперь у нас закончились элементы для обработки, поэтому мы возвращаем окончательное значение 6, ч действительно сумма 1,2 и 3


Давайте представим немного более сложный сценарий - добавив ряд отформатированных числовых значений в строку.Вот уменьшить:

let sum = reduce(a,"") { (accumulator, nextValue) in accumulator + nextValue } 

Это выглядит почти идентично, но вы заметите, что первоначальный установлен в "" вместо 0. Оператор + Теперь объединяет строки и Int.

call# acc next result 
1  ""  1  ""+1 -> "1" 
2  "1"  2  "1"+2 -> "12" 
3  "12" 3  "12"+3 -> "123" 

И мы закончили, и можем распечатать строку, или что угодно.


Теперь давайте посмотрим на ваш первый вопрос!

Добавление ряда точек к карте аналогично (но не совсем так же, как) добавлению чисел вместе; это ближе к примеру строки, где у аккумулятора есть другой тип (строка/карта) из элементов массива (целое/сокровище).

Вы можете добавить «серый серый череп» к пустой карте, а затем добавить «тенистую бухту» к карте с серым черепом на ней, а затем добавить «местоположение сокровищ» на карту с «серым черепом замка», и «теневые бухта» уже нарисованы на ней. Тогда вы сделали, и вы можете начать поиск сокровищ.

Ваше начальное значение не равно нулю, (или «»), но пустая карта.

Когда добавляется новая точка (rect), она добавляется к карте , которая имеет предыдущую точку на ней, она не добавляется непосредственно к предыдущей точке.

Предыдущий пункт остается на карте, без изменений! у него просто новый маркер карты, чтобы поделиться историями.

Что касается вашего вопроса относительно того, как прямоугольник с нулевым размером может что-либо сделать, я предполагаю, что это точно так же, как точка.

+0

Спасибо за подробный ответ. Я все еще запутался относительно того, как изменяется значение MKMapSize (width: 0, height: 0)? – user1107173

+1

Alex справа - прямоугольник с нулевой шириной и высотой - это, по сути, просто точка (ее начало). Изменение происходит с вызовом 'MKMapRectUnion()', так как он возвращает 'MKMapRect', который включает оба параметра. Даже если оба параметра действительно являются точками, объединение будет прямоугольником, содержащим обе точки. –

+0

Получил это. Я просто искал MKMapRect и возвращает начало и размер. Который, по моему мнению, станет следующим значением для второго вызова. – user1107173

3

Если это помогает о reduce думать с императивной точки зрения, это, по сути, что делает ваш код:

var rectToDisplay = MKMapRectNull 
for treasure in self.treasures { 
    let treasurePointRect = MKMapRect(origin: treasure.location.mapPoint, size: MKMapSize(width: 0, height: 0)) 
    rectToDisplay = MKMapRectUnion(rectToDisplay, treasurePointRect) 
} 
Смежные вопросы