the programming language guidelines book types coding-style swift type-safety

types - guidelines - the swift programming language 4.2 pdf



¿Por qué la guía de lenguaje de Swift sugiere usar Int "incluso cuando se sabe que los valores no son negativos"? (2)

Esta es una pregunta sobre el estilo de programación en Swift, específicamente Int vs UInt .

La Guía de Lenguaje de Programación de Swift aconseja a los programadores que utilicen el tipo entero con signo genérico Int incluso cuando se sabe que las variables no son negativas. De la guía :

Use UInt solo cuando necesite específicamente un tipo de entero sin signo con el mismo tamaño que el tamaño de palabra nativo de la plataforma. Si este no es el caso, se prefiere Int, incluso cuando se sabe que los valores almacenados son no negativos. Un uso constante de Int para valores enteros ayuda a la interoperabilidad del código, evita la necesidad de convertir entre diferentes tipos de números y hace coincidir la inferencia del tipo entero, como se describe en Seguridad de tipos e Inferencia de tipos.

Sin embargo, UInt será de 32 bits sin firma en arquitecturas de 32 bits y de 64 bits sin firmar en arquitecturas de 64 bits, por lo que no hay beneficio en el rendimiento al usar Int sobre UInt .

Por el contrario, la guía Swift da un ejemplo posterior:

dejar edad = -3
assert (edad> = 0, "la edad de una persona no puede ser menor a cero")
// esto hace que se active la aserción, porque la edad no es> = 0

Aquí, un problema de tiempo de ejecución podría ser capturado en tiempo de compilación si el código se hubiera escrito como:

let age:UInt = -3 // this causes a compiler error because -3 is negative

Hay muchos otros casos (por ejemplo, cualquier cosa que indexará una colección) donde usar un UInt atraparía problemas en tiempo de compilación en lugar de tiempo de ejecución.

Entonces la pregunta: ¿el consejo en la guía de Swift Programming Language es correcto, y los beneficios de usar Int "incluso cuando los valores almacenados son conocidos como no negativos" superan las ventajas de seguridad de usar UInt ?

Nota adicional: Habiendo utilizado Swift por un par de semanas, está claro que se requiere interoperabilidad con Cocoa UInt . Por ejemplo, el marco de AVFoundation utiliza enteros sin signo en cualquier lugar donde se requiera un "conteo" (número de muestras / cuadros / canales, etc.). La conversión de estos valores a Int podría provocar errores graves en los que los valores son mayores que Int.max


En su pregunta, dice: "Un uso constante de Int para valores enteros ayuda a la interoperabilidad del código, evita la necesidad de convertir entre diferentes tipos de números y hace coincidir la inferencia de tipos enteros, como se describe en Tipo de seguridad y tipo de inferencia".

Esto evita problemas como la asignación de un Int a un UInt. Los valores Int negativos asignados a UInts dan como resultado valores grandes en lugar del valor negativo deseado. La representación binaria de ambos no diferencia un tipo del otro.

Además, ambas son clases, una no desciende de la otra. Las clases creadas reciben Ints no pueden recibir UInts sin sobrecarga, lo que significa que la conversión entre las dos sería una tarea común de UInts que se utilizan cuando la mayoría del framework recibe Ints. Convertir entre los dos también puede convertirse en una tarea no trival.

Los dos párrafos anteriores hablan de "interoperabilidad" y "conversión entre diferentes tipos de números". Problemas que se evitan si no se utilizan UInts.


No creo que usar UInt sea tan seguro como crees que es. Como anotó:

let age:UInt = -3

da como resultado un error de compilación. También probé:

let myAge:Int = 1 let age:UInt = UInt(myAge) - 3

que también resultó en un error de compilación. Sin embargo, los siguientes escenarios (en mi opinión, mucho más comunes en los programas reales) no tuvieron errores de compilación, pero en realidad resultaron en errores en el tiempo de ejecución de EXC_BAD_INSTRUCTION :

func sub10(num: Int) -> UInt { return UInt(num - 10) //Runtime error when num < 10 } sub10(4)

tanto como:

class A { var aboveZero:UInt init() { aboveZero = 1 } } let a = A() a.aboveZero = a.aboveZero - 10 //Runtime error

Si estos hubieran sido simples Int , en lugar de colgarse, podría agregar código para verificar sus condiciones:

if a.aboveZero > 0 { //Do your thing } else { //Handle bad data }

Incluso podría llegar a equiparar sus consejos contra el uso de UInt s con sus consejos contra el uso de opcionales no envueltos implícitamente: No lo hagas a menos que estés seguro de que no obtendrás ningún elemento negativo, porque de lo contrario obtendrás errores de tiempo de ejecución ( excepto en el caso más simple).