2 puntos por GN⁺ 2024-01-15 | 1 comentarios | Compartir por WhatsApp

Pensar en lenguaje K

  • La programación en K se realiza en su mayor parte a través del REPL.
  • rlwrap de ngn/k permite recorrer el historial con las teclas de flecha, lo que resulta útil para desarrollar programas grandes.
  • Las funciones se prueban en el REPL y luego se trasladan al código real.
  • La salida bonita de ngn/k siempre devuelve datos K válidos y puede precalcularse para mejorar la velocidad del programa.
  • Los scripts de K se ejecutan como si se hubieran escrito en el REPL, y el valor de retorno de cada línea se imprime a menos que termine con punto y coma.
  • Los scripts permiten definiciones de varias líneas, lo que ayuda a la legibilidad.
  • Para guardar el trabajo en un script y usarlo desde el REPL, se puede ejecutar el archivo y cargar los datos con \lfile.k.
  • Se puede cargar un archivo varias veces en el REPL para sobrescribir los datos anteriores.
  • La ayuda del REPL accesible con \ incluye varios comandos útiles.

Simplificación de la programación con arreglos

  • La programación con arreglos es un proceso continuo de simplificar patrones complejos en patrones más pequeños, declarativos y fáciles de leer.
  • La forma de simplificar patrones complejos se analiza en detalle en "Patterns and Antipatterns in APL: Escaping Beginner's Plateau - Aaron Hsu - Dyalog '17".

Transformación a K de la multiplicación de matrices

  • El algoritmo iterativo de multiplicación de matrices tomado de un artículo de Wikipedia puede convertirse directamente a K.
  • El peor ejemplo de código traducido a K requiere muchas asignaciones de variables globales, bucles anidados y mucha mutación.
  • Es posible simplificar el código para resolver estos problemas uno por uno.

Simplificación del bucle interno

  • En el bucle interno, sum puede simplificarse usando fold (/).
  • ' (each) devuelve un arreglo, por lo que se puede eliminar la variable global C.
  • Se pueden eliminar las variables i, j y k para simplificar el bucle.

Eliminación de bucles y minimización de variables globales

  • Sin k, se puede eliminar el bucle intermedio emparejando directamente filas y columnas.
  • Para eliminar j, se puede emparejar cada columna de B con A[i].
  • Para eliminar i, se puede usar eachleft para emparejar cada fila de A con cada columna de B.
  • Ya no se necesitan variables globales.

Forma final de la función de multiplicación de matrices

  • + (transposición) es costoso, así que puede eliminarse.
  • En lugar de multiplicar cada fila de x por cada columna de y, se puede hacer implícitamente el mismo trabajo ajustando cada fila de B contra todo A.
  • Al final se obtiene una función de multiplicación de matrices concisa y explícita.
  • El proceso de simplificar código pasa por varios pasos al principio, pero a medida que aumenta la familiaridad con K, puede volverse más fácil e intuitivo.
  • La multiplicación de matrices es un procedimiento simple que encaja bien con el soporte de arreglos de K.
  • En capítulos futuros se verán más algoritmos que no encajan tan bien con K y cómo manejarlos.

Opinión de GN⁺

  • Este artículo muestra cómo se pueden simplificar y optimizar algoritmos como la multiplicación de matrices usando el lenguaje K.
  • La retroalimentación inmediata mediante el REPL y la mejora iterativa del código son características centrales de la programación en K, y también son un método de aprendizaje útil para ingenieros de software principiantes.
  • El proceso de simplificación del código es importante para mejorar la capacidad de programación, y este artículo lo explica de forma clara mediante ejemplos concretos.

1 comentarios

 
GN⁺ 2024-01-15
Opinión de Hacker News
  • Varias personas están cuestionando la utilidad y la comprensibilidad de los lenguajes de arreglos.

    • Los lenguajes de arreglos no son adecuados para todos los problemas.
    • Son sorprendentemente capaces para muchos tipos de problemas.
    • Los usuarios de lenguajes de arreglos suelen ser muy inteligentes.
    • Aprender cómo funcionan los lenguajes de arreglos es un gran desafío.
    • Escribir código "procedimental" en lenguajes de arreglos es algo muy malo.
    • Entender la programación tácita (tacit programming) es una experiencia genial que te expande la mente.
    • La experiencia de interiorizar los encadenamientos de verbos (verb trains).
    • Comprender cómo los lenguajes basados en arreglos manejan arreglos de cualquier dimensión.
    • Comprender cómo funciona under.
    • Comprender cómo funcionan los exponentes de función (function exponents).
  • Hay muchos aspectos sorprendentes en los lenguajes de arreglos, y la lista anterior es solo una parte.

    • Ver a Aaron Hsu desarrollar un compilador APL paralelo hizo que se convencieran del verdadero potencial de los lenguajes de arreglos.
    • Discusión sobre la "densidad semántica (semantic density)" del código APL.
  • Si nunca has oído hablar de la programación de arreglos y quieres una introducción, recomiendan "The Array Cast".

  • Descubrieron APL/APL2 en los años 70 y les fascinó, pero les atraía aún más la capacidad de componer funciones.

    • Haskell, al ser puro y tipado, es más divertido y poderoso que APL.
    • La "notación como herramienta para pensar" de APL parece una lógica para justificar una concisión excesiva.
  • La revelación más importante al usar lenguajes de arreglos:

    • Los verbos son algoritmos.
    • Una secuencia de verbos (o adverbios) es la forma de composición más directa que han usado.
    • Un programa es una composición de algoritmos, no un conjunto de oraciones y expresiones.
    • La idea de tratar dominio y rango de forma consistente a través de arreglos, mapas y funciones.
    • La evaluación de izquierda a derecha sin necesidad de que los ojos "salten" al leer código.
    • Es posible y preferible enviar el código a los datos.
    • Ventajas adicionales del lenguaje K: se pueden implementar vistas (es decir, dependencias) directamente y es posible la carga en caliente de código mediante el intérprete.
  • Pregunta sobre los lenguajes de arreglos: ¿cómo se realiza una tarea como "encontrar todos los números menores que N para los que la condición P es verdadera"?

    • En los lenguajes de arreglos, por lo general se genera un arreglo de 1 a N, se prueba la condición sobre el arreglo y luego se aplica una máscara para obtener solo los elementos que cumplen la condición.
    • Si N es grande y la condición no se cumple con frecuencia, crear demasiados arreglos temporales innecesariamente parece un desperdicio de memoria y recursos.
    • Las implementaciones de lenguajes de arreglos pueden optimizar estos problemas o resolverlos con técnicas como la evaluación perezosa (lazy evaluation).
  • Experiencia con el lenguaje J: el paradigma de los lenguajes de arreglos está sesgado, y no están seguros de que pensar todos los problemas como anidamientos de arreglos realmente ayude.

    • Poder crear libremente estructuras de datos que simplifican el problema puede simplificar mucho la parte algorítmica.
    • Para usar APL/J/K, por ese sesgo, hay que ser más inteligente.
  • Impresión al resolver problemas en K: el lenguaje K es deliberadamente críptico.

    • Es un lenguaje adecuado para acertijos y soluciones ingeniosas, pero trabajar con arreglos de numpy en Python también enseña lenguajes de arreglos y cómo pensar en arreglos.
  • Ejemplo del lenguaje de arreglos J: dot =: +/ . * se usa para calcular el producto punto entre P y Q.

  • La sintaxis de K es más corta, pero hay que mantener en la cabeza mucho contexto incorporado sobre cómo funciona el lenguaje K.