2009-02-20 10 views
6

W Perl, można często uniknąć stosując bloki sterujące, tak:Zwięzłe wyrażenie foreach w jednej linii

print "$_\n" foreach(@files); 

zamiast:

foreach(@files){ 
    print "$_\n"; 
} 

Jak to działa składni Poniżej więcej złożony przypadek:

die("Not a file: $_") unless -f $_ foreach(@files); 

Daje mi błąd składniowy. Nie próbuję pisać zaciemnionego kodu, jest to po prostu nieistotna część programu, dlatego chcę go wyrazić tak zwięźle, jak to tylko możliwe.

zestawione ODPOWIEDZI:

mogę przyjąć tylko jedną odpowiedź jako zaakceptowany odpowiedź, ale lubię następujące te z Chris i Jon najlepiej.

Ten wykorzystuje foreach jak zamierzałem, ale bez syntax error:

-f or die "Not a file: $_" foreach @files; 

A po nich jest co najmniej tak samo dobre. Lubię to die jest na początku instrukcji, ponieważ to właśnie uwagę czytelnika powinno być skierowane:

die("Not a file: $_") for grep {!-f} @files; 
+0

Zgadzam się, że 'die()' jest najlepszy na początku linii, ale w szczypie, logika zwarcia jest dla mnie tak samo czytelna. –

+1

Po prostu grałeś w golfa? W przeciwnym razie, dlaczego ważne jest, aby mieć go na jednej linii? –

Odpowiedz

12

Wystarczy być Perlish (TMTOWTDI) można użyć logiki zwarcia:

-f or die "Not a file: $_" foreach @files; 

testowany na OS X i dzieł.

Na marginesie, -f or die wygląda dużo wspólnych open() or die konstruktów widzę w Perlu i nadal ( myślę) pokazuje intencję linii (do die pod pewnymi warunkami).

+1

Bardzo zadbane. ++ i hooray dla szwajcarskiej piły łańcuchowej! –

+0

Podoba mi się. Równoległość z open() lub die() jest nieco wyłączona, ponieważ celem open() jest zwykle otwieranie pliku not die(). Ale jeśli myślisz o celu powyższego kodu, aby przetestować istnienie pliku, równoległość jest dokładna. Trudne połączenie, ale myślę, że bardziej podoba mi się twój. ;-) –

7

dobrze, nie może być zamierzając napisać kod zaciemniony, ale chcę powiedzieć, że 'z pewnością próbuje do.

Czy dwie linie (a nawet blok w jednym wierszu, jak sugeruje Brent.Longborough) zamiast jednego będzie tak zły? Szczerze mówiąc, to jest powód, dla którego generalnie nienawidzę próbować debugować/edytować kod perlowy innych ludzi, duża liczba osób, które piszą w perlu wydają się mieć obsesję na punkcie robienia wszystkiego w najbardziej "sprytny" sposób, zamiast robić to w sposób łatwy do zrozumienia dla kogoś, kto czyta.

+0

+1. Nigdy nie rozumiałem, dlaczego "clevver == w tylko jednej linii" dla niektórych osób. – innaM

+1

Myślę, że niektóre przykłady (takie jak te używające 'grep') są" sprytne ", ale nie dlatego, że są tylko jedną linią. Są sprytni, bo to tylko jedna linia, ale wyraźnie pokazują znaczenie. I wygląda ładnie - zagnieżdżone nawiasy i nawiasy w jednej linii wyglądają źle (moim zdaniem (z wyjątkiem Lispa (haha))). –

3

Jeśli nie próbujesz pisać zaciemnionego kodu, nie powinieneś próbować pisać tego w ten sposób. Bierzesz coś, co powinno być proste i trudne do zrozumienia.

+1

Co do diabła jest zaciemnione w tej sprawie? Jak byś to napisał? – Svante

+0

Zgadzam się z Harleqin - kilka odpowiedzi na tej stronie pokazuje, że istnieją sposoby, aby to napisać, które są jednocześnie a) jasne i b) jedną linię. –

+0

Odpowiedziałem na jego komentarz: "Nie próbuję pisać obfuskanego kodu". Jego próba została zaciemniona zgodnie z definicją Webstera: "być wymijającym, niejasnym lub mylącym". Odpowiedzi przesłane podczas publikowania były niejasne i mylące, a niektóre przykłady opublikowane później wyglądają dobrze. – gpojd

11

Można użyć @ odpowiedź Brent.Longborough, albo jeśli naprawdę chcesz Postfix, wykonaj następujące czynności:

do { die("Not a file: $_") unless -f $_ } foreach(@files); 

Jednak zgadzam się z innymi, tylko dlatego, że to jest „nieistotna część” nie znaczy, że zwięzłość jest lepsza. Czytelność się liczy.

+0

Jak to jest nieczytelne? Jak wolisz to napisać? – Svante

+0

Nie powiedziałem, że jest "nieczytelne". Jednak twierdzę, że jest * mniej * czytelne do korzystania z przykuty struktur kontroli Postfiksa. To oczywiście subiektywne. Chodzi o to, że PO nie powiedział, że stara się zmaksymalizować czytelność, ale że powinien być "zwięzły", ponieważ był "nieważny". –

5

Jeśli test błędu jest podstawowym punktem tego kodu, może być sensowne, aby jego położenie początkowe znajdowało się na początku wiersza. Nieznaczna poprawa byłoby użyć grep:

die("Not a file: $_") for grep {!-f} @files; 

Ale jeśli plan zapętlenie poprzez pliki z jakiegoś innego powodu, w tej części kodu, byłoby lepiej, aby dodać go do ciała pętli.

0

Cholera, Jon pokonał mnie po prostu grep.

Ale mam większe pytanie: jak to nie ma znaczenia, jeśli faktycznie zamierzasz wyskoczyć, jeśli znajdziesz jakieś pliki w twojej tablicy? (W przeciwieństwie do, powiedzmy, usuwania tych elementów, ostrzegania użytkownika, a następnie przetwarzania reszty listy.) Myślę, że zabicie całego shebangu jest rozsądnie ważną częścią programu.

W każdym razie nie możesz zrobić dokładnie tego, czego chcesz, z modyfikatorami Postfix, ponieważ możesz mieć tylko jedną rzecz po obu jej stronach. Więc nie możesz mieć zarówno unless, jak i foreach. Ze szczytu odpowiedniego bitu perldoc perlsyn:

Wszelkie proste stwierdzenie może ewentualnie być następnie SINGLE modyfikatora, tuż przed średnik kończący (lub blok kończąc).

+0

Tak. Gdyby to był tylko wydruk, powiedziałbym, że tradycyjna notacja jest lepsza. Ale umrze prawdopodobnie powinien być pierwszym tokenem na linii, jeśli to możliwe. –

-2

Jesteś tak martwy.

Your maintenance programmer http://www.codinghorror.com/blog/images/carny.jpg

Mam nadzieję, że nigdy cię znajdzie. Ale powinieneś think about him whenever you code.

+0

Lepszy, ale mniej szokujący cytat z połączonego artykułu: "Alternatywnie, zawsze koduj i komentuj w taki sposób, że jeśli ktoś o kilka nacięć junior podniesie kod, będą mieli przyjemność z czytania i uczenia się z niego . " - http://c2.com/cgi/wiki?CodeForTheMaintainer –

1

Myślisz zbyt mocno. Oto ona w jednej linii bez akrobacji:

foreach (@files) { die("Not a file!") unless -f } 

Możecie bawić z rzeczy wewnątrz bloku do golfa go w dół, ale usuwanie nawiasów i szelki nie pomaga w ogóle, i prawdopodobnie będzie pomylić kolejnego programistę, który musi na to spojrzeć.

Prawdopodobnie masz coś bardziej skomplikowanego, a to tylko przykład. W prawdziwym świecie staje się jeszcze łatwiejsze:

not_a_file_die_die_die(\@files); 

Następnie przenosisz wszystkie skomplikowane elementy do podprogramu. Prawdziwy trik polega na tym, aby cel był zwięzły, a nie kod implementujący ideę. W wielu przypadkach mechanika naprawdę nie ma znaczenia; zależy ci bardziej na wyniku. W takich przypadkach nie poci mechaniki.

Powiązane problemy