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 los ordenadores era mucho más sencillo en décadas anteriores, cuando los programadores suponí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 y un código (0x07) para hacer sonar una campana, y todo cabía en 7 bits: el conjunto de caracteres ASCII.

Como es natural, 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 resumir una larga historia, muchas personas inteligentes y pacientes tuvieron que participar en comités durante años para definir los detalles del conjunto de caracteres Unicode y de codificaciones como UTF-8, y mucho software necesitó una reescritura muy complicada. Además, se introdujeron muchos bugs nuevos.

Para evitar que todo se rompiera, 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 dar por hecho que todo sería Unicode: caracteres, strings, nombres de variables y funciones, operadores matemáticos...

Para citar el manual, «Julia hace que trabajar 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)

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

Si nos fijamos mejor, parece que estos caracteres se pueden representar con 4 dígitos hexadecimales. El conjunto de caracteres completo 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 los 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 funcionar con una entrada 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. Fíjate en 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.

Conversiones entre Char Vector y String

Para pasar de String a Char Vector, podemos usar collect().

Para pasar de Char Vector a String, existe 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)

Fíjate en que el constructor String() opera sobre un Vector. Para convertir un único Char en un string de 1 carácter, la función es string(), con la s minúscula.

julia> string('a')
"a"

Almacenamiento

Todo lo visto hasta ahora en este documento parece relativamente sencillo, así que ¿de verdad hay poco de lo que preocuparse?

Por desgracia, esto 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. Estos se llaman «unidades de código», y la función ncodeunits() devuelve el número necesario 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 nueva ventana o pestaña

Aprende Caracteres

La práctica está bloqueada

Desbloquea 3 ejercicios más para practicar Caracteres