Yeni yerleşik operatörleri tanımlama
Standart GolfScript yorumlayıcısı, çift tırnaklı dizgilerde enterpolasyonlu Ruby koduna izin veren nadiren kullanılan bir özelliğe sahiptir.
Bu özelliğin daha yaygın kullanılmamasının nedenlerinden biri , enteresan olarak , enterpolasyonlu kodun derleme zamanında çalıştırılması ve çıktının GolfScript yorumlayıcısı tarafından önbelleğe alınmasıdır, böylece aynı string değişmezi daha sonra her zaman aynı değeri verir. string eval.
Bununla birlikte, bu özelliğin iyi olduğu ortaya çıkan bir şey, Ruby kodunda uygulanan yeni GolfScript operatörlerini tanımlamaktır. Örneğin, standart yerleşik +
operatör gibi çalışan yeni bir ikili ekleme işlecini nasıl tanımlayacağınız :
"#{var'add','gpush a+b'.cc2}";
Tanımı kodunuzda nereye koyduğunuz önemli değil; yeni operatör Ruby kodunu içeren çift tırnaklı dize ayrıştırıldığında tanımlanır. add
Operatör eserler yukarıda tanımlanan aynen böyle yerleşik +
operatör ve tamamen aynı şekilde kullanılabilir:
1 2 add # evaluates to 3
"foo" "bar" add # evaluates to "foobar"
Tabii ki, yeni bir ekleme operatörü tanımlamak , yerleşik +
operatörü silmek gibi aptalca bir şey yapmadıysanız oldukça işe yaramaz . Ancak, aynı hileyi, Golfscript'in (kolayca) bir diziyi düzgün bir şekilde karıştırmak gibi doğal olarak yapamayacağı şeyleri yapan yeni operatörleri tanımlamak için kullanabilirsiniz:
"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";
10,shuf # evaluates to 0,1,2,...,9 in random order
veya tüm yığının içeriğini basmak:
"#{var'debug','puts Garray.new($stack).ginspect'.cc}";
4,) ["foo" debug # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched
veya etkileşimli girdi:
"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";
]; { "> " print gets ~ ]p 1 } do # simple GolfScript REPL
hatta web erişimi:
"#{
require 'net/http'
require 'uri'
var'get','gpush Gstring.new(Net::HTTP.get_response(URI.parse(a.to_s)).body)'.cc1
}";
"http://example.com" get
Tabii ki, ikincisinin bir nevi golfçü (ve daha riskli!) Uygulaması şöyle olacaktır:
"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";
Kendisinde özellikle golf sahası olmamakla birlikte, bu, GolfScript'in özelliklerini yerleşik komutların sağlamasının ötesine genişletmenize olanak tanır.
O nasıl çalışır?
Yeni GolfScript operatörlerinin bu şekilde nasıl tanımlandığına dair yetkili referans, elbette, tercüman için kaynak koddur . Yani, işte birkaç hızlı ipucu:
name
Ruby kodunu çalıştıran yeni bir operatör tanımlamak için şunu code
kullanın:
var'name','code'.cc
Kodun içinde, gpop
yığından bir değer okumak ve gpush
geri almak için kullanın. Yığına doğrudan dizi yoluyla da erişebilirsiniz $stack
. Örneğin , yığının her ikisine a
ve b
yığına itmek, yapmaktan $stack<<a<<b
daha golfcüdür gpush a;gpush b
.
[
Dizi başlangıç işaretleyicilerinin pozisyonları dizide saklanır $lb
. gpop
Fonksiyon yığın daralmaları konumları aşağıdaki ise aşağı bu belirteçler ayarlanması ancak manipüle ilgilenir $stack
, doğrudan dizi değildir.
.cc
Bir GolfScript operatörü içine dizede Ruby kodu derler dize yöntemi etrafında sadece bir kolaylık sarıcı Gblock.new()
. Ayrıca varyantları bulunur .cc1
, .cc2
ve .cc3
bu operatör otomatik yığın kapalı, 1, 2 ya da 3 argüman açılır ve değişkenlere atamak yapmak a
, b
ve c
. Argüman türlerini otomatik olarak önceliğe göre sıralaması dışında, bunun .order
gibi çalışan bir yöntem de vardır ..cc2
GolfScript yığında tüm değerler (ve! Olmalıdır) tip nesneler Gint
, Garray
, Gstring
ya da Gblock
. Temelde bulunan yerel tamsayıya veya diziye ihtiyaç duyulduğunda yöntemle erişilebilir .val
.
- Ancak, s
Gstring.val
dizisini döndüren not Gint
! Bir açmak için Gstring
bir yerli Ruby dizeye çağrıyı .to_s
yerine üzerinde (veya dize enterpolasyon gibi otomatik Bunu yapan bir bağlamda kullanın). .to_gs
Herhangi bir GS değerini çağırmak onu bir Gstring
a'ya dönüştürür , böylece herhangi bir GS değeri ile sıralanabilir .to_gs.to_s
.
Bu gpush
işlev, yerel Ruby numaralarını, dizeleri veya dizileri ilgili GS türlerine otomatik olarak sığdırmaz; bu nedenle, örneğin açıkça çağırıp sık sık kendiniz yapmanız gerekir Gstring.new()
. Yığına GS değer türlerinden biri dışında bir şeyi iterseniz, daha sonra üzerinde işlem yapmaya çalışan herhangi bir kodun çökmesi olasıdır.
GS değer tipleri ayrıca, .factory
örneğin içeriklerini değiştirdikten sonra dizileri / dizgileri yeniden sarmak için yararlı olabilecek, türün yapıcısını çağıran bir yönteme sahiptir. Tüm tipler aynı zamanda tip zorlama uygulayan bir .coerce
yönteme sahiptir : aynı tip içeren ve zorlanan bir çifti döndürür .a.coerce(b)
a
b
... x
içine... [x]
? Görebildiğim en iyi şey[.;]
.