Husk est un tout nouveau langage de golf, créé par les utilisateurs de PPCG Leo et Zgarb . Il a commencé à être de plus en plus compétitif, restant souvent proche ou même battant des langues connues pour être très laconiques, comme Jelly et 05AB1E.
Énumérons quelques-unes des techniques de golf qui sont quelque peu spécifiques à Husk. Comme toujours, veuillez poster un pourboire par réponse.
Réponses:
Utilisez la valeur de retour des prédicats
Dans Husk, les fonctions qui testent leurs entrées pour une propriété retournent généralement un résultat significatif dans les cas véridiques, car tout entier positif est véridique.
Exemples:
¹ différence appropriée signifie différence de points de code pour les caractères. Il fait également référence à l'ordre des arguments. c'est-à-dire pour
<x y
, seraitx-y
la source
Utiliser des étiquettes de ligne débordantes
Comme vous le savez peut-être déjà, il
[₀-₉]+|[₀-₉]
s'agit d'une expression régulière pour que la syntaxe appelle une ligne différente de celle dans laquelle vous vous trouvez actuellement.Cette astuce est particulièrement utile si vous souhaitez qu'une fonction définie sur une ligne spécifique soit appelée en tant qu'argument de plusieurs des fonctions du tableau ci-dessous, ou en tant qu'argument d'une ou plusieurs des fonctions ci-dessous et par elle-même.
Table de fonction:
Les lignes de votre code sont étiquetées avec leurs indices de base respectifs, de haut en bas. Si M <N , où M est l'étiquette et N est le nombre de lignes dans votre code, l'étiquette ne représente que la fonction définie à la ligne M . Si N ≤ M <N * 6 , il représente la fonction du tableau ci-dessus à l'indice ⌊M ÷ N⌋ avec la fonction définie à la ligne M mod N comme premier argument. Si N * 6 ≤ M , une erreur d'index est déclenchée.
la source
Les lambdas peuvent être plus courts que les nouvelles fonctions
Comme vous le savez probablement si vous avez un programme multi-lignes, vous pouvez vous référer aux lignes avec les indices
₀…₉
, par exemple dans le cas de₁
fera référence à la fonctiong
. Maintenant, si vous appliquez toujours les entrées à la fonctiong
(et que vous l'utilisez plusieurs fois); quelque chose comme ça:Vous devez introduire un lambda car il vous fait économiser 1 octet pour chaque utilisation supplémentaire:
L'inverse pourrait aussi être vrai
Dans le cas des lambdas auto-référentiels (
φχψ
), il y a le cas spécial où vous appliquez les entrées directement à la fonction récursive, dans ces cas, vous feriez mieux d'utiliser l'index₀
au lieu de définir un nouveau lambda et d'utiliser⁰
.la source
Utilisations de
Γ
L'utilisation principale de la fonction intégrée
Γ
, connue sous le nom de correspondance de motifs sur des listes ou de déconstruction de listes , est de diviser une liste en une tête et une queue et d'y appliquer une fonction binaire. Cela correspond à l'idiome de correspondance du motif Haskelloù
<something>
est une expression contenantx
,xs
et éventuellementf
. Il y a 4 surcharges deΓ
, chacune fonctionnant un peu différemment.list
La première surcharge,,
list
prend une valeura
et une fonction binairef
. Il retourne une nouvelle fonction qui prend une liste, retournea
si elle est vide et appellef
sur la tête et la queue si elle n'est pas vide. Par exemple,Γ_1€
prend une liste, retourne-1
si elle est vide et l'index de première occurrence du premier élément dans la queue sinon.listN
La deuxième surcharge,,
listN
est similaire àlist
, sauf qu'ellea
est omise et que la valeur par défaut du type de retour est utilisée à la place. Par exemple,Γ€
est équivalent àΓ0€
, car la valeur numérique par défaut est0
.En pratique,
listN
est utilisé plus souvent quelist
, car la valeur par défaut n'est pas pertinente ou correspond exactement à ce dont vous avez besoin. Un modèle commun estΓ~αβγ
, oùαβγ
sont trois fonctions; cela s'appliqueβ
au premier élément etγ
à la queue, et combine les résultats avecα
. Il a été utilisé par exemple dans cette réponse . D'autres modèles incluent l'Γo:α
applicationα
uniquement au premier élément et l'Γ·:mα
applicationα
à tous les éléments sauf le premier. Ce dernier a été utilisé dans cette réponse .listF
La troisième surcharge est un peu plus compliquée. Comme
list
ça, ça prend une valeura
et une fonctionf
, et renvoie une nouvelle fonctiong
qui prend une liste. Cependant, cette foisf
prend un argument de fonction supplémentaire, qui estg
lui - même, et peut l'appeler sur n'importe quelle valeur (y compris, mais sans s'y limiter, la queue de la liste d'entrée). Cela signifie quelistF
implémente un schéma général de récursivité sur les listes.listF
n'est pas utilisé très souvent, car la récursivité explicite aveclist
/listN
est généralement de la même longueur ou plus courte, comme dans cette réponse .listNF
listNF
est àlistF
ce quilistN
est àlist
: l'entréea
est omise et la valeur par défaut du type de retour est utilisée à la place. Dans de rares circonstances, il peut être plus court qu'un pli droit, par exemple dans cette réponse .À titre d'exemple des versions récursives de
Γ
, la fonctionΓλ·:o⁰↔
mélange une liste dans l'ordre premier, dernier, deuxième, avant-dernier, troisième, avant-dernier, etc. Essayez-le en ligne! La fonctionf
est la lambda expliciteλ·:o⁰↔
, dont l'argument⁰
est la fonction entière. Ce quif
ne fait qu'inverser la queue avec↔
, puis appeler la fonction principale récursivement aveco⁰
, et enfin clouer la tête en arrière avec·:
. Bien sûr,Γ·:o₀↔
est un octet plus court, mais ne fonctionne pas si la ligne contient autre chose que cette fonction.la source
Les combinateurs peuvent être appliqués à des fonctions d'ordre supérieur
Supposons que vous ayez une liste d'entiers X et que vous souhaitiez compter le nombre total d'éléments de X qui sont plus grands que la longueur (X) . Éléments de comptage qui satisfont un prédicat est fait avec la fonction d'ordre supérieur
#
, mais ici le prédicat (étant plus grande que la longueur (X) ) dépend de X . La solution consiste à appliquer le combinateurṠ
à#
et la fonctiono>L
qui vérifie si une liste est plus courte qu'un nombre. Dans la fonctionṠ#o>L
, la liste X est transmiseo>L
, la fonction partiellement appliquée est transmise#
et X est donné#
comme deuxième argument.En général, si
α
est une fonction d'ordre supérieur,β
une fonction binaire etγ
une fonction unaire,Ṡαβ
est équivalente au pseudocode Haskell§αβγ
est équivalent àet
~αβγ
équivaut àtant que les types correspondent.
Comme autre exemple concret,
§►δṁ≠P
trouve une permutation d'une liste X qui maximise la somme des différences absolues aux valeurs correspondantes de X (δṁ≠
zippe deux listes en utilisant la différence absolue et prend la somme).la source
Valeurs par défaut de Husk
Husk n'est pas aussi strict que Haskell où vous rencontrez des problèmes lorsque, par exemple, vous essayez d'obtenir l'
last
élément d'une liste vide. Pour ce faire, il utilise des valeurs prédéfinies, voici une liste des valeurs par défaut, maxima et minima:* Ici ∞ devrait représenter une liste infinie du maximum correspondant (voir ci-dessous pour un exemple)
Remarque: pour les tuples (X, Y), les valeurs de chaque composant seront utilisées séparément.
Quand ils sont utilisés
Alors que les maxima et les minima ne sont utilisés que
▲▼
sur des listes vides (par exemple,husk -u "▼" "[]:LLN"
ils renverront une liste infinie deInf
), les valeurs par défaut sont utilisées à quelques endroits:F
etḞ
)Θ
)r
) échoue←→
) ou indexer en un (!
)Γ
) sur des listes vides►
ou◄
sur des listes videsla source