2012-05-24 15 views
11

Considere el siguiente problema: dada una lista de longitud tres de tuplas (String, Int), ¿hay un par de elementos que tengan la misma parte "Int"? (Por ejemplo, [("bob",5),("gertrude",3),("al",5)] contiene un par tal, sino [("bob",5),("gertrude",3),("al",1)] no lo hace.)¿Qué hace un buen nombre para una función de ayuda?

Así es como me gustaría implementar una función de este tipo:

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 

coincidencia de patrones para unir nombres a la "Int He usado "parte de las tuplas, pero quiero ordenar primero (para agrupar miembros similares), así que puse la función de coincidencia de patrones dentro de una cláusula where. Pero esto me lleva a mi pregunta: ¿cuál es una buena estrategia para elegir nombres para funciones que viven dentro de where, cláusulas? Quiero poder pensar en esos nombres rápidamente. Para este ejemplo, "hasPair" parece una buena opción, ¡pero ya está tomada! Encuentro que el patrón aparece mucho: el nombre aparentemente natural para una función auxiliar ya está ocupado por la función externa que lo llama. Así que, en ocasiones, llamé a tales funciones auxiliares cosas como "op", "foo" e incluso "ayudante"; aquí he elegido "servilleta" para enfatizar su naturaleza de usarlo una vez, tirarlo de la basura.

Entonces, queridos lectores de Stackoverflow, ¿qué llamarían "servilleta"? Y, lo que es más importante, ¿cómo abordas este problema en general?

+7

'go' es el camino :) –

+2

Una métrica general - _use nombres descriptivos cortos, si se esfuerza por ser adecuadamente descriptivo, simplemente haga que short_. Por cierto 'servilleta 'como está escrito actualmente no es muy robusto (la lista debe tener exactamente tres miembros), si lo piensas un poco más, tal vez sugiera un mejor nombre. –

+3

@stephen Sí, me di cuenta de eso de 'servilleta' mientras la escribía. Sin embargo, ¿diría usted que esto es cierto en general: si le resulta difícil nombrar una función, es probable que su diseño necesite mejoras? Si es cierto, es un concepto bastante poderoso ... – gcbenison

Respuesta

25

Reglas generales para la nomenclatura de ámbito local.

  • f, k, g, h para super simples, cosas semi-anónimos locales
  • go para (cola) ayudantes recursivas (precedent)
  • n, m, i, j para la longitud y el tamaño y otros valores numéricos
  • v para obtener resultados de búsqueda de mapas y otros tipos de diccionario
  • s y t para cadenas.
  • a:as y x:xs y y:ys para las listas.
  • (a,b,c,_) para tuple fields.

En general, estos solo se aplican a los argumentos de los HOF. Para su caso, iría con algo como k o eq3.

Utilice apóstrofes con moderación, para obtener valores derivados.

+2

Solo para que quede claro para cualquiera que lea esto: estas no son reglas del lenguaje Haskell, son (muy comunes) convenciones. – huon

+2

¿No es 'k' el nombre convencional para continuaciones específicamente? – Heatsink

+2

Oh, sí, y 'p' y' q' para predicados. –

3

Tiendo a llamar funciones con valores booleanos p para el predicado. pred, por desgracia, ya está ocupado.

+0

Siempre puede sombrear 'pred', bajo su propio riesgo, por supuesto. –

2

En casos como este, donde la función interna es básicamente la misma que la función externa, pero con diferentes precondiciones (que requieren que la lista esté ordenada), a veces uso el mismo nombre con una función principal, p. hasPairs'.

Sin embargo, en este caso, prefiero tratar de dividir el problema en partes que sean útiles por sí mismas en el nivel superior. Eso generalmente también hace que nombrarlos sea más fácil.

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

Sí, esto parece coincidir con el argumento de @ stephen de que un mejor diseño conduce naturalmente a mejores nombres. – gcbenison

+0

¿Ese uso de 'hasPair'' sería coherente con @ don's" Use apostrophes sparingly, for derived values ​​"? – gcbenison

+1

En segundo lugar esto. No tenga miedo de algunas definiciones adicionales de nivel superior, esto hace que la depuración sea más fácil ya que puede inspeccionar el comportamiento de las funciones de soporte independientemente del soporte. Use exportaciones explícitas de módulos si le preocupa exponer una API en particular. –

1

Mi estrategia sigue sugerencias de Don bastante de cerca:

  1. Si hay un nombre obvio para ello, utilizan eso.
  2. Use go si es el "trabajador" o si no tiene un propósito muy similar a la función original.
  3. Sigue las convenciones personales según el contexto, p. Ej. step y start para args a un pliegue.
  4. Si todo esto falla, sólo tiene que ir con un nombre genérico, como f

Hay dos técnicas que personalmente evitar. Uno está usando la versión apóstrofe de la función original, p. hasPair' en la cláusula where de hasPair. Es muy fácil escribir uno accidentalmente cuando te referías al otro; Prefiero usar go en tales casos. Pero esto no es un gran problema, siempre y cuando las funciones tengan diferentes tipos. La otra está usando nombres que pueden connotar algo, pero no algo que tenga que ver con lo que la función realmente hace. napkin entraría en esta categoría. Cuando vuelva a visitar este código, esta elección de nombre probablemente lo desconcertará, ya que habrá olvidado la razón original por la que lo llamó napkin. (¿Porque las servilletas tienen 4 esquinas? ¿Porque se doblan fácilmente? ¿Porque limpian los líos? ¿Se encuentran en los restaurantes?) Otros delincuentes son cosas como bob y myCoolFunc.

Si le ha dado a una función un nombre que es más descriptivo que go o h, entonces debería poder ver el contexto en el que se usa, o el cuerpo de la función, y en ambas situaciones obtener una muy buena idea de por qué se eligió ese nombre. Aquí es donde entra mi punto n. ° 3: convenciones personales. Gran parte del consejo de Don se aplica. Si está utilizando Haskell en una situación de colaboración, luego coordine con su equipo y decida sobre ciertas convenciones para situaciones comunes.

Cuestiones relacionadas