2012-05-24 12 views
11

Betrachten Sie das folgende Problem: Gibt es bei einer Liste der Länge dreier Tupel (String, Int) ein Paar Elemente mit demselben "Int" -Teil? (Zum Beispiel enthält [("bob",5),("gertrude",3),("al",5)] ein solches Paar, aber [("bob",5),("gertrude",3),("al",1)] nicht.)Was macht einen guten Namen für eine Hilfsfunktion?

Dies ist, wie ich eine solche Funktion implementieren würde:

import Data.List (sortBy) 
import Data.Function (on) 

hasPair::[(String,Int)]->Bool 
hasPair = napkin . sortBy (compare `on` snd) 
    where napkin [(_, a),(_, b),(_, c)] | a == b = True 
             | b == c = True 
             | otherwise = False 

I Muster verwendet haben, passende Namen zu binden an den „Int "Teil der Tupel, aber ich möchte zuerst sortieren (um Gruppen wie Mitglieder), so habe ich die Muster-Matching-Funktion in eine where Klausel. Aber das bringt mich zu meiner Frage: Was ist eine gute Strategie für die Auswahl Namen für Funktionen, die innerhalb where Klauseln leben? Ich möchte schnell an solche Namen denken können. Für dieses Beispiel scheint "hasPair" eine gute Wahl zu sein, aber es ist schon vergeben! Ich finde, dass dieses Muster sehr häufig vorkommt - der natürlich erscheinende Name für eine Hilfsfunktion wird bereits von der äußeren Funktion, die es aufruft, übernommen. So habe ich manchmal solche Hilfsfunktionen wie "op", "foo" und sogar "helper" genannt - hier habe ich "serviette" gewählt, um seine Gebrauch-es-einmal-weg-weg-Natur zu betonen.

Also, liebe Stackoverflow-Leser, was hättest du "Serviette" genannt? Und noch wichtiger: Wie gehen Sie generell mit diesem Thema um?

+7

'go' ist der Weg :) –

+2

Eine allgemeine Metrik - _use kurze beschreibende Namen, wenn Sie Mühe haben, geeignet beschreibend sein, machen Sie sie kurz_. Übrigens ist die "Serviette", wie sie derzeit geschrieben wird, nicht sehr robust (die Liste muss genau drei Mitglieder haben), wenn Sie darüber nachdenken, wird sie vielleicht einen besseren Namen vorschlagen. –

+3

@stephen Ja, das habe ich über 'Serviette' bemerkt, als ich es geschrieben habe. Würdest du sagen, dass das im Allgemeinen wahr ist: Wenn es dir schwer fällt, eine Funktion zu benennen, muss dein Design wahrscheinlich verbessert werden? Wenn das stimmt, das ist ein ziemlich starkes Konzept ... – gcbenison

Antwort

25

Allgemeine Regeln für die lokale Benennung von Variablen.

  • f, k, g, h für super einfach lokale, halb anonyme Dinge
  • go für (Schwanz) rekursive Helfer (precedent)
  • n, m, i, j für Länge und Größe und andere numerische Werte
  • v für Ergebnisse von Kartensuchen und anderen Wörterbuchtypen
  • s und t für Strings.
  • a:as und x:xs und y:ys für Listen.
  • (a,b,c,_) für Tupelfelder.

Diese gelten im Allgemeinen nur für Argumente zu HOFs. Für Ihren Fall würde ich mit etwas wie k oder eq3 gehen.

Verwenden Sie Apostrophe sparsam für abgeleitete Werte.

+2

Nur um klar zu sein für jeden, der dies liest: Dies sind keine Regeln der Haskell-Sprache, sie sind (sehr häufig) Konventionen. – huon

+2

Ist nicht 'k' der übliche Name für Fortsetzungen speziell? – Heatsink

+2

Oh, ja, und 'p' und' q' für Prädikate. –

3

Ich neige dazu, boolean Wertfunktionen p für Prädikat zu nennen. pred ist leider schon vergeben.

+0

Sie können jederzeit 'pred' beschatten, auf eigene Gefahr natürlich. –

2

In Fällen wie diesen, in dem die innere Funktion grundsätzlich dieselbe wie die Außen Funktion, jedoch mit unterschiedlichen Voraussetzungen (erforderlich ist, dass die Liste sortiert wird), I manchmal den gleichen Namen mit einem Apostroph verwenden, z.B. hasPairs'.

jedoch in diesem Fall würde ich eher versuchen, das Problem in Teile zu zerlegen, die selbst auf der obersten Ebene nützlich sind. Das macht es normalerweise auch einfacher, sie zu benennen.

hasPair :: [(String, Int)] -> Bool 
hasPair = hasDuplicate . map snd 

hasDuplicate :: Ord a => [a] -> Bool 
hasDuplicate = not . isStrictlySorted . sort 

isStrictlySorted :: Ord a => [a] -> Bool 
isStrictlySorted xs = and $ zipWith (<) xs (tail xs) 
+0

Ja, das scheint @ Stephen zu widersprechen, dass ein besseres Design natürlich zu besseren Namen führt. – gcbenison

+0

Wäre die Verwendung von "hasPair" konsistent mit @ don "Verwenden Sie Apostrophe sparsam für abgeleitete Werte"? – gcbenison

+1

Ich zweite dies. Haben Sie keine Angst vor einigen zusätzlichen Top-Level-Definitionen, dies erleichtert insbesondere das Debugging, da Sie das Verhalten der unterstützenden Funktionen isoliert von den unterstützten untersuchen können. Verwenden Sie explizite Modulexporte, wenn Sie Bedenken haben, eine bestimmte API verfügbar zu machen. –

1

Meine Strategie folgt Don Vorschläge ziemlich eng:

  1. Wenn es einen offensichtlichen Namen dafür ist, dass zu verwenden.
  2. Verwenden Sie go, wenn es der "Arbeiter" oder sonst sehr ähnlichen Zweck der ursprünglichen Funktion ist.
  3. Befolgen Sie persönliche Konventionen basierend auf Kontext, z. step und start für Args zu einer Falte.
  4. nicht alle Stricke Wenn, gehen Sie einfach mit einem generischen Namen, wie f

Es gibt zwei Techniken, die ich persönlich zu vermeiden. Man verwendet die Apostroph-Version der ursprünglichen Funktion, z. hasPair' in der where-Klausel von hasPair. Es ist zu leicht, versehentlich einen zu schreiben, wenn Sie den anderen meinen; Ich bevorzuge in solchen Fällen go. Aber das ist keine große Sache, solange die Funktionen verschiedene Typen haben. Die andere verwendet Namen, die etwas konnotieren könnten, aber nichts, was mit der Funktion der Funktion zu tun hat. napkin würde in diese Kategorie fallen. Wenn Sie diesen Code erneut aufrufen, wird Sie diese Benennungswahl wahrscheinlich verblüffen, da Sie den ursprünglichen Grund vergessen haben, dass Sie ihn napkin genannt haben. (Weil Servietten 4 Ecken haben? Weil sie leicht gefaltet werden? Weil sie Durcheinander bereinigen? Sie werden in Restaurants gefunden?) Andere Übeltäter sind Dinge wie bob und myCoolFunc.

Wenn Sie eine Funktion einen Namen gegeben haben, die eher deskriptiv als go oder h ist, dann sollten Sie in der Lage sein zu sehen entweder den Kontext, in dem sie verwendet wird, oder den Körper der Funktion, und in beiden Fällen erhalten eine ziemlich gute Idee, warum dieser Name gewählt wurde. Hier kommt mein Punkt # 3 ins Spiel: persönliche Konventionen. Ein großer Teil von Dons Ratschlag gilt. Wenn Sie Haskell in einer kollaborativen Situation verwenden, koordinieren Sie mit Ihrem Team und entscheiden Sie sich für bestimmte Konventionen für häufige Situationen.

Verwandte Themen