Rutas
/
Julia
Julia
/
Ejercicios
/
Impecable
Impecable

Impecable

Ejercicio de aprendizaje

Introducción

¡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 daban por sentado 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, además de 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 abreviar una larga historia, 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 un montón de 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 sentado que todo sería Unicode: caracteres, strings, nombres de variables y funciones, operadores matemáticos...

Citando el manual: «Julia makes dealing with plain ASCII text simple and efficient, and handling Unicode is as simple and efficient as possible». Fíjate en el «as possible»: 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 evidente 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 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 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 Chars:

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

Muchas funciones de manejo de strings también pueden trabajar con una entrada de tipo Char.

  • Para los alfabetos adecuados, cambia las mayúsculas y minúsculas con uppercase() y lowercase().
  • Comprueba las mayúsculas y minúsculas con isuppercase() y islowercase().
  • Comprueba el tipo de carácter con:
    • isletter() abarca muchos alfabetos
    • isdigit(), comprueba estrictamente 0:9
    • isnumeric(), más amplio que isdigit, así que devuelve true para ¾ y varios sistemas de escritura no europeos
    • isxdigit(), dígitos hexadecimales
    • isascii(), carácter anterior a Unicode
    • ispunct(), puntuación
    • isspace(), cualquier carácter de espacio en blanco
    • isprint(), caracteres imprimibles (lo contrario es iscntrl())
islowercase('A')  # false
uppercase('γ')  # 'Γ': Unicode U+0393 (category Lu: Letter, uppercase)
ispunct('@')  # true
isdigit('A')  # false
isxdigit('A')  # true

Interconversión 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)

Fíjate en que el constructor String() opera sobre un vector. Para convertir un único Char a 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 tan poco de lo que preocuparse?

Lamentablemente, ¡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) 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() devolverá 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 padre más un modificador.

Este problema afecta a los strings, donde plantea dificultades para la indexación.

Instrucciones

En este ejercicio implementarás un conjunto parcial de rutinas de utilidad para ayudar a un desarrollador a limpiar nombres de identificadores.

En las 6 tareas irás construyendo gradualmente las funciones transform, para convertir caracteres individuales, y clean, para convertir strings.

Un identificador válido consta de cero o más letras, guiones bajos, guiones, signos de interrogación y emojis.

Si se pasa un string vacío a la función clean, se debe devolver un string vacío.

1. Sustituye los guiones que encuentres por guiones bajos

Implementa la función transform para sustituir los guiones por guiones bajos.

julia> transform('-')
"_"

2. Elimina todos los espacios en blanco

Elimina todos los caracteres de espacio en blanco. Esto incluirá los espacios en blanco iniciales y finales.

julia> transform(' ')
""

3. Convierte camelCase a kebab-case

Modifica la función transform para convertir camelCase a kebab-case

julia> transform('D')
"-d"

4. Omite los caracteres que sean dígitos

Modifica la función transform para omitir los caracteres que sean numéricos.

julia> transform('7')
""

5. Sustituye las letras griegas minúsculas por signos de interrogación

Modifica la función transform para sustituir cualquier letra griega en el rango «α» a «ω».

julia> transform('β')
"?"

6. Combina estas operaciones para operar sobre un string

Implementa la función clean para aplicar estas operaciones a un string completo.

Los caracteres que queden fuera de las reglas deben pasar sin cambios.

julia> clean("  a2b Cd-ω😀  ")
"ab-cd_?😀"
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Julia Exercism

¿Listo para empezar Impecable?

Regístrate en Exercism para aprender y dominar Julia con 35 conceptos128 ejercicios y mentoría humana real, todo gratis.