2012-05-17 5 views
6

ich viele temporären Variablen in Haskell zu erstellen:Vermeiden Sie temporäre Variablen mit Namen mit Shadowing

main = do 
    let nums'' = [1..10] 
    let nums' = a . bunch . of_ . functions $ nums'' 
    let nums = another . bunch . of_ . functions $ nums' 
    print nums 

Das heißt, ich will nicht, eine lange Kette von Funktionen wie so schreiben:

let nums = another . bunch . of_ . functions . a . bunch . of_ . functions $ [1..10] 

Da es für mich unlesbar wird, versuche ich, die Funktionen entsprechend ihrer Arbeit zu gruppieren. In diesem Prozess erstelle ich eine Menge hässlicher temporärer Variablen wie nums'' und nums' (ich könnte ihnen sinnvollere Namen geben, aber der Punkt steht immer noch ... jede neue Zeile bedeutet eine neue Variable). Dies ist ein Fall, in dem eine schattierte Variable saubereren Code ergeben würde. Ich möchte etwas tun wie:

let nums = [1..10] 
nums = a . bunch . of_ . functions $ nums 
nums = another . bunch . of_ . functions $ nums 

I.e. genau wie oben, aber ohne die temporären Variablen. Gibt es eine Möglichkeit, dies in Haskell zu tun?

atomically $ do 
    (...this code...) 
    return nums 

Etwas, das Haskell würde wissen, dass der Code in diesem Abschnitt beschatteten Variablen enthält, und es sollte nur über das Endergebnis Sorge: Vielleicht könnte das Ganze in einer „Transaktion“ eingewickelt werden. Ist das möglich?

+0

Sie auch den Staat Monade verwenden könnten, wenn Sie, ohne eine Reihe von Namen einen Wert zu übergeben entlang ohne Mutation noch wollen – amindfv

+3

ich kann, dass (a) argumentieren, wenn Sie von Bedeutung haben Namen, um die Zwischenschritte zu geben, gibt es kein Problem; und (b) wenn Sie keine aussagekräftigen Namen haben, um die Zwischenschritte zu machen, dann gibt es keinen Vorteil, sie aufzulösen. Und aus (a) und (b) können wir schließen, dass es kein Problem gibt. Es hängt natürlich davon ab, ob Sie die Räumlichkeiten akzeptieren. –

+4

Ich bin nicht damit einverstanden, dass die Wiederverwendung des gleichen Namens für verschiedene Zwecke es notwendigerweise lesbarer macht. Nun muss der Leser herausfinden, auf welche Variable sich jedes Ereignis bezieht. – augustss

Antwort

11

Dieser Stil ist sehr häufig:

let nums = another 
     . bunch 
     . of_ 
     . functions 
     . a 
     . bunch 
     . of_ 
     . functions 
     $ [1..10] 

Es eindeutig den Code abgrenzt; während . die Stelle des temporären Variablennamens dient.

Und es vermeidet die gefährlichen Probleme, die passieren können, wenn Sie beginnen, Variablennamen zu beschatten - versehentlich auf die falsche x zu verweisen, wird Sie früher oder später in Schwierigkeiten bringen.

4

Wenn Sie unbedingt müssen, ist es möglich, aber nicht idiomatisch. Verwenden Sie stattdessen, was Don oder Luqui vorschlagen.

main = do 
    nums <- return [1..10] 
    nums <- return $ a . bunch . of_ . functions $ nums 
    nums <- return $ another . bunch . of_ . functions $ nums 
    print nums 

Wenn Sie nicht in einer Monade sind, können Sie immer einen neuen Do-Block in der Identitätsmonade starten.

6

Da Ihre Namen (nums, nums', nums'', ...) vermitteln keine Informationen über die Gruppierung, können Sie einfach zu einer Gruppe verwenden Linie die Funktionalität bricht und kommunizieren das Gleiche:

main = 
    let nums = a . bunch . of_ . functions 
      . another . bunch . of_ . functions 
      $ [1..10] 
    in print nums 

jedoch Ich würde vorschlagen, dass Sie statt dessen die Subcomputations Namen geben, die do Informationen vermitteln, z. normalizedNums, average usw. Dann gibt es kein hässliches Abschattungsproblem, weil Sie unterschiedliche Namen verwenden.

7

Hier ist ein Vorschlag, den niemand anderen gegeben hat, den ich von Zeit zu Zeit verwende: Sie mögen Ihre Funktionen benennen, anstatt Ihre Werte zu benennen!Zum Beispiel, vielleicht könnten Sie schreiben:

let runningSum = a . bunch . of_ . functions 
    weight  = another . bunch . of_ . functions 
in weight . runningSum $ [1..10] 
Verwandte Themen