Jakie masz ogólne wskazówki na temat gry w golfa w Perl 6? Szukam pomysłów, które można zastosować do ogólnych problemów z golfem, które są przynajmniej nieco specyficzne dla Perla 6 (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.
Należy pamiętać, że Perl 6 nie jest Perl 5, więc to pytanie nie jest duplikatem. Większość wskazówek dotyczących golfa w Perlu 5 po prostu nie dotyczy Perla 6.
say (3² + 4², 2²⁰, 5⁻²)
==>(25 1048576 0.04)
. Pełna lista Unicode, którą możesz nadużywać w ten sposób, znajduje się tutaj: docs.perl6.org/language/unicode_texas .Naucz się funkcji czytać dane wejściowe. Perl 6 ma wiele interesujących funkcji, które mogą z łatwością odczytać dane wejściowe z ARGV lub STDIN (jeśli nic nie zostało określone w ARGV), które mogą skrócić twój kod, jeśli zostanie użyty poprawnie. Jeśli wywołasz je jako metody uchwytu pliku, możesz zmusić je do działania na konkretnym uchwycie pliku (przydatne, jeśli na przykład czytasz z
STDIN
, ale musisz czytać argumenty na ARGV).get
Ta funkcja otrzymuje pojedynczą linię i automatycznie ją łamie, więc nie musisz. Jest to przydatne, jeśli chcesz przeczytać tylko jedną linię.
lines
Ta funkcja pobiera wszystkie linie z pliku lub STDIN. To leniwa lista, więc jeśli z niej korzystasz
for
, będzie czytać tylko to, czego potrzebujesz. Na przykład.slurp
Spowoduje to odczytanie całego pliku lub STDIN i zwróci wynik jako pojedynczy ciąg.
źródło
say "<$_>" for lines
teraz działaOstrzeżenie : zbliża się ściana tekstu. Z czasem zebrałem wiele małych sztuczek.
Napisz swoje rozwiązania jako anonimowe bloki
Zostało to już wspomniane, ale chciałbym to powtórzyć. W TIO możesz pisać
my $f =
w nagłówku, blok w odpowiednim kodzie i zaczynać stopkę od;
. Wydaje się, że jest to zdecydowanie najkrótszy sposób na wykonanie zadania (ponieważ nie musisz przejmować się czytaniem jakichkolwiek danych wejściowych, są one podawane w argumentach).Innym fajnym sposobem jest użycie przełącznika
-n
lub-p
, ale nie znalazłem sposobu, aby działał w TIO.Do przekazywania argumentów używaj składni dwukropka
Oznacza to,
thing.method(foo,bar)
że możesz zrobićthing.method:foo,bar
i zapisać 1 postać. Niestety nie można wywołać innej metody z wyniku z oczywistych powodów, dlatego warto używać tylko ostatniej metody w bloku.Używaj
$_
jak najwięcejCzasami lepiej jest z tego powodu wziąć jeden argument listy niż kilka oddzielnych argumentów. Podczas uzyskiwania dostępu
$_
możesz wywoływać na nim metody, zaczynając od kropki: np..sort
Jest równa$_.sort
.Pamiętaj jednak, że każdy blok ma swój własny
$_
, więc parametry bloku zewnętrznego nie będą się rozchodzić do wewnętrznych. Jeśli chcesz uzyskać dostęp do parametrów funkcji głównej z wewnętrznego bloku, ...Użyj
^
zmiennych, jeśli nie możesz użyć$_
Włóż
^
między sigil i nazwy zmiennej, na przykład:$^a
. Działają one tylko wewnątrz bloku. Kompilator najpierw zlicza ich liczbę w bloku, sortuje je leksykograficznie, a następnie przypisuje pierwszy argument do pierwszego, drugi do drugiego i tak dalej. The^
z niego korzystać tylko przy pierwszym wystąpieniu zmiennej. Więc{$^a - $^b}
bierze 2 skalary i odejmuje je. Liczy się tylko kolejność alfabetyczna, podobnie{-$^b + $^a}
jak to samo.Jeśli kiedykolwiek masz ochotę użyć spiczastej składni bloku (jak
->$a,$b {$a.map:{$_+$b}}
), o wiele lepiej jest napisać fałszywą instrukcję na początku bloku, używając^
dla każdego argumentu, którego nie będziesz używać w bloku głównym (jak{$^b;$^a.map:{$_+$b}}
) (Uwaga) jest to lepszy sposób na golfa{$^a.map(*+$^b)}
. Chciałem tylko pochwalić się tą koncepcją.)Przeczytaj dokumenty operatora uważnie
Operatorzy są bardzo potężni i często są najkrótszym sposobem na załatwienie sprawy. Zwłaszcza meta-operatorzy (operatorów, które mają operatorów jako argument)
[]
,[\]
,X
,<<
/>>
iZ
są warte Twojej uwagi. Nie zapominaj, że meta-op może podjąć inną meta-op jako argument (jakXZ%%
udało mi się użyć tutaj ). Możesz także użyć>>
wywołania metody, które może być znacznie tańsze niż mapa (@list>>.method
zamiast@list.map(*.method)
, ale uwaga, to nie to samo! ). I wreszcie, zanim użyjesz pliku binarnego<< >>
, pamiętaj o tymZ
często robi to samo przy znacznie mniejszej liczbie znaków.Jeśli nakładasz na siebie wiele metaoperacji, możesz określić pierwszeństwo za pomocą nawiasów kwadratowych
[]
. Dzięki temu zaoszczędzisz, gdy zgromadzisz tak wiele operatorów, że dezorientuje to kompilator. (To nie zdarza się często.)W końcu, jeśli trzeba zmusić warte Bool, int lub STR, nie używać metod
.Bool
,.Int
a.Str
, ale operatorzy?
,+
a~
. Lub jeszcze lepiej, po prostu wprowadź je do wyrażenia arytmetycznego, aby zmusić je do Int i tak dalej. Najkrótszym sposobem na uzyskanie długości listy jest+@list
. Jeśli chcesz obliczyć 2 do potęgi długości listy, po prostu powiedz,2**@list
a zrobi to The Right Thing.Użyj zmiennych stanu swobodnego
$
,@
i%
W każdym bloku każde wystąpienie
$
(lub@
lub%
) odnosi się do nowej błyszczącej zmiennej stanu skalarnego (lub tablicy lub skrótu) (zmiennej, której wartość utrzymuje się podczas wywołań bloku). Jeśli potrzebujesz zmiennej stanu, do której należy odwoływać się tylko raz w kodzie źródłowym, te trzy są twoimi wielkimi przyjaciółmi. (Najczęściej$
.) Na przykład w wyzwaniu Odwrotne cykle matematyczne można go użyć do cyklicznego wybierania operatorów z tablicy, która została zindeksowana$++%6
.Skorzystaj z podform
map
,grep
i in.To znaczy: raczej rób
map {my block},list
niżlist.map({my block})
. Nawet jeśli uda ci się użyćlist.map:{my block}
, te dwa podejścia mają tę samą liczbę bajtów. I często trzeba wywoływać listę w nawiasie podczas wywoływania metody, ale nie podczas wywoływania podrzędnego. Tak więc podejście podrzędne wychodzi zawsze lepiej lub przynajmniej tak samo jak metoda pierwsza.Jedynym wyjątkiem jest sytuacja, w której znajduje się obiekt, który ma być
map
ped,grep
ped i tak dalej$_
. Wtedy.map:{}
oczywiście bijemap {},$_
.Użyj skrzyżowań (
&
i|
) zamiast&&
i||
.Oczywiście są one o 1 bajt krótsze. Z drugiej strony należy je zwinąć, zmuszając je do kontekstu logicznego. Można to zawsze zrobić za pomocą
?
. Tutaj powinieneś zdawać sobie sprawę z meta-op,!
op
która wymusza kontekst bool, używaop
i neguje wynik.Jeśli masz listę i chcesz zamienić ją w skrzyżowanie, nie używaj
[&]
i[|]
. Zamiast tego użyj.any
i.all
. Są też takie,.none
których nie da się tak łatwo naśladować w połączeniach.źródło
&&
i||
nadal są przydatne w przypadku zwarcia?Zmniejsz miejsce używane na zmienne
Jest w tym kilka części.
Usuń białe znaki
Zmienne zadeklarowane za pomocą
my
zwykle można zadeklarować bez spacji międzymy
nazwą zmiennej i.my @a
jest równoważne zmy@a
.Używaj zmiennych bez pieczęci
Możesz zadeklarować zmienne za pomocą ukośnika odwrotnego, aby usunąć znak przed nazwą zmiennej, na przykład:
(niestety nie można usunąć spacji :()
Jest to przydatne, ponieważ później można nazywać je tylko samą nazwą zmiennej.
Zasadniczo oszczędza to bajty, jeśli używasz zmiennej więcej niż raz w innym miejscu w kodzie. Minusem jest to, że zmienna musi zostać zainicjowana.
Użyj
$!
i$/
Te wstępnie zadeklarowane zmienne są zwykle używane odpowiednio dla wyjątków i dopasowań wyrażenia regularnego, ale nie trzeba ich definiować za pomocą
my
.Szczególnie przydatne jest użycie
$/
jako tablicy i użycie skrótów,$
po których następuje liczba, aby uzyskać dostęp do tego elementu$/
tablicy;źródło
Użyj
...
zamiastfirst
Zazwyczaj, jeśli chcesz znaleźć pierwszy numer, który pasuje do jakiegoś warunku
&f
, możesz go przedstawić w następujący sposób:Zamiast tego możesz użyć
...
operatora:Jeśli musisz zacząć
0
, możesz-1
później+
.Jeśli chcesz indeks pierwszego elementu na liście,
@a
która ma warunek&f
, zwykle robisz:Zamiast:
(lub odwrotnie, jeśli chcesz 0 indeksowanych). W ten sam sposób możesz uzyskać wszystkie elementy aż do pierwszego, który spełni warunek.
Wadą tego jest to, że lista musi spełnić warunek w pewnym momencie, w przeciwnym razie
...
operator spróbuje ekstrapolować poza koniec listy i najprawdopodobniej wyśle błąd. Nie można również użyć dowolnego kodu po lewej stronie, ponieważ byłby interpretowany jako część sekwencji.źródło