Cuidado: termos do leigo à frente.
Esta explicação não é rigorosamente correta no nível de código mais básico. No entanto, foi revisado por um cara que realmente trabalha no Swift e ele disse que é bom o suficiente como uma explicação básica.
Portanto, quero tentar responder de forma simples e direta à pergunta "por que".
Para ser mais preciso: por que temos que marcar as funções de estrutura como mutating
quando podemos alterar os parâmetros de estrutura sem nenhuma palavra-chave de modificação?
Portanto, o quadro geral tem muito a ver com a filosofia que mantém o Swift rápido.
Você pode pensar nisso como o problema de gerenciar endereços físicos reais. Quando você muda seu endereço, se houver muitas pessoas que têm o seu atual, você deve avisar a todas que você se mudou. Mas se ninguém tiver seu endereço atual, você pode simplesmente ir para onde quiser e ninguém precisa saber.
Nessa situação, o Swift é como um correio. Se muitas pessoas com muitos contatos se movimentam muito, a sobrecarga é muito alta. É necessário pagar uma grande equipe para lidar com todas essas notificações, e o processo exige muito tempo e esforço. É por isso que o estado ideal de Swift é que todos em sua cidade tenham o mínimo de contatos possível. Assim, ele não precisa de uma grande equipe para lidar com as alterações de endereço e pode fazer todo o resto de maneira mais rápida e melhor.
É também por isso que o pessoal da Swift está falando a respeito de tipos de valor versus tipos de referência. Por natureza, os tipos de referência acumulam "contatos" em todos os lugares, e os tipos de valor geralmente não precisam de mais do que alguns. Os tipos de valor são "Swift" -er.
Então, de volta a pequena imagem: structs
. Structs são muito importantes no Swift porque podem fazer a maioria das coisas que os objetos podem fazer, mas são tipos de valor.
Vamos continuar a analogia do endereço físico imaginando um misterStruct
que vive em someObjectVille
. A analogia fica um pouco complicada aqui, mas acho que ainda é útil.
Portanto, para modelar a alteração de uma variável em a struct
, digamos que misterStruct
tenha cabelo verde e receba uma ordem para mudar para cabelo azul. A analogia fica complicada, como eu disse, mas mais ou menos o que acontece é que em vez de mudar misterStruct
o cabelo, a pessoa velha se muda e uma nova pessoa com cabelo azul entra, e essa nova pessoa começa a se chamar misterStruct
. Ninguém precisa receber uma notificação de mudança de endereço, mas se alguém olhar para esse endereço, verá um cara de cabelo azul.
Agora vamos modelar o que acontece quando você chama uma função em a struct
. Nesse caso, é como misterStruct
obter um pedido como changeYourHairBlue()
. Assim, o correio entrega a instrução de misterStruct
"mude seu cabelo para azul e diga-me quando terminar".
Se ele está seguindo a mesma rotina de antes, se está fazendo o que fazia quando a variável foi alterada diretamente, o que misterStruct
vai fazer é sair de sua própria casa e chamar uma nova pessoa de cabelo azul. Mas esse é o problema.
A ordem era "vá mudar seu cabelo para azul e me diga quando terminar", mas foi o cara verde que recebeu o pedido. Depois que o cara azul se muda, uma notificação de "trabalho concluído" ainda precisa ser enviada de volta. Mas o cara azul não sabe nada sobre isso.
[Para realmente entender essa analogia, algo horrível, o que tecnicamente aconteceu com o cara de cabelo verde foi que, depois que ele se mudou, ele imediatamente cometeu suicídio. Portanto, ele também não pode notificar ninguém de que a tarefa está concluída ! ]
Para evitar este problema, em casos como este única , Swift tem que ir diretamente para a casa naquele endereço e realmente mudar o cabelo do habitante atual . Esse é um processo completamente diferente do que apenas enviar um novo cara.
E é por isso que Swift deseja que usemos a mutating
palavra - chave!
O resultado final parece o mesmo para qualquer coisa que se refira à estrutura: o habitante da casa agora tem cabelo azul. Mas os processos para alcançá-lo são completamente diferentes. Parece que está fazendo a mesma coisa, mas está fazendo algo muito diferente. Está fazendo uma coisa que as estruturas do Swift em geral nunca fazem.
Portanto, para dar ao pobre compilador uma pequena ajuda, e não fazer com que ele descubra se uma função sofre mutação struct
ou não, por conta própria, para cada função de estrutura já existente, somos solicitados a ter pena e usar a mutating
palavra - chave.
Em essência, para ajudar a Swift a permanecer ágil, todos devemos fazer nossa parte. :)
EDITAR:
Ei cara / dudette que me rebaixou, eu apenas reescrevi completamente minha resposta. Se ficar melhor com você, você removerá o voto negativo?