Racket: Символы
Любой текст в Racket представлен типом string
, который представляет собой список фиксированной длины, состоящий из символов — значений типа char
.
И вот тут придётся сразу же предупредить: в русском языке слова "character" (если речь идёт о части строки) и "symbol" имеют один и тот же перевод — "символ". Вот только в Racket и других языках семейства lisp есть отдельная сущность
symbol
и именно её принято называть "символом". Поэтому далее в тексте вы будете встречать либо "строковый символ", либо имя типа, то есть "char". Так будет проще избежать подмены понятий.
Итак, строки состоят из строковых символов. Как же выглядят эти символы сами по себе в виде литералов? Когда речь идёт о печатных символах (printable characters), то любой из оных можно представить в виде символов (ага, опять синоним!) "#\" плюс самого желаемого символа:
(displayln #\a) ; => a
(displayln #\1) ; => 1
(displayln #\,) ; => ,
(displayln #\)) ; => )
(displayln #\\) ; => \
(displayln #\#) ; => #
Как видите, нет проблем с закрывающими скобками и самими #
и \
— любой печатный символ может быть закодирован таким образом.
Но как же указать в виде литерала пробел, табуляцию, или перевод строки? Для символа "пробела" ("space") и большинства управляющих символов (control characters) можно указать их имя после #\
:
#\space ; это пробел
#\newline ; a это — перевод строки
Кроме того, любой из символов Unicode можно указать, используя его код в восьмеричном или шестнадцатеричном представлении:
(displayln #\λ) ; => λ
(displayln (integer->char 955)) ; => λ
(displayln #\u3BB) ; => λ
(displayln #\n) ; => n
(displayln #\156) ; => n
Здесь функция integer->char
преобразует десятичное число в строковый символ с кодом 955 (греческая буква "лямбда"). Запись 3BB
— это то же, что 955, только в шестнадцатеричной форме. 156 — восьмеричный код ASCII-символа "n".
А вот #\955
использовать не получится: восьмеричным числом можно задавать только коды в диапазоне 0...377, то есть символы таблицы ASCII. Но символы Unicode повсеместно принято указывать в шестнадцатеричном виде, поэтому данное ограничение не вызывает больших неудобств.
В дополнение к integer->char
Racket предоставляет и функцию char->integer
, которая вычисляет десятичный код символа. Такие функции преобразования одного типа в другой можно встретить очень часто, и во многих случаях функции идут подобными парами.
Задание
Реализуйте две функции, next-char
и prev-char
, которые вычисляют для символа-аргумента следующий и предыдущий символы (с точки зрения десятичного кода).
Упражнение не проходит проверку — что делать? 😶
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя 🤔
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно 🙄
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.