Как работает литерал int Swift для вывода с плавающей точкой? - PullRequest
0 голосов
/ 18 сентября 2018

Свифт может выводить, что литералы int являются двойными или плавающими

let x: Float = 3

Он работает даже с арифметикой.Он преобразует все, прежде чем выполнять математику, так что это также 3:

let y: Float = 5/2 + 0.5

Но каковы действительные правила для этого?Существуют неоднозначные ситуации, например, если логический вывод относится к параметру:

func foobar(_ x: Int) -> Int {
  return x
}

func foobar(_ x: Float) -> Float {
  return y
}

foobar(1/2)

В этом случае он выводит его как int и возвращает 0, но если вы удаляете первую функцию, он переключается на float ивозвращает 0.5.

Каковы правила?Где это задокументировано?

Еще более раздражает то, что Swift может вывести его как поплавок, но не

func foobar(_ x: Float) -> Float {
   return x
}

let x = 1/2
foobar(x) // Cannot convert value of type 'Int' to expected argument type 'Float'

Ответы [ 3 ]

0 голосов
/ 18 сентября 2018

По умолчанию, передавая 1/2 в качестве аргумента, вы выполняете вычисление для двух Целых чисел , которое будет вычислять результат типа Целое , таким образом, первая используемая функция.

Чтобы иметь Float , один или все аргументы должны иметь тип Float, поэтому либо 1.0/2, либо 1/2.0, либо 1.0/2.0.Это приведет к запуску второй функции.

В let x = 1/2 вывод x относится к типу Int, поскольку оба типа 1 и 2 относятся к типу Int ,

Swift не будет пытаться вывести Float , если не указано иное.

0 голосов
/ 18 сентября 2018

Здесь есть два поведения Swift:

  1. Swift может вывести int литерал как type float, если необходимо (или double)
  2. Каждый литерал имеет тип по умолчанию , который используется в случае сбоя вывода.Тип для литералов int: Int

Только с одной функцией применяется правило 1.Он видит, что нужен float, поэтому он выводит деление как деление с плавающей точкой, а литералы int как плавающие:

func foobar(_ x: Float) -> Float {
  return y
}
foobar(1/2) // 0.5

Если вы перегружаете функцию, правило 1 больше не работает.Тип теперь неоднозначный, поэтому он возвращается к типу по умолчанию Int, который, к счастью, соответствует одному из определений:

func foobar(_ x: Int) -> Int {
  return x
}
func foobar(_ x: Float) -> Float {
  return y
}
foobar(1/2)  // 0

Посмотрите, что произойдет, если вы сделаете так, чтобы значение по умолчанию больше не работало.Ни одно из правил не применяется, поэтому вы получите ошибку:

func foobar(_ x: Double) -> Double {
  return x
}
func foobar(_ x: Float) -> Float {
  return y
}
foobar(1/2)  // Ambiguous use of operator '/'
0 голосов
/ 18 сентября 2018

Литералы не имеют типа как такового.Документы говорят:

Если нет подходящей информации о типе, Swift делает вывод, что тип литерала является одним из типов литералов по умолчанию, определенных в стандартной библиотеке Swift.Типами по умолчанию являются Int для целочисленных литералов, Double для литералов с плавающей запятой, String для строковых литералов и Bool для логических литералов.

Так что, если ваш аргумент explicity не говорит ничего, кроме Int, онбудет выводить целочисленные литералы как Int.


См. это для получения дополнительной информации, Лексическая структура - Литералы .

...