การกำหนดตัวดำเนินการในตัวใหม่
ล่าม GolfScript มาตรฐานมีคุณสมบัติที่ไม่ค่อยได้ใช้ที่อนุญาตให้มีการแก้ไขโค้ดรูบี้ในตัวอักษรสตริงที่ยกมาสองครั้ง
เหตุผลหนึ่งคุณลักษณะนี้ไม่ได้ใช้กันอย่างแพร่หลายคือว่าเชื่องช้ารหัสหยันจะถูกดำเนินการที่รวบรวมเวลาและการส่งออกจะถูกเก็บไว้โดยล่าม GolfScript เพื่อให้ตัวอักษรสตริงเดียวกันจะหลังจากนั้นมักจะให้ผลผลิตที่มีมูลค่าเท่ากันแม้ภายใน สตริง eval
อย่างไรก็ตามสิ่งหนึ่งที่คุณสมบัตินี้ดีสำหรับการกำหนดตัวดำเนินการ GolfScript ใหม่ที่ใช้ในรหัสทับทิม ตัวอย่างเช่นต่อไปนี้เป็นวิธีการกำหนดตัวดำเนินการเพิ่มเติมไบนารีใหม่ที่ทำงานเหมือนกับตัวดำเนินการมาตรฐานใน+
ตัว:
"#{var'add','gpush a+b'.cc2}";
ไม่สำคัญว่าคุณใส่คำจำกัดความไว้ในรหัสของคุณที่ใด ตัวดำเนินการใหม่จะถูกกำหนดทันทีที่สตริงที่มีเครื่องหมายคำพูดคู่ที่มีรหัส Ruby ถูกวิเคราะห์คำ add
ผู้ประกอบการที่กำหนดไว้ข้างต้นงานว่าเหมือนตัวใน+
ผู้ประกอบการและสามารถนำมาใช้ในทางเดียวกันว่า:
1 2 add # evaluates to 3
"foo" "bar" add # evaluates to "foobar"
แน่นอนการกำหนดผู้ประกอบการนอกจากนี้ใหม่จะไร้ประโยชน์สวยถ้าคุณไม่ได้ทำอะไรโง่เหมือนลบในตัว+
ผู้ประกอบการ แต่คุณสามารถใช้เคล็ดลับแบบเดียวกันนี้เพื่อกำหนดตัวดำเนินการใหม่ที่ทำในสิ่งที่ Golfscript ไม่สามารถทำได้อย่างง่ายดาย (เช่น) กล่าวโดยทั่วไปคือการเรียงลำดับอาเรย์อย่างสม่ำเสมอ:
"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";
10,shuf # evaluates to 0,1,2,...,9 in random order
หรือพิมพ์เนื้อหาของสแต็กทั้งหมด:
"#{var'debug','puts Garray.new($stack).ginspect'.cc}";
4,) ["foo" debug # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched
หรืออินพุตแบบโต้ตอบ:
"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";
]; { "> " print gets ~ ]p 1 } do # simple GolfScript REPL
หรือแม้กระทั่งการเข้าถึงเว็บ:
"#{
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
แน่นอนว่านักกอล์ฟส่วนใหญ่ (และมีความเสี่ยง!) จะได้รับการปฏิบัติเช่นนี้:
"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";
ในขณะที่ไม่ได้เล่นกอล์ฟโดยเฉพาะมันช่วยให้คุณขยายขีดความสามารถของ GolfScript เกินกว่าที่คำสั่งในตัวจะมอบให้
มันทำงานยังไง?
การอ้างอิงที่มีสิทธิ์ในวิธีการกำหนดผู้ประกอบการ GolfScript ใหม่ในลักษณะนี้เป็นของหลักสูตรที่ซอร์สโค้ดล่าม ที่กล่าวว่านี่เป็นเคล็ดลับสั้น ๆ :
ในการกำหนดโอเปอเรเตอร์ใหม่name
ที่รันโค้ด Ruby code
ให้ใช้:
var'name','code'.cc
ภายในรหัสที่ใช้gpop
ในการอ่านค่าออกมาจาก stack และgpush
จะผลักดันหนึ่งกลับมาอยู่ใน. $stack
คุณยังสามารถเข้าถึงสแต็คโดยตรงผ่านอาร์เรย์ ตัวอย่างเช่นในการผลักดันให้ทั้งสองa
และb
บนสแต็คก็ golfier ที่จะทำมากกว่า$stack<<a<<b
gpush a;gpush b
- ตำแหน่งของ
[
เครื่องหมายเริ่มต้นอาร์เรย์จะถูกเก็บไว้ใน$lb
อาร์เรย์ gpop
ฟังก์ชั่นการดูแลของการปรับเครื่องหมายเหล่านี้ลงหากสแต็ค shrinks ด้านล่างตำแหน่งของพวกเขา แต่การจัดการกับ$stack
อาร์เรย์โดยตรงไม่ได้
.cc
วิธีสตริงที่รวบรวมรหัสทับทิมในสตริงเป็นผู้ประกอบการ GolfScript Gblock.new()
เป็นเพียงความสะดวกสบายรอบเสื้อคลุม นอกจากนี้ยังมีสายพันธุ์.cc1
, .cc2
และ.cc3
ที่ทำให้ผู้ประกอบการโดยอัตโนมัติ pop 1, 2 หรือ 3 ข้อโต้แย้งปิดสแต็คและกำหนดให้กับตัวแปรa
, และb
c
นอกจากนี้ยังมี.order
วิธีการที่ใช้งานได้.cc2
ยกเว้นว่าจะเรียงลำดับข้อโต้แย้งตามลำดับความสำคัญของประเภทโดยอัตโนมัติ
ค่าทั้งหมดในกอง GolfScript มี (และควรจะเป็น!) วัตถุชนิดGint
, Garray
, หรือGstring
Gblock
จำนวนเต็มพื้นฐานหรืออาเรย์พื้นฐานที่จำเป็นสามารถเข้าถึงได้ผ่าน.val
วิธีการ
- อย่างไรก็ตามโปรดทราบว่า
Gstring.val
ส่งคืนอาร์เรย์Gint
s! ในการเปลี่ยนเป็นGstring
สตริงรูทีนดั้งเดิมให้เรียก.to_s
ใช้แทน (หรือใช้ในบริบทที่ทำโดยอัตโนมัติเช่นการแก้ไขสตริง) การเรียก.to_gs
ใช้ค่า GS ใด ๆ จะเปลี่ยนเป็น a Gstring
เพื่อให้ค่า GS ใด ๆ สามารถทำให้เป็นสตริง.to_gs.to_s
ได้
gpush
ฟังก์ชั่นไม่ได้อัตโนมัติห่อหมายเลขทับทิมพื้นเมืองสตริงหรืออาร์เรย์ลงในประเภท GS Gstring.new()
สอดคล้องกันดังนั้นคุณมักจะต้องทำมันด้วยตัวคุณเองโดยชัดเจนเช่นการเรียก หากคุณกดรหัสอื่นใดที่ไม่ใช่ประเภท GS ลงในสแต็กรหัสใด ๆ ที่พยายามจะจัดการในภายหลังนั้นอาจมีปัญหาได้
ประเภทค่า GS ยังมี.factory
วิธีที่เรียกใช้ตัวสร้างของประเภทซึ่งจะมีประโยชน์เช่นสำหรับการ rewrapping อาร์เรย์ / สตริงหลังจากจัดการเนื้อหาของพวกเขา ประเภททั้งหมดยังมี.coerce
วิธีที่ดำเนินการบังคับประเภท : a.coerce(b)
ส่งคืนคู่ที่มีa
และb
บังคับให้เป็นประเภทเดียวกัน
... x
เป็น... [x]
?[.;]
ที่ดีที่สุดของฉันสามารถดูเป็น