Что это означает, если настройка мутирующей функции сама по себе равна другой функции - PullRequest
0 голосов
/ 03 июля 2019

Я изучал образец проекта Apple Arkit. Я пытался понять код, так как я все еще учусь. Я видел, что функция, устанавливающая ее самостоятельно равной другой функции, может кто-нибудь объяснить, что именно делают эти функции. Пожалуйста, кратко опишите подробно. В коде «мутирующий func normalize ()» устанавливает self в self.normalized почему это так. Что делает этот код Разве мы не можем просто вызвать «func normalized ()», похоже, что мы воссоздаем ту же функцию.

mutating func normalize() {

   self = self.normalized()
}


func normalized() -> SCNVector3 {

    if self.length() == 0 {
      return self
  }
    return self / self.length()
}



func length() -> CGFloat {

    return sqrt(self.x * self.x + self.y * self.y)

    }

Ответы [ 2 ]

1 голос
/ 03 июля 2019

Типы значений в Swift могут быть изменяемыми и неизменяемыми. Поэтому, когда вы создаете структуру (или любой другой тип значения) и присваиваете ее переменной (var), она изменчива, и вы вызываете normalize () для нее. Это означает, что структура не будет скопирована в другой мир памяти и будет обновлена ​​на месте (будет действовать как ссылочный тип). Но когда вы присваиваете его константе (let) - его нельзя изменить, поэтому единственный способ обновить значения в этой структуре - создать новый с обновленными значениями, как в методе normalized (). Что касается вашего вопроса - normalize () - это просто повторное использование логики для нормализации вектора из normalized (). Так что это совершенно прекрасное решение. Назначение себя разрешено только в изменяемых методах. Это в основном переписывает значение struct с новым.

0 голосов
/ 03 июля 2019

Я предполагаю, что этот фрагмент находится в struct, а не в классе.

self.normalized() делает копию self и делит компоненты копии по длине, а затем возвращает копию,self не затрагивается.

self.normalize() получает нормализованную версию self, а затем заменяет self на копию.Таким образом, оно меняется на месте.

Под капотом каждая функция-член передает self в качестве неявного аргумента.то есть для компилятора объявление выглядит так:

func normalised(self: SCNVector3) -> SCNVector3

Помещение mutating в начало определения функции создает скрытый аргумент inout

func normalise(self: inout SCNVector3)

Итак, если выиметь

var a = SCNVector3(3, 4, 0)
let b = SCNVector3(4, 3, 0)
let c = b.normalized() 
a.normalize()

После этого кода c будет (0.8, 0.6, 0), а a будет (0.6, 0.8, 0).b не изменится.

Обратите внимание, что a должен быть объявлен с var, потому что он изменяется на месте с помощью normalise()

Редактировать

В комментариях хан спрашивает:

Я не могу понять, почему мы должны снова создать функцию, мы можем использовать «нормализованную функцию»

Смысл в том, почему мы не можем сделать что-то вроде этого:

    var a = SCNVector3(3, 4, 0)
    a = a.normalized()

и вообще не иметь функции normalise()?

Выше будет точнотот же эффект, что и a.normalize(), и, на мой взгляд [1], это лучший стиль, более "функциональный".

Я думаю, что a.normalize() существует только потому, что в Swift обычно используются обе формы функции.Например, с наборами у вас есть и union(), и formUnion(): первый возвращает объединение одного набора с другим, второй заменяет набор на объединение самого себя и другого набора.В некоторых случаях версия функции «на месте» может быть более эффективной, но я думаю, что не с этой normalize функцией.

То, что вы решите использовать, зависит от ваших предпочтений.


[1] На самом деле, лучший стиль -

let a = SCNVector3(3, 4, 0).normalized()
...