Топаз 5.21 удаляет глобальные функции вроде print, статические пространства имён вроде Math и FS и шесть стандартных модулей. Их вызовы переходят в методы значений и модули std. Сначала смените языковой режим, а затем исправляйте удалённые формы в тех местах, на которые укажет topaz check.
Установите Топаз и сохраните копии исходного кода, входных данных и результатов.
Смените языковой режим
В topaz.toml задайте для language и std значение "5.21".
[package]
language = "5.21"
[dependencies]
std = "5.21"Топаз 5.21 принимает только языковой режим topaz-5.21. Пакет, оставшийся в языковом режиме 5.20, останавливается с ошибкой unsupported language mode. Отдельный файл без topaz.toml уже проверяется по правилам 5.21.
Найдите удалённые формы
Этот файл всё ещё вызывает print, удалённый в 5.21.
print("ready")Сохраните его как old-forms.tpz и проверьте.
topaz check old-forms.tpzДля удалённого вызова, как print здесь, средство проверки сообщает TPZ5002 и называет вызов для 5.21. Для импорта удалённого стандартного модуля, например import std.math, оно сообщает TPZ3001 и называет методы, которые его заменяют.
error[TPZ5002]: `print` is not bound; import std.io and use io.writeLine(value) in 5.21
--> old-forms.tpz:1:1
|
1 | print("ready")
| ^^^^^
old-forms.tpz: 1 type diagnosticИсправьте файл по сообщению и сохраните его снова.
import std.io
io.writeLine("ready")Теперь topaz check old-forms.tpz завершается успешно, а topaz run old-forms.tpz печатает ready.
Замените удалённые формы
Замените форму из первого столбца формой из второго. Если в третьем столбце указан импорт, добавьте его один раз в начало файла.
| Удалено в 5.21 | Что писать вместо | Сначала импортируйте |
|---|---|---|
print(x) | io.writeLine(x) | import std.io |
input() | io.readStdin() | import std.io |
open(p) | io.open(p) | import std.io |
assert(c) | test.assert(c) | import std.test |
map(xs, f), filter(xs, f), reduce(xs, z, f) | xs.map(f), xs.filter(f), xs.reduce(z, f) | |
toFloat(n), toInt(s), toIntRadix(s, r), fromCodePoint(n) | n.toFloat(), s.toInt(), s.toIntRadix(r), n.toCodePoint() | |
Math.sqrt(x), Math.abs(x), Math.sin(x), Math.cos(x), Math.tan(x), Math.isNaN(x), Math.isFinite(x) | x.sqrt(), x.abs(), x.sin(), x.cos(), x.tan(), x.isNaN(), x.isFinite() | |
Math.floor(x), Math.ceil(x), Math.round(x) | x.floor(), x.ceil(), x.round() | |
Math.parseFloat(s) | s.parseFloat() | |
Math.min(a, b), Math.max(a, b) | a.atMost(b), a.atLeast(b) | |
JSON.parse(s), JSON.stringify(v), JSON.parseAs<T>(s) | json.parse(s), json.stringify(v), json.parseAs<T>(s) | import std.json |
JSON.decode<T>(v) | v.decode<T>() | |
FS.readText(p), FS.writeText(p, text), FS.readBytes(p), FS.writeBytes(p, bytes), FS.list(p) | fs.readText(p), fs.writeText(p, text), fs.readBytes(p), fs.writeBytes(p, bytes), fs.list(p) | import std.fs |
CSV.parse(s), CSV.parseWithHeader(s), CSV.stringify(rows), CSV.stringifyWithHeader(rows, columns) | csv.parse(s), csv.parseWithHeader(s), csv.stringify(rows), csv.stringifyWithHeader(rows, columns) | import std.csv |
TOML.parse(s), TOML.stringify(v), TOML.fromJson(v) | toml.parse(s), toml.stringify(v), toml.fromJson(v) | import std.toml |
TOML.toJson(t) | t.toJson() | |
Test.assert(c), Test.assertEq(a, b), Test.assertNe(a, b), Test.assertContains(text, part) | test.assert(c), test.assertEq(a, b), test.assertNe(a, b), test.assertContains(text, part) | import std.test |
Test.assertOk(result), Test.assertErr(result), Test.assertSome(option), Test.assertNone(option), Test.assertGolden(name, actual) | test.assertOk(result), test.assertErr(result), test.assertSome(option), test.assertNone(option), test.assertGolden(name, actual) | import std.test |
Encoding.utf8Encode(s), Encoding.utf8Decode(b) | s.encodeUtf8(), b.decodeUtf8() | |
Encoding.hexEncode(b), Encoding.hexDecode(s) | b.toHex(), Bytes.fromHex(s) | |
Encoding.base64Encode(b), Encoding.base64Decode(s) | b.toBase64(), Bytes.fromBase64(s) | |
Hash.sha256(b), Hash.sha512(b), Hash.crc32(b) | b.sha256(), b.sha512(), b.crc32() | |
Hash.hmacSha256(key, data) | key.hmacSha256(data) | |
Codec.gzipCompress(b), Codec.gzipDecompress(b), Codec.deflateCompress(b), Codec.deflateDecompress(b) | b.gzipCompress(), b.gzipDecompress(), b.deflateCompress(), b.deflateDecompress() | |
Codec.deflateFixedCompress(b), Codec.zlibFixedCompress(b), Codec.reedSolomon255223Protect(b) | b.deflateFixedCompress(), b.zlibFixedCompress(), b.reedSolomon255223Protect() | |
Codec.zstdCompress(b, level), Codec.zstdDecompress(b) | b.zstdCompress(level), b.zstdDecompress() | |
Cli.hasFlag(args, name), Cli.option(args, name), Cli.options(args, name), Cli.positionals(args) | args.hasFlag(name), args.option(name), args.options(name), args.positionals() | |
Array.of(a, b) | [a, b] | |
Set.of(a, b) | set { a, b } | |
Map.new() | map {} | |
Bytes.encodeUtf8(s), Bytes.concat(a, b) | s.encodeUtf8(), a.concat(b) | |
BigInt.fromInt(n), Decimal.fromInt(n) | n.toBigInt(), n.toDecimal() | |
import std.math, import std.encoding, import std.hash, import std.codec, import std.cli | Удалите импорт и вызывайте методы из строк выше | |
import std.gen | [for x in lo..hi => x], [false, true] | |
topaz lispex run | lispex run для исходников Лиспекса, topaz lispex embed run для встроенного вычислителя | |
topaz lispex info | topaz lispex embed info |
x.floor(), x.ceil(), x.round() и x.trunc() возвращают int. Если нужно вещественное число, как у Math.floor(x), пишите x.floor().toFloat() и так же поступайте с ceil и round. Новое преобразование в целое проверяет диапазон результата.
std.bytes, std.path, std.regex, std.url, std.date, std.bigint и std.decimal экспортируют только типы. Их функции вызываются как методы значений или как функции типов, например Bytes.fromHex.
Пользовательские функции и импортированные пространства имён сохраняют объявленный смысл. Для вызова с именованными аргументами сначала сохраните выражения аргументов во временные значения в исходном порядке вычисления, а затем переносите получатель. Встроенную функцию, использованную как значение, замените явно типизированной лямбдой.
Перенесите исходный код, написанный до v5
Перенесите исходный код Топаза, написанный до v5, на текущий синтаксис вручную. Сохраняйте прежнее поведение и сравнивайте результаты после каждого изменения. Совместимые обновления продукта не требуют отдельного переноса исходников.
Перенесите один файл
В этом историческом примере использованы старые формы объявления и типа массива.
mut let имена: [string] = ["Ada"]
let первое = имена[0]Сохраните приведённый ниже код с текущим синтаксисом в рабочей папке как from-pre-v5.tpz.
import std.io
let mut имена: Array<string> = ["Ada"]
let первое: Option<string> = имена.get(0)
io.writeLine("{первое}")Выполните эти команды из той же папки.
topaz check from-pre-v5.tpz
topaz run from-pre-v5.tpzПроверка завершается с кодом 0. Запуск также завершается с кодом 0 и печатает следующий результат.
Some(Ada)имена.get(0) возвращает Option<string>. Первый элемент существует, поэтому результат равен Some(Ada). Индекс вне массива возвращает None. Прямая индексация массива также поддерживается и вызывает ошибку выполнения при выходе за границы. Выберите нужное программе поведение.
В документации помещайте старый код в блок text. Для текущего синтаксиса используйте блок topaz.
Запишите поведение перед изменением проекта
Запишите входные файлы, корни модулей, входные данные, ожидаемый вывод, ошибки выполнения, файловые и сетевые действия. Сохраните результаты запусков для сравнения. Отделите примеры на Rust, JavaScript и синтаксисе фреймворков от исходников Топаза.
Приведите исходный код и метаданные пакета к текущему режиму языка. Настройки пакета описаны в разделе Пакеты и зависимости. Прежний синтаксис смотрите в Классике, а нужную сейчас форму ищите в текущем руководстве.
Замените повторяющиеся формы
| Старая форма | Текущая форма | Что сохранить |
|---|---|---|
mut let x | let mut x | Возможность повторного присваивания привязке |
[T] | Array<T> | Тип элемента |
function(T) -> U | (T) -> U | Типы параметра и результата |
[head, ...tail] | [head, ..tail] | Остаток элементов в шаблоне списка |
args: ...T | ...args: T | Тип вариативного аргумента |
Анонимная function | (x: T) => expr | Параметры, результат и захваченные привязки |
s[i], s.length | s.scalars() и явные строковые API | Позиции и количество скаляров Unicode |
Обратные кавычки, ${expr} | Двойные кавычки, {expr} | Содержимое строки и интерполяцию |
Скаляр Unicode представляет одно значение Unicode и может отличаться от байта или видимого символа. Индексация и зарегистрированные теги шаблонов описаны в разделе Строки и шаблоны. Используйте self в тех местах, где его допускает текущее объявление метода.
Для обрабатываемых ошибок используйте Result, для отсутствующих значений используйте Option или тип с null. Различайте ошибки выполнения и возвращаемые значения ошибок. Перенесите очистку в defer или поддерживаемые конструкции using. Обновите import, export, видимость и инициализацию по разделу Модули и видимость.
Код других языков оставляйте в явно обозначенных шагах сборки или преобразования. Вставлять его в модуль Топаза как синтаксис Топаза нельзя.
Сравните переписанную программу
Выполните topaz check для изменённого исходника, затем запустите тесты проекта. Для файла выше сравните вывод с Some(Ada). Для проекта сравните сохранённые входные данные и результаты.
Проверьте инициализацию модулей, порядок обхода, позиции скаляров Unicode, числовые ошибки, очистку и разрешённые операции хоста. При диагностике исправьте указанное место по ссылке на текущий синтаксис. Если проверка прошла, но вывод отличается, изучите изменённую логику на тех же входных данных.
Соберите программу для нужных нативных сред, Web или Worker по разделу Результат сборки. Неподдерживаемые формы должны вызывать диагностику до создания результата сборки. Перенос завершён, когда проверки и тесты проходят, а каждая выбранная сборка ведёт себя ожидаемым образом.