11

次の問題を考えてみましょう。タプルの長さ3のリスト(String、Int)が与えられた場合、同じ「Int」部分を持つ要素のペアはありますか?(たとえば、その[("bob",5),("gertrude",3),("al",5)]ようなペアが含まれていますが、含まれてい[("bob",5),("gertrude",3),("al",1)]ません。)

これは私がそのような関数を実装する方法です:

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

タプルの「Int」部分に名前をバインドするためにパターンマッチングを使用しましたが、最初に(メンバーのようにグループ化するために)ソートしたいので、パターンマッチング関数をwhere句内に配置しました。しかし、これは私の質問に私をもたらします:の中にある関数の名前を選ぶための良い戦略は何whereですか?そんな名前を早く考えられるようになりたいです。この例では、「hasPair」は良い選択のように見えますが、すでに採用されています。パターンがたくさん出てくることがわかります-ヘルパー関数の自然に見える名前は、それを呼び出す外部関数によってすでに使用されています。そのため、時々、このようなヘルパー関数を「op」、「foo」、さらには「helper」と呼んでいます。ここでは、「ナプキン」を選択して、一度だけ使用することを強調しています。

それで、親愛なるStackoverflow読者、あなたは「ナプキン」と何と呼んだでしょうか?そしてもっと重要なことに、あなたは一般的にこの問題にどのようにアプローチしますか?

4

4 に答える 4

25

ローカルスコープの変数の命名に関する一般的な規則。

  • f、、、超単純なローカルk、半匿名のものgh
  • go(末尾)再帰ヘルパー(前例
  • n、、、、長さm、サイズijおよびその他の数値
  • vマップルックアップおよびその他の辞書タイプの結果
  • st文字列の場合。
  • a:asおよびx:xsおよびy:ysリスト用。
  • (a,b,c,_)タプルフィールド用。

これらは通常、HOFへの引数にのみ適用されます。あなたの場合、私はまたはのようなもので行きkますeq3

派生値には、アポストロフィを慎重に使用してください。

于 2012-05-24T15:29:04.553 に答える
3

p私は述語のためにブール値関数を呼び出す傾向があります。pred、残念ながら、すでに取られています。

于 2012-05-24T18:58:54.820 に答える
2

このような場合、内部関数は基本的に外部関数と同じですが、前提条件が異なります(リストがソートされている必要があります)。たとえば、同じ名前を素数で使用することがありますhasPairs'

ただし、この場合は、問題をトップレベルでそれ自体が役立つ部分に分解することをお勧めします。これにより、通常、名前を付けるのも簡単になります。

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)
于 2012-05-25T02:13:35.853 に答える
1

私の戦略は、ドンの提案にかなり厳密に従っています。

  1. わかりやすい名前がある場合は、それを使用してください。
  2. goそれが「ワーカー」である場合、または元の機能と目的が非常に類似している場合に使用します。
  3. コンテキストに基づいた個人的な慣習に従います。たとえばstepstart引数を折りたたむ場合などです。
  4. 他のすべてが失敗した場合は、次のような一般的な名前を付けてくださいf

私が個人的に避けているテクニックは2つあります。1つは、元の関数のアポストロフィバージョンを使用することです。たとえばhasPair'、のwhere句を使用しhasPairます。あなたがもう一方を意味するときに誤って一方を書くのは簡単すぎます。私はそのような場合に使用することを好みますgo。しかし、関数のタイプが異なる限り、これは大したことではありません。もう1つは、何かを暗示する可能性のある名前を使用していますが、関数が実際に行うこととは関係ありません。napkinこのカテゴリに分類されます。このコードを再検討すると、名前を付けた元の理由を忘れてしまうため、この名前の選択はおそらくあなたを困惑させるでしょうnapkin。(ナプキンには4つの角があるので?簡単に折りたたむので?混乱をきれいにするので?レストランで見つけられるので?)他の犯罪者は次のようなものですbobおよびmyCoolFunc

goまたはよりもわかりやすい名前を関数に付けた場合はh、それが使用されているコンテキストまたは関数の本体のいずれかを確認できるはずです。どちらの状況でも、その理由をかなりよく理解できます。その名前が選ばれました。これが私のポイント#3の出番です:個人的な慣習。ドンのアドバイスの多くが当てはまります。共同作業でHaskellを使用している場合は、チームと調整して、一般的な状況での特定の規則を決定します。

于 2012-05-26T20:27:24.733 に答える