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. addOperatö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:
nameRuby kodunu çalıştıran yeni bir operatör tanımlamak için şunu codekullanın:
var'name','code'.cc
Kodun içinde, gpopyığından bir değer okumak ve gpushgeri almak için kullanın. Yığına doğrudan dizi yoluyla da erişebilirsiniz $stack. Örneğin , yığının her ikisine ave byığına itmek, yapmaktan $stack<<a<<bdaha golfcüdür gpush a;gpush b.
[Dizi başlangıç işaretleyicilerinin pozisyonları dizide saklanır $lb. gpopFonksiyon yığın daralmaları konumları aşağıdaki ise aşağı bu belirteçler ayarlanması ancak manipüle ilgilenir $stack, doğrudan dizi değildir.
.ccBir 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, .cc2ve .cc3bu operatör otomatik yığın kapalı, 1, 2 ya da 3 argüman açılır ve değişkenlere atamak yapmak a, bve c. Argüman türlerini otomatik olarak önceliğe göre sıralaması dışında, bunun .ordergibi çalışan bir yöntem de vardır ..cc2
GolfScript yığında tüm değerler (ve! Olmalıdır) tip nesneler Gint, Garray, Gstringya da Gblock. Temelde bulunan yerel tamsayıya veya diziye ihtiyaç duyulduğunda yöntemle erişilebilir .val.
- Ancak, s
Gstring.valdizisini döndüren not Gint! Bir açmak için Gstringbir yerli Ruby dizeye çağrıyı .to_syerine üzerinde (veya dize enterpolasyon gibi otomatik Bunu yapan bir bağlamda kullanın). .to_gsHerhangi bir GS değerini çağırmak onu bir Gstringa'ya dönüştürür , böylece herhangi bir GS değeri ile sıralanabilir .to_gs.to_s.
Bu gpushiş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 .coerceyönteme sahiptir : aynı tip içeren ve zorlanan bir çifti döndürür .a.coerce(b)ab
... xiçine... [x]? Görebildiğim en iyi şey[.;].