четверг, 13 июня 2019 г.

Спецификация Go: постоянные выражения (constant expressions)

Постоянные выражения (constant expressions) могут содержать только постоянные операнды и вычисляются во время компиляции.

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

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

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

const a = 2 + 3.0          // a == 5.0   (нетипизированная константа с плавающей точкой)
const b = 15 / 4           // b == 3     (нетипизированная целочисленная константа)
const c = 15 / 4.0         // c == 3.75  (нетипизированная константа с плавающей точкой)
const Θ float64 = 3/2      // Θ == 1.0   (тип float64, 3/2 - это целочисленное деление)
const Π float64 = 3/2.     // Π == 1.5   (тип float64, 3/2. Это деление с плавающей точкой)
const d = 1 << 3.0         // d == 8     (нетипизированная целочисленная константа)
const e = 1.0 << 3         // e == 8     (нетипизированная целочисленная константа)
const f = int32(1) << 33   // недопустимо (константа 8589934592 переполняет int32)
const g = float64(2) >> 1  // недопустимо (float64(2) является типизированной константой с плавающей точкой)
const h = "foo" > "bar"    // h == true  (нетипизированная логическая константа)
const j = true             // j == true  (нетипизированная логическая константа)
const k = 'w' + 1          // k == 'x'   (нетипизированная рунная константа)
const l = "hi"             // l == "hi"  (нетипизированная строковая константа)
const m = string(k)        // m == "x"   (тип string)
const Σ = 1 - 0.707i       //            (нетипизированная комплексная постоянная)
const Δ = Σ + 2.0e-4       //            (нетипизированная комплексная постоянная)
const Φ = iota*1i - 1/1i   //            (нетипизированная комплексная постоянная)

Применение комплекса встроенных функций к нетипизированным константам целых чисел, рун или чисел с плавающей точкой позволяет получить нетипизированную комплексную константу.

const ic = complex(0, c)   // ic == 3.75i  (нетипизированная комплексная постоянная)
const iΘ = complex(0, Θ)   // iΘ == 1i     (тип complex128)

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

const Huge = 1 << 100         // Huge == 1267650600228229401496703205376  (нетипизированная целочисленная константа)
const Four int8 = Huge >> 98  // Four == 4                                (тип int8)

Делитель постоянной операции деления или остатка не должен быть равен нулю:

3.14 / 0.0   // недопустимо: деление на ноль

Значения типизированных констант всегда должны быть точно представлены значениями константного типа. Следующие константные выражения недопустимы:

uint(-1)    // -1 не может быть представлен как uint
int (3.14)  // 3.14 нельзя представить как int
int64(Huge) // 1267650600228229401496703205376 не может быть представлен как int64
Four * 300  // операнд 300 не может быть представлен как int8 (тип Four)
Four * 100  // произведение 400 не может быть представлен как int8 (тип Four)

Маска, используемая унарным оператором побитового дополнения ^, соответствует правилу для неконстант: маска - это все 1 (единицы) для констант без знака и -1 для констант со знаком и без типов.

^1         // нетипизированная целочисленная константа, равная -2
uint8(^1)  // недопустимо: то же самое, что и uint8(-2), -2 нельзя представить как uint8
^uint8(1)  // типизированная uint8 константа, то же самое, что и 0xFF ^ uint8(1) = uint8(0xFE)
int8(^1)   // то же самое, что и int8(-2)
^int8(1)   // то же самое, что и -1 ^ int8(1) = -2

Ограничение реализации: компилятор может использовать округление при вычислении нетипизированных выражений с плавающей точкой или сложных константных выражений. Это округление может привести к тому, что константное выражение с плавающей точкой будет недопустимым в целочисленном контексте, даже если оно будет целочисленным при вычислении с бесконечной точностью, и наоборот.


Читайте также:


Комментариев нет:

Отправить комментарий