2012-05-17 7 views
6

tworzę dużo zmiennych tymczasowych w Haskell:Unikaj zmiennych tymczasowych za pomocą nazwy shadowing

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

Oznacza to, że nie chcę, aby napisać długi łańcuch funkcji tak:

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

Ponieważ staje się nieczytelne dla mnie, więc staram się pogrupować funkcje zgodnie z tym, co robią. W efekcie powstaje szereg brzydkich zmiennych tymczasowych, takich jak nums'' i nums' (mogę nadać im bardziej znaczące nazwy, ale punkt wciąż stoi ... każda nowa linia oznacza nową zmienną). Jest to przypadek, w którym zmienna shadowingu spowodowałaby czystszy kod. Chciałbym zrobić coś takiego:

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

tj. dokładnie tak samo jak powyżej, ale bez zmiennych tymczasowych. Czy jest jakiś sposób, aby to zrobić w Haskell? Być może cała sprawa może być owinięty w „transakcji”:

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

coś, co pozwoli Haskell wiedzieć, że kod w tym punkcie zawierają zmienne shadownigu i powinien martwić się tylko o wyniku końcowym. czy to możliwe?

+0

Można również użyć Monada państwa, jeżeli chcesz przekazać wartość wzdłuż bez mutacji jeszcze nie tworząc kilka nazwisk – amindfv

+3

może Uważam, że (a), jeśli mają znaczenie imiona dają pośrednie kroki, nie ma problemu; oraz (b) jeśli nie masz znaczących nazwisk, aby wykonać pośrednie kroki, nie ma korzyści z ich rozbicia. Z (a) i (b) możemy wywnioskować, że nie ma problemu. To zależy od tego, czy akceptujesz lokal, oczywiście. –

+4

Nie zgadzam się, że ponowne użycie tej samej nazwy dla różnych celów koniecznie czyni ją bardziej czytelną. Teraz czytelnik musi dowiedzieć się, która zmienna wiąże każde wystąpienie. – augustss

Odpowiedz

11

Ten styl jest bardzo powszechne:

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

wyraźnie wyznacza kod; podczas gdy . służy miejsce nazwy zmiennej tymczasowej.

Pozwala to uniknąć niebezpiecznych problemów, które mogą się pojawić po rozpoczęciu zacieniania nazw zmiennych - przypadkowe odwołanie się do niewłaściwego numeru x wpędzi cię w kłopoty wcześniej lub później.

4

Jeśli musisz, to możliwe, ale nie idiomatyczne. Użyj tego, co sugeruje Don lub luqui.

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

Jeśli nie jesteś w monadzie, zawsze możesz rozpocząć nowy blok do monady tożsamości.

6

Od swoimi nazwami (nums, nums', nums'', ...) przekazać żadnych informacji na temat grupy, można po prostu użyć podziały wiersza do grupy funkcjonalność i przekazują to samo:

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

jednak Sugerowałbym, aby zamiast tego podać nazwy subkomputacji, które przekazują informacje, np. normalizedNums, average itd. Wtedy nie ma brzydkiego problemu z cieniami, ponieważ używasz różnych nazw.

7

Oto propozycja nikt inny nie dał którego używam od czasu do czasu: może chcesz nazywania funkcji zamiast nazywania wartości!Na przykład, być może można napisać:

let runningSum = a . bunch . of_ . functions 
    weight  = another . bunch . of_ . functions 
in weight . runningSum $ [1..10] 
Powiązane problemy