Husk es un lenguaje de golf bastante nuevo, creado por los usuarios de PPCG Leo y Zgarb . Ha comenzado a ser cada vez más competitivo, a menudo manteniéndose cerca o incluso superando idiomas conocidos como muy concisos, como Jelly y 05AB1E.
Hagamos una lista de algunas de las técnicas de golf que son algo específicas de Husk. Como siempre, publique un consejo por respuesta.
Respuestas:
Usa el valor de retorno de predicados
En Husk, las funciones que prueban sus entradas para alguna propiedad generalmente devolverán un resultado significativo en casos verdaderos, ya que cualquier número entero positivo es verdadero.
Ejemplos:
¹ diferencia apropiada significa diferencia de puntos de código para caracteres. También se refiere al orden del argumento. es decir
<x y
, seríax-y
fuente
Utilice etiquetas de líneas desbordantes
Como ya sabrás,
[₀-₉]+|[₀-₉]
es la expresión regular para que la sintaxis llame a una línea diferente a la que estás actualmente.Este consejo es especialmente útil si desea que una función definida en una línea específica se llame como un argumento de más de una de las funciones en la tabla a continuación, o como un argumento para una o más de las funciones a continuación y por sí misma.
Tabla de funciones:
Las líneas en su código están etiquetadas con sus respectivos índices basados en 0, de arriba a abajo. Si M <N , donde M es la etiqueta y N es el número de líneas en el código, la etiqueta justo representa la función definida en la línea M . Si N ≤ M <N * 6 , representa la función de la tabla anterior en el índice ⌊M ÷ N⌋ con la función definida en la línea M mod N como primer argumento. Si N * 6 ≤ M , se genera un error de índice.
fuente
Las lambdas pueden ser más cortas que las nuevas funciones
Como probablemente sepa si tiene un programa de varias líneas, puede consultar las líneas con los subíndices
₀…₉
, por ejemplo, en el caso de₁
se referirá a la funcióng
. Ahora, si siempre aplica las entradas a la funcióng
(y la usa varias veces); algo como esto:Debe introducir una lambda porque le ahorra 1 byte por cada uso adicional:
Lo contrario también podría ser cierto
En el caso de lambdas autorreferenciales (
φχψ
), existe el caso especial en el que aplica las entradas directamente a la función recursiva, en estos casos es mejor usar el subíndice en₀
lugar de definir una nueva lambda y usarla⁰
.fuente
Usos de
Γ
El uso principal de la función incorporada
Γ
, conocida como coincidencia de patrones en listas o deconstrucción de listas , es dividir una lista en cabeza y cola, y aplicar una función binaria en ellas. Esto corresponde al patrón de coincidencia de patrones de Haskelldonde
<something>
es una expresión que contienex
,xs
y posiblementef
. Hay 4 sobrecargasΓ
, cada una de las cuales funciona un poco diferente.list
La primera sobrecarga,
list
toma un valora
y una función binariaf
. Devuelve una nueva función que toma una lista, devuelvea
si está vacía y llamaf
a la cabeza y la cola si no está vacía. Por ejemplo,Γ_1€
toma una lista, devuelve-1
si está vacía, y el índice de la primera aparición del primer elemento en la cola si no.listN
La segunda sobrecarga,
listN
es similar alist
, excepto quea
se omite y en su lugar se usa el valor predeterminado del tipo de retorno. Por ejemplo,Γ€
es equivalente aΓ0€
, ya que el valor numérico predeterminado es0
.En la práctica,
listN
se usa con más frecuencialist
, ya que el valor predeterminado es irrelevante o exactamente lo que necesita. Un patrón común esΓ~αβγ
, dondeαβγ
hay tres funciones; esto se aplicaβ
al primer elemento yγ
a la cola, y combina los resultados conα
. Se usó, por ejemplo, en esta respuesta . Otros patrones incluyenΓo:α
para aplicarα
solo al primer elemento yΓ·:mα
para aplicarα
a todos los elementos excepto el primero. Este último se usó en esta respuesta .listF
La tercera sobrecarga es un poco más complicada. Al igual
list
, toma un valora
y una funciónf
, y devuelve una nueva funcióng
que toma una lista. Sin embargo, esta vezf
toma un argumento de función adicional, que es eng
sí mismo, y puede invocarlo en cualquier valor (incluido, entre otros, el final de la lista de entrada). Esto significa quelistF
implementa un esquema de recursión general en las listas.listF
no se usa con mucha frecuencia, ya que la recursividad explícita conlist
/listN
suele ser de la misma longitud o más corta, como en esta respuesta .listNF
listNF
es alistF
lo quelistN
eslist
:a
se omite la entrada y en su lugar se usa el valor predeterminado del tipo de retorno. En raras circunstancias, puede ser más corto que un pliegue derecho, por ejemplo en esta respuesta .Como ejemplo de las versiones recursivas de
Γ
, la funciónΓλ·:o⁰↔
baraja una lista en el orden primero, último, segundo, penúltimo, tercero, penúltimo, y así sucesivamente. Pruébalo en línea! La funciónf
es la lambda explícitaλ·:o⁰↔
, cuyo argumento⁰
es la función completa. Lo quef
hace es invertir la cola con↔
, luego llamar a la función principal de forma recursivao⁰
y finalmente clavar la cabeza hacia atrás con·:
. Por supuesto,Γ·:o₀↔
es un byte más corto, pero no funciona si la línea contiene algo más que esta función.fuente
Los combinadores se pueden aplicar a funciones de orden superior
Supongamos que tiene una lista de enteros X y desea contar el número total de elementos de X que son mayores que la longitud (X) . Elementos de recuento que satisfacen un predicado se hace con la función de orden superior
#
, pero aquí el predicado (que es mayor que la longitud (X) ) depende de X . La solución es aplicar el combinadorṠ
a#
y la funcióno>L
que comprueba si una lista es más corto que un número. En la funciónṠ#o>L
, se pasa la lista X, se pasao>L
la función parcialmente aplicada#
y se da X#
como segundo argumento.En general, si
α
es una función de orden superior,β
una función binaria yγ
una función unaria,Ṡαβ
es equivalente al pseudocódigo de Haskell§αβγ
es equivalente ay
~αβγ
es equivalente asiempre y cuando los tipos coincidan.
Como otro ejemplo concreto,
§►δṁ≠P
encuentra una permutación de una lista X que maximiza la suma de las diferencias absolutas a los valores correspondientes de X (δṁ≠
comprime dos listas usando la diferencia absoluta y toma la suma).fuente
Valores predeterminados de Husk
Husk no es tan estricto como Haskell, donde te encuentras con problemas cuando, por ejemplo, intentas obtener el
last
elemento de una lista vacía. Para lograr esto, utiliza valores predefinidos, aquí hay una lista de los valores predeterminados, máximos y mínimos:* Aquí ∞ debe representar una lista infinita del máximo correspondiente (vea a continuación un ejemplo)
Nota: Para las tuplas (X, Y) usará los valores para cada componente por separado.
Cuando se usan
Mientras que los máximos y mínimos solo se usan
▲▼
en listas vacías (por ejemplohusk -u "▼" "[]:LLN"
, devolverá una lista infinita deInf
) los valores predeterminados se usan en algunos lugares:F
yḞ
)Θ
)r
) falla←→
) o indexar en uno (!
)Γ
) en listas vacías►
o◄
en listas vacíasfuente