Tracks
/
Julia
Julia
/
Temario
/
Caracteres
Ca

Caracteres en Julia

4 ejercicios

Acerca de Caracteres

¡Este es un tema enorme! Es posible escribir un libro largo sobre él, y varias personas lo han hecho (busca «unicode book» en Amazon para ver algunos ejemplos).

Una historia muy breve

Manejar caracteres en las computadoras era mucho más sencillo en décadas anteriores, cuando quienes programaban asumían que el inglés era el único idioma importante. Así que: 26 letras, mayúsculas y minúsculas, 10 dígitos, varios signos de puntuación, más un código (0x07) para hacer sonar una campana, y todo cabía en 7 bits: el conjunto de caracteres ASCII.

Naturalmente, la gente empezó a preguntar qué pasaba con à, ä y Ł, luego otras personas empezaron a preguntar por ऄ, ஹ y ญ, y los jóvenes querían emojis 😱. ¿Qué hacer?

Para abreviar una historia larga, muchas personas inteligentes y pacientes tuvieron que formar parte de comités durante años, resolviendo los detalles del conjunto de caracteres Unicode y de codificaciones como UTF-8, y muchísimo software necesitó una reescritura muy complicada. Además, se introdujeron muchos bugs nuevos.

Para evitar que todo se rompa, el diseño de Unicode/UTF-8 garantiza que los primeros 127 códigos sean idénticos a ASCII (incluso la campana).

Los caracteres en Julia

Los lenguajes diseñados después de 2005 aproximadamente tienen la enorme ventaja de que ya existía un estándar Unicode razonablemente estable.

Julia (publicado por primera vez en 2012) pudo asumir que todo sería Unicode: caracteres, strings, nombres de variables y funciones, operadores matemáticos...

Para citar el manual, «Julia hace que tratar con texto ASCII simple sea sencillo y eficiente, y manejar Unicode es tan sencillo y eficiente como sea posible». Fíjate en el «como sea posible», es una parte importante de la afirmación.

Los literales de carácter se escriben entre comillas simples y son distintos de los strings escritos entre comillas dobles.

Esto es obvio para quienes vienen del mundo de C/C++, pero puede resultar confuso para quienes programan en Python y JavaScript.

julia> a = 'a'  # Roman alphabet
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

julia> typeof(a)
Char

julia> jha = 'झ'  # Devanagari alphabet
'झ': Unicode U+091D (category Lo: Letter, other)

julia> typeof(jha)
Char


julia> '❤'  # heart emoji
'❤': Unicode U+2764 (category So: Symbol, other)

Podemos ver en los ejemplos que el tipo es Char, y Julia tiene más información sobre la categoría del carácter.

Si miramos con más detalle, parece que estos caracteres se pueden representar con 4 dígitos hexadecimales. El conjunto completo de caracteres necesita hasta 6 dígitos hexadecimales.

Estos números se llaman «puntos de código» y actualmente van de U+0000 a U+10FFFF. Se muestran en el REPL, pero dentro del código usa codepoints() para obtenerlos.

Convertir entre Char e Int es sencillo:

julia> Int('a')
97

julia> Char(97)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

El compilador permite algunas formas de aritmética de enteros con Char:

julia> 'b' - 'a'  # interval, in alphabetic order
1

julia> 'b' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

julia> 'a' + 5
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)

julia> 'f' + ('A' - 'a')  # same as `uppercase('f')`
'F': ASCII/Unicode U+0046 (category Lu: Letter, uppercase)

Funciones para caracteres

Un subconjunto de las funciones para manejar strings también puede trabajar con argumentos de tipo Char.

islowercase('A')  # false
uppercase('γ')  # 'Γ': Unicode U+0393 (category Lu: Letter, uppercase)
ispunct('@')  # true
isdigit('A')  # false
isxdigit('A')  # true

Para comprobar si un carácter está presente en un string, tenemos in. Nota que esto es distinto de las subcadenas:

# char search
julia> 'a' ∈ "xabcahliazlnkiw"
true

# substring search
julia> "a" ∈ "xabcahliazlnkiw"
use occursin(needle, haystack) for string containment

Además, las expresiones regulares (el tema de otro concepto) permiten búsquedas y manipulaciones potentes.

Interconversiones entre vectores de Char y strings

Para pasar de un string a un vector de Char, podemos usar collect().

Para pasar de un vector de Char a un string, está el constructor String().

julia> s = "abcde"
"abcde"

julia> cv = collect(s)
5-element Vector{Char}:
 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)

julia> String(cv)
"abcde"

Esto funciona con cualquier carácter, no solo con ASCII.

julia> collect("❤,😱")
3-element Vector{Char}:
 '❤': Unicode U+2764 (category So: Symbol, other)
 ',': ASCII/Unicode U+002C (category Po: Punctuation, other)
 '😱': Unicode U+1F631 (category So: Symbol, other)

Nota que el constructor String() opera sobre un vector. Para convertir un solo Char a un string de 1 carácter, la función es string(), con s minúscula.

julia> string('a')
"a"

Almacenamiento

Todo lo que hemos visto hasta ahora en este documento parece relativamente sencillo, entonces ¿de verdad no hay mucho de qué preocuparse?

Por desgracia, ¡eso es demasiado optimista!

Una complicación viene de la necesidad de «hasta» 6 dígitos hexadecimales por punto de código. Esto significa que distintos caracteres necesitan distintas cantidades de espacio en memoria cuando se codifican en UTF-8.

Un byte solo puede almacenar números (sin signo) de hasta 255, dos dígitos hexadecimales, así que UTF-8 usa un número variable de bytes (de 1 a 4) para almacenar un Char. A estos se les llama «unidades de código», y la función ncodeunits() devolverá el número que se necesita para un carácter dado.

julia> codepoint(jha)  # jha 'झ' is defined in an earlier example
0x0000091d

julia> ncodeunits(jha)
3

julia> ncodeunits('a')  # ASCII character
1

julia> ncodeunits('😱')  # emoji
4

Además, no todo lo que se puede mostrar en pantalla tiene su propio punto de código único. Algunos caracteres visualmente distintos se consideran derivados de otros, así que Unicode los trata como un carácter base más un modificador.

Editar en GitHub El enlace se abre en una ventana o pestaña nueva

Aprende Caracteres

La práctica está bloqueada

Desbloquea 3 ejercicios más para practicar Caracteres