Co, ten post jeszcze nie istnieje?
Oczywiście, GolfScript jest stworzony do gry w golfa, więc możesz pomyśleć, że tak naprawdę nie są potrzebne żadne konkretne wskazówki. Aby jednak w pełni wykorzystać funkcje GolfScript, musisz nauczyć się kilku nieoczywistych sztuczek. Ten post służy do zbierania przydatnych porad i wskazówek.
Na początek oto oficjalne strony referencyjne GolfScript. Najpierw powinieneś naprawdę zapoznać się z tymi:
W szczególności bardzo polecam przeczytanie stron w tej kolejności - szybki przegląd jest mało przydatny, dopóki nie zaznajomisz się z wbudowanymi funkcjami, a samouczek zawiera kilka ważnych szczegółów, które nie zostały wyjaśnione na innych stronach .
Ps. Ze względu na inspirację i osobiste zainteresowania, oto kilka pytań , na które chciałbym znaleźć miłe odpowiedzi:
Jak wykonać ograniczoną transliterację w GolfScript?
{FROM?TO=}%
działa, jeśli możesz być pewien, że wszystkie dane wejściowe znajdują się wFROM
(lub nie przejmuj się, że wszystkie są mapowane do ostatniego elementuTO
), ale wszystkie sposoby, w jakie widziałem pozostawienie niezmapowanych wartości bez zmian, były mniej lub bardziej klugey.Jak najlepiej przekonwertować ciąg znaków na tablicę kodów ASCII i odwrotnie? Jakie operacje powodują to jako efekt uboczny? Jaki jest najlepszy sposób na zrzucenie znaków ciągu znaków na stos (podobnie jak w
~
przypadku tablic)?
źródło
... x
się... [x]
? Najlepsze, co mogę zobaczyć, to[.;]
.x
jest liczbą, to[]+
działa i jest o jeden znak krótszy. I oczywiście, jeślix
jest to jedyna rzecz na stosie, to po prostu]
zrobi.Odpowiedzi:
Racjonalny / zmiennoprzecinkowy / złożony
Czytałem tyle razy, że GolfScript ma tylko liczby całkowite, że zacząłem w to wierzyć. Cóż, to nieprawda.
Dane wyjściowe to
ze standardowym interpreterem GolfScript i
na Web GolfScript .
Podobne hacki pozwalają rzucać na Rational, Float lub nawet Complex:
źródło
Gint.new(@val**b.val)
. Wygląda na to, żeGint
konstruktorowi brakuje int int ...Negowanie liczby
Jedną z rzeczy, której brakuje GolfScript, jest wbudowany operator negacji. Oczywiste sposoby przekonwertowania liczby ze stosu na liczbę ujemną, takie jak
-1*
lub0\-
, wymagają trzech znaków. Jest jednak sposób na zrobienie tego na dwa sposoby:Działa to, ponieważ GolfScript używa arytmetyki dopełniania dwóch , więc ~ x równa się - x −1.
Oczywiście wariant
(~
działa również; wybór między nimi jest ogólnie kwestią gustu.źródło
Przetasowanie tablicy
Najprostszym sposobem przetasowania tablicy w GolfScript jest sortowanie według losowego klucza sortowania. Jeśli potrzebujesz tylko tandetnie przetasować kilka wartości, zrobi to następujący kod:
Pamiętaj, że nawet w przypadku krótkich list nie da to dobrego losowania. Z powodu paradoksu urodzinowego , aby uzyskać rozsądnie jednolite tasowanie, argument
rand
musi być znacznie większy niż kwadrat długości tasowanej listy.Zastąpienie
9
powyższego przez99
daje zatem całkiem dobre wyniki dla list składających się z maksymalnie dziesięciu elementów, ale wykazuje zauważalne odchylenie dla dłuższych list.Poniższy kod, który używa 9 9 = 387,420,489 możliwych wartości, jest odpowiedni dla około 1000 pozycji (i jest akceptowalny dla około 20 000):
W przypadku naprawdę długich list dodaj jeszcze 9 dla wartości 99 99 ≈ 3,7 × 10 197 :
Testowanie:
Oto rozkład pierwszego elementu na 10-elementowej liście, przetasowanej przy użyciu różnych wariantów pokazanych powyżej, z próbkami ponad 10 000 prób:
Dane wyjściowe
10,{;9rand}$0=
pokazują bardzo wyraźne uprzedzenie, przy0
czym prawdopodobieństwo trzykrotnego wylądowania na pierwszej pozycji jest następujące1
:Z
10,{;99rand}$0=
, większość odchyleń zniknęła, ale wciąż pozostaje zauważalna ilość:Z
10,{;9.?rand}$0=
, wynik jest w zasadzie nie do odróżnienia od prawdziwie losowej próbki:Ps. W przypadku naprawdę złego tasowania tablic lub ciągów liczbowych następujący kod może być czasem akceptowany:
Na ogół będzie on absurdalnie tendencyjny, ale dopóki wszystkie elementy tablicy wejściowej (lub wszystkie kody znaków w łańcuchu) będą większe niż jeden, ma niezerowe prawdopodobieństwo wytworzenia dowolnej permutacji tablicy, która czasami może spełnić źle napisane wymagania dotyczące wyzwań.
źródło
Aby odpowiedzieć na konkretne pytanie:
Dla tych, którzy nie rozumieją problemu, system typów GolfScript daje pierwszeństwo typom w kolejności: liczba całkowita, tablica, ciąg, blok. Oznacza to, że zwykłe operacje tablicowe zastosowane do ciągu prawie zawsze dają ciąg. Na przykład
pozostawi
'BCD234'
na stosie.W rezultacie najlepszym sposobem na konwersję łańcucha znaków na tablicę kodów ASCII jest prawie na pewno zrzucenie znaków ze stosu, a następnie zebranie ich w tablicę.
Jaki jest najlepszy sposób na zrzucenie znaków w ciągu na stos?
{}/
Jaki jest najlepszy sposób przekonwertowania ciągu znaków na tablicę kodów ASCII?
[{}/]
(ze zwykłym zastrzeżeniem, że jeśli na stosie nie ma nic więcej, możesz pominąć[
)Jaki jest najlepszy sposób na konwersję tablicy kodów ASCII na ciąg?
''+
(Zauważ, że to również spłaszcza tablicę, więc np.[65 [66 67] [[[49] 50] 51]]''+
Daje'ABC123'
)źródło
[]+''+
? (wydaje się raczej długi)Jeśli Twój program w tajemniczy sposób się psuje, sprawdź swoje zmienne
Właśnie spędziłem chwilę na debugowaniu pozornie poprawnego programu, który był używany
!
jako zmienna (na tej podstawie, że nie zamierzałem go ponownie używać). Niestety nie używaniaif
, a okazuje się, że realizacjaif
połączeń!
zdecydować, który oddział do naśladowania.źródło
Zawijanie górnego elementu stosu w tablicę
Dla pełnej ogólności najlepszą opcją wydają się 4 znaki. Jednak w niektórych szczególnych przypadkach można to zmniejszyć.
1 znak
]
działa w specjalnym przypadku, któryx
jest jedyną rzeczą na stosie.3 znaki
[]+
działa w specjalnym przypadku, któryx
jest liczbą całkowitą..,/
działa w specjalnym przypadku, którymx
jest prawdziwa tablica lub ciąg znaków. Np"AB".,/
daje["AB"]
;3,.,/
daje[[0 1 2]]
. Jednak"".,/
i[].,/
oba dają[]
.4 znaki
[.;]
działa bezwarunkowo.źródło
To dobre pytanie. W GolfScript nie ma bezpośredniego sposobu przypisania wartości do elementu tablicy, więc w ten czy inny sposób będziesz musiał odbudować całą tablicę.
Najkrótszym ogólnym sposobem, jaki znam, aby wstawić nową wartość
x
indeksui
do tablicy, jest podzielenie tablicy pod danym indeksem i dołączeniex
do pierwszej połowy przed ponownym połączeniem ich ze sobą:.i<[x]+\i>+
(11 znaków) - wstaw wartośćx
do tablicy o indeksie (0)i
Aby zastąpić wartości w indeksie
i
zx
, po prostu trzeba skrócić drugą połowę tablicy o jeden element:.i<[x]+\i)>+
(12 znaków) - zamień element o indeksie (0)i
na wartośćx
Alternatywnie, skrócenie pierwszej połowy zamiast tego skutecznie zrobi to samo, ale z indeksowaniem opartym na 1, co czasami może być preferowane:
.i(<[x]+\i>+
(12 znaków) - zamień element o indeksie (1)i
wartościąx
We wszystkich powyższych przykładach, jeśli
x
jest liczbą, nawiasy kwadratowe wokół niej można pominąć, aby zapisać dwa znaki, ponieważ i tak zostanie ona automatycznie zmuszona do tablicy+
:.i<x+\i>+
(9 znaków) - wstaw liczbęx
do tablicy o indeksie (0)i
.i<x+\i)>+
(10 znaków) - zamień element o indeksie (0)i
na liczbęx
.i(<x+\i>+
(10 znaków) - zamień element o indeksie (1)i
na liczbęx
Nawiasy można również pominąć, jeśli jeden
x
lub wejściowa „tablica” (lub obie) są w rzeczywistości łańcuchami, w którym to przypadku wynik zostanie również wymuszony na ciąg znaków (przy użyciu zwykłych reguł konwersji tablic → ciągów znaków).Ps. W szczególnym przypadku, jeśli wiemy, że tablica zawiera między
i
2 x 2i
elementy, możemy wstawić nowy elementx
w indeksie (0) zai
pomocąi/[x]*
(6 znaków). To, co tak naprawdę robi, polega na podzieleniu tablicy na części składające się z maksymalniei
elementów i wstawieniux
między każdą porcją. Zauważ, że w tym przypadku nawiasy są konieczne, nawet jeślix
jest liczbą.Pps. Alternatywnym podejściem jest użycie dynamicznie nazwanych zmiennych. Na przykład,
przypisze wartość
'foo'
do zmiennejx42
, natomiastodzyska to.
Możesz to dalej zoptymalizować, pomijając
x
prefiks i po prostu przypisując bezpośrednio do literałów liczbowych - jest to całkowicie legalne w GolfScript i pozwala zapisać jeden znak z kodu przypisania i skrócić kod pobierania do po prostu`~
(lub w ogóle do niczego, jeśli wskaźnik jest stały!). Wadą jest oczywiście to, że przypisanie literału liczbowego zastąpi jego wartość w dowolnym miejscu w kodzie. Często jednak można uniknąć literałów liczbowych (lub przynajmniej ograniczyć się do początku programu, zanim którykolwiek z nich zostanie ponownie przypisany), w którym to przypadku ta sztuczka jest w porządku.źródło
i
dla 9 bajtów:.[i=]/[x]*
Ostateczna manipulacja wyjściem
Domyślnie po zakończeniu programu interpreter GolfScript wyświetla wszystko na stosie oraz końcową nową linię, dokładnie tak, jakby Twój program zakończył się następująco:
Dokumentacja nie wspomina bezpośrednio, że interpreter dosłownie wywołuje wbudowane,
puts
aby wygenerować takie dane wyjściowe, i że to wbudowane jest dosłownie zdefiniowane jako:W ten sposób można stłumić lub manipulować ostateczną wyjście poprzez przedefiniowanie
jeśli czujesz się naprawdę skręcone). Oto kilka przykładów:
puts
,print
i / lubn
(lubPomiń ostatnią linię:
(Oczywiście możesz pominąć,
;
jeśli nie przeszkadza ci dodatkowy pusty łańcuch na stosie.)Całkowicie pomiń efekt końcowy:
To zastępuje
puts
wszystko, co się dzieje na stosie. Jeśli jest to coś, czego nie chcesz wykonać, możesz użyć np0:puts;
. Zamiast tego. Zauważ, że to również pomijap
(które jest zdefiniowane jako{`puts}:p;
), ale nadal możesz użyćprint
wyjścia, jeśli chcesz.źródło
nothing
masz na myśli\n
?];
do stłumienia końcowego wyniku.minimum maksimum
Aby znaleźć najmniejszą / największą wartość w tablicy, po prostu posortuj ją i weź pierwszy / ostatni element:
$0=
(3 znaki) - minimalny element w łuku$-1=
(4 znaki) - maksymalny element w tablicyJeśli znasz długość tablicy, która ma 10 elementów lub mniej, możesz znaleźć maksimum w trzech znakach, zastępując
-1
je indeksem ostatniego elementu.Jeśli masz wartości na stosie, możesz je najpierw zebrać do tablicy. W tym celu przydatna jest niekiedy sztuczka polegająca na
[\]
zebraniu dwóch górnych elementów stosu do tablicy, podczas[@]
gdy trzech górnych. W ten sposób otrzymujemy:[\]$0=
(6 znaków) - minimum dwie wartości na stosie[@]$0=
(6 znaków) - minimum trzy wartości na stosie[\]$1=
(6 znaków) - maksymalnie dwie wartości na stosie[@]$2=
(6 znaków) - maksymalnie trzy wartości na stosieTej samej sztuczki można również użyć do znalezienia mediany trzech wartości, które mogą być czasami przydatne:
[@]$1=
(6 znaków) - mediana trzech wartości na stosieOto kolejna potencjalnie użyteczna sztuczka polegająca na znalezieniu min / max dwóch wartości , pozostawiając oryginalne wartości na stosie :
.2$>$
(5 znaków) - znajdź minimum dwie wartości na stosie, pozostawiając oryginalne wartości nietknięte.2$<$
(5 znaków) - znajdź maksymalnie dwie wartości na stosie, pozostawiając oryginalne wartości nietknięteDziała to tak, że
.2$
klonuje dwa górne elementy na stosie w odwrotnej kolejności (tj.a b
→a b b a
),<
/>
porównuje kopie i zwraca 0 lub 1, a$
następnie skalar kopiuje jedną z dwóch wartości wejściowych w zależności od wyniku porównania.Jeśli masz na stosie dwie nieujemne liczby całkowite, możesz użyć
,\,&,
(5 znaków), aby znaleźć ich minimum i,\,|,
(5 znaków), aby znaleźć ich maksimum. Ta sztuczka używa odpowiednio ustawiania przecięcia i połączenia w zakresach. Możesz zapisać inną postać, jeśli można zastosować,
do każdego argumentu osobno, bez konieczności ich wymiany. Ponieważ ta metoda oblicza zakres dla każdego argumentu, nie jest bardzo wydajna dla większych liczb, ale może być bardzo przydatna dla mniejszych danych wejściowych.Jeszcze krótszym sposobem na znalezienie minimum dwóch nieujemnych liczb całkowitych na stosie jest
,<,
(3 znaki). Niestety, ta sztuczka nie działa w celu znalezienia maksimum.całkowita wartość
Wbudowany operator GolfScript wartości bezwzględnej to
abs
(3 znaki). Chociaż jest to o dwa znaki więcej niż wolałbym, ogólnie trudno go pokonać.W niektórych przypadkach (np. Do sortowania według wartości bezwzględnej) kwadrat liczby może być odpowiednim substytutem jego wartości bezwzględnej; można to obliczyć na dwa znaki, albo
2?
albo.*
. W ten sposób otrzymujemy:{.*}$0=
(7 znaków) - minimalny element według wartości bezwzględnej w tablicy{.*}$-1=
(8 znaków) - maksymalny element według wartości bezwzględnej w tablicyPodobnie, zamiast np. Testowania, czy wartość bezwzględna liczby jest mniejsza niż 3 za pomocą
abs 3<
(6 znaków, w tym spacja), możesz przetestować, czy jej kwadrat jest mniejszy niż 9 za pomocą.*9<
(4 znaki, nie potrzeba spacji).źródło
,\,&,
(5 znaków), aby znaleźć ich minimum i,\,|,
(5 znaków), aby znaleźć ich maksimum. Ta sztuczka używa odpowiednio ustawiania przecięcia i połączenia w zakresach. Możesz zapisać inną postać, jeśli można zastosować,
do każdego argumentu osobno, bez konieczności ich wymiany. Ponieważ ta metoda oblicza zakres dla każdego argumentu, nie jest bardzo wydajna dla większych liczb, ale może być bardzo przydatna dla mniejszych danych wejściowych.Usuwanie duplikatów z tablicy
Operatory zbioru
|
(zjednoczenie),&
(przecięcie) i^
(różnica symetryczna) zwiną wiele elementów tablicy w jeden. Zatem najprostszym sposobem na usunięcie zduplikowanych elementów z tablicy jest połączenie lub połączenie się ze sobą:lub:
Operatory te będą traktować ciągi znaków jako tablice znaków, więc można ich również użyć do usunięcia zduplikowanych znaków z ciągów znaków.
źródło
Ograniczona transliteracja
Aby odpowiedzieć na konkretne pytanie: w jaki sposób najlepiej wykonać dany ciąg
tr
? Na przykładtr/ABC/abc/
Jeśli wpłynie to na wszystkie znaki w ciągu, jest to dość łatwe:
{'ABC'?'abc'=}%
(narzut: 9 znaków).Jednak łamie się, jeśli niektóre postacie nie są transliterowane i
'ABC'?
daje-1
.Jeśli transliteracja nie jest cykliczna, można wykonać jedną zamianę na raz za pomocą ciągów znaków dzielących i łączących:
'AaBbCc'1/2/{~@@/\*}/
(narzut: 15 znaków). Można to poprawić, ale istnieje alternatywne podejście, które jest obecnie lepsze i działa w przypadku transliteracji cyklicznych.Obecnie najkrótsze ogólne rozwiązania mają narzut 14 znaków:
Jedno podejście obejmuje znak ucieczki: gdzie oznacza dosłowny bajt zerowy. (Oczywiście ta metoda nie jest całkowicie ogólna: nie może zamapować żadnego innego znaku na bajt zerowy).
{.'ABC'?'abc0'=\or}%
0
Alternatywnie,
{.'ABC'?'abc'@),+=}%
ma taki sam narzut, ale używa tylko drukowalnych znaków ASCII.@),+
Jest zwinięty (ale, jak widać, najkrótsza) sposobem zapewnienia, że ciąg wymiana zawsze kończy się znakiem wejściowego.źródło
'ABCDEF'
otrzymuję wynik'abc000'
, ale właściwy wynik byłby'abcDEF'
. Czy coś brakuje?Zamień ciąg znaków na tablicę znaków char
Możesz to zrobić, wpisując:
1/
po nim.Przykład:
"String"1/
wypycha, aby ułożyć tablicę w stos['S''t''r''i''n''g']
.Jest to przydatne, gdy chcesz przenosić znaki po łańcuchu.
źródło
"abc"1/(+
->"bca"
, ale"abc"(+
->bc97
.Przypisywanie do literałów liczbowych
Często zamiast pisać,
1:x
a następnie używać / aktualizować zmiennąx
, możesz po prostu użyć i zaktualizować1
bezpośrednio:Oczywiście działa to również w przypadku innych wartości początkowych, ale ulegnie awarii, jeśli ta wartość wystąpi gdziekolwiek indziej w kodzie.
Interpunkcja jako nazwy zmiennych
Jeśli masz do wykorzystania zmiennych, to również często mądry używać znaków interpunkcyjnych, który nie jest już w kodzie - wiele programów można zrobić bez
&
,|
,^
, lub?
. W ten sposób możesz na przykład napisać&n
zamiastx n
wypychać zmienną, a następnie wypychać nowy wiersz.źródło
!
często jest to zły pomysł, ponieważ będzie przerwaif
ido
(jak równieżwhile
,until
,and
,or
ixor
). Podobnie,or
jest definiowany przez tłumacza jako alias dla1$\if
, więc zmianę definicji1
,$
lub\
również złamać. Przedefiniowanie`
przerwp
.Filtrowanie tablicy
Najbardziej ogólnym sposobem filtrowania tablicy jest użycie
{ },
, która ocenia blok kodu dla każdego elementu tablicy i wybiera te elementy, dla których wynikowa wartość jest prawdziwa (tj. Działa jakgrep
w Perlu).Jednak użycie operatora odejmowania tablic
-
jest często krótsze. Ten operator pobiera dwie tablice i usuwa z pierwszego każdy element występujący w drugiej tablicy. Tak nie jest zmienia się kolejność elementów w pierwszej tablicy lub zwinąć duplikatów. Przydatną sztuczką jest dwukrotne zastosowanie operacji odejmowania w celu uzyskania nie przecinającego się operatora przecięcia tablicy:a b -
: usuń wszystkie elementy znalezione w tablicyb
z tablicya
a. b --
: usuń wszystkie elementy, które nie zostały znalezione w tablicyb
z tablicya
W szczególności można tego użyć do zliczenia liczby wystąpień elementu w tablicy:
a.[c]--,
: policz liczbę razy elementc
występuje w tablicya
Ogólnie rzecz biorąc, ta metoda nie jest optymalna, ponieważ:
a[c]/,(
: policz liczbę razy elementc
występuje w tablicya
a{c=},,
: policz liczbę razy elementc
występuje w tablicya
jest o jeden znak krótszy (i, jeśli liczenie jest wyłączone o jeden,
a[c]/,
zapisuje on o jeden znak więcej). Jednak w szczególnym przypadku, gdyc
jest liczbą ia
jest normalną tablicą (nie ciągiem), nawiasy kwadratowe wokółc
można pominąć, ponieważ-
operator wymusza argumenty na ten sam typ:a.c--,
: policz ile razy liczbac
występuje w tablicy (nie łańcuch!)a
(Jeśli
a
jest łańcuchem ic
jest liczbą od 0 do 9,a.c--
policzy liczbę razy cyfrac
występuje wa
.)Podobną sztuczkę można zastosować do znalezienia najczęstszego elementu w tablicy :
Ponownie, jeśli dane wejściowe są tablicą liczb, cała
[.]
sekwencja może zostać pominięta. Niestety, nie działa to na ciągi bez[.]
.źródło
a[c]/,(
ia{c=},,
są o jeden bajt krótsze.Czytaj ze STDIN
GolfScript może czytać ze standardowego:
To będzie kontynuować czytanie od STDIN aż do osiągnięcia EOF. Alternatywnie:
lub
Inne dostępne rzeczy:
Dla każdego z nich można ich użyć tylko raz (i także raz przy każdej zmianie parametru, także jeszcze raz z pustymi nawiasami); potem oryginalna wartość będzie tym, co otrzymasz zamiast nowej wartości.
źródło
{"#{STDIN.readline}"p}2*
która nie odczytuje 2 wierszy, ale zamiast tego łańcuch jest oceniany tylko raz.i
dowolną liczbę całkowitą,'"#{'i):i';STDIN.gets}"'++~
da ona inny wynik za każdym razem, gdy będzie ona oceniana. Warto również wspomnieć o backtickach. Jeśli założymy Linuksa, możemy użyć np.`head -1`
ZamiastSTDIN.gets
."#{var'g','gpush Gstring.new(STDIN.gets)'.cc}";
pozwala także zdefiniować nowego operatora GolfScript,g
który odczytuje linię ze standardowego wejścia i wypycha ją na stos.Dekodowanie danych szesnastkowych
GolfScript nie ma liter szesnastkowych liczb całkowitych, więc niestety nie można po prostu parsować danych szesnastkowych
~
. Zamiast tego, jeśli twój kod musi pobierać dane szesnastkowe, musisz go przeanalizować ręcznie.Ta 8-znakowa pętla zastosowana do łańcucha przekształci małe cyfry szesnastkowe na ich numeryczne odpowiedniki:
Jeśli musisz (również) zaakceptować wielkie cyfry szesnastkowe, najłatwiejszym (i prawdopodobnie najkrótszym) rozwiązaniem jest najpierw użycie małych liter
32|
, w sumie 11 znaków:Zauważ, że wyjściowo technicznie nadal będzie to ciąg znaków (składający się ze znaków ASCII 0–15), ale większość funkcji tablicy GolfScript również akceptuje ciągi znaków. Jeśli absolutnie potrzebujesz tablicy, zawsze możesz jej użyć
[{39%9-}/]
(gdzie pierwsza[
jest opcjonalna, jeśli stos jest inaczej pusty).Aby przekonwertować wynik powyższego kodu na liczbę całkowitą, możesz po prostu użyć
16base
(6 znaków). Jeśli zamiast tego chcesz tablicę bajtów, najkrótszym rozwiązaniem, jakie znalazłem, było po prostu zdekodowanie każdej pary cyfr szesnastkowych za pomocą2/{16base}%
(11 znaków). Podsumowując, najkrótszy kod, który znalazłem, aby przekształcić ciąg szesnastkowy w tablicę bajtów, to 8 + 11 = 19 znaków:Zauważ, że wyjście tego kodu jest rzeczywiście tablicą, a nie łańcuchem. W razie potrzeby można go stringify przez złączenie go np
""+
, a jeśli nie masz nic przeciwko dodatkowej nowej linii na końcun+
.źródło
Definiowanie nowych wbudowanych operatorów
Standardowy interpreter GolfScript ma rzadko używaną funkcję która umożliwia interpolację kodu Ruby w literałach łańcuchowych z podwójnym cudzysłowem.
Jednym z powodów, dla których ta funkcja nie jest częściej używana, jest to, że niezręcznie interpolowany kod jest wykonywany w czasie kompilacji , a dane wyjściowe są buforowane przez interpreter GolfScript, dzięki czemu ten sam literał łańcuchowy zawsze będzie dawał tę samą wartość, nawet wewnątrz ciąg znaków eval.
Jednak okazuje się, że ta funkcja jest dobra dla definiowania nowych operatorów GolfScript zaimplementowanych w kodzie Ruby. Na przykład, oto jak zdefiniować nowy operator dodawania binarnego, który działa tak jak standardowy wbudowany
+
operator:Tak naprawdę nie ma znaczenia, gdzie umieścisz definicję w kodzie; nowy operator zostaje zdefiniowany, gdy tylko parsowany jest ciąg cudzysłowu zawierający kod Ruby.
add
Operator zdefiniowany powyżej działa dokładnie jak wbudowana+
operatora i mogą być stosowane w taki sam sposób:Oczywiście, zdefiniowanie nowego operatora dodawania jest dość bezużyteczne, chyba że zrobiłeś coś głupiego jak wymazanie wbudowanego
+
operatora . Ale możesz użyć tej samej sztuczki, aby zdefiniować nowe operatory, które robią rzeczy, których Golfscript nie może (łatwo) robić natywnie, na przykład równomiernie tasuje tablicę:lub drukowanie zawartości całego stosu:
lub interaktywne wejście:
a nawet dostęp do sieci:
Oczywiście nieco bardziej golfową (i bardziej ryzykowną!) Implementacją tego drugiego byłoby np .:
Chociaż sama w sobie nie jest golfistą, pozwala to rozszerzyć możliwości GolfScript poza to, co zapewniają wbudowane polecenia.
Jak to działa?
Autorytatywnym odniesieniem do sposobu definiowania nowych operatorów GolfScript w ten sposób jest oczywiście kod źródłowy interpretera . To powiedziawszy, oto kilka krótkich wskazówek:
Aby zdefiniować nowego operatora,
name
który uruchamia kod Rubycode
, użyj:Wewnątrz kodu użyj,
gpop
aby odczytać wartość ze stosu igpush
wypchnąć ją z powrotem. Możesz również uzyskać dostęp do stosu bezpośrednio przez tablicę$stack
. Na przykład, aby wcisnąć obaa
ib
na stos, jest bardziej golfisty$stack<<a<<b
niżgpush a;gpush b
.[
markerów początkowych tablicy są przechowywane w$lb
tablicy.gpop
Funkcja dba o dostosowanie tych markerów w dół, gdy psychiatrzy stosu poniżej ich pozycji, ale manipulowanie$stack
tablicę bezpośrednio nie.Metoda
.cc
ciągów, która kompiluje kod Ruby w ciągu znaków do operatora GolfScript, jest jedynie wygodnym rozwiązaniemGblock.new()
. Posiada również warianty.cc1
,.cc2
a.cc3
które sprawiają, że operator automatycznie pop 1, 2 lub 3 argumenty ze stosu i przypisać je do zmiennycha
,b
ic
. Istnieje również.order
metoda, która działa podobnie.cc2
, ale automatycznie sortuje argumenty według priorytetu typu .Wszystkie wartości na stosie GolfScript są (i powinny być!) Obiektów typu
Gint
,Garray
,Gstring
lubGblock
. Dostęp do podstawowej natywnej liczby całkowitej lub tablicy, w razie potrzeby, można uzyskać za pomocą tej.val
metody.Gstring.val
zwraca tablicęGint
s! Aby zamienićGstring
natywny ciąg Ruby, wywołaj.to_s
go zamiast tego (lub użyj go w kontekście, który robi to automatycznie, np. Interpolacja łańcucha). Wywołanie.to_gs
dowolnej wartości GS zamienia ją w aGstring
, więc dowolną wartość GS można powiązać.to_gs.to_s
.Ta
gpush
funkcja nie automatycznie zawija natywne liczby Ruby, ciągi znaków lub tablice w odpowiednie typy GS, więc często będziesz musiał zrobić to sam, jawnie wywołując npGstring.new()
. Jeśli wypchniesz na stos coś innego niż jeden z typów wartości GS, dowolny kod, który później spróbuje nim manipulować, może ulec awarii.Typy wartości GS mają również
.factory
metodę wywołującą konstruktor typu, co może być przydatne np. Do ponownego pakowania tablic / ciągów po manipulowaniu ich zawartością. Wszystkie typy mają również.coerce
metodę, która wykonuje wymuszenie typu :a.coerce(b)
zwraca parę zawierającąa
ib
wymuszoną na ten sam typ.źródło