새로운 내장 연산자 정의
표준 GolfScript 인터프리터에는 거의 사용되지 않는 기능 이있어 큰 따옴표로 묶인 문자열 리터럴로 보간 된 Ruby 코드를 허용합니다.
이 기능이 더 일반적으로 사용되지 않는 한 가지 이유는, 어색하게 보간 된 코드가 컴파일 타임에 실행 되고 출력이 GolfScript 인터프리터에 의해 캐시되어 동일한 문자열 리터럴이 이후에도 항상 동일한 값을 산출하기 때문입니다 문자열 평가.
그러나이 기능이 유용한 것으로 밝혀진 것은 Ruby 코드로 구현 된 새로운 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
스택에서 값을 읽고 gpush
다시 푸시합니다 $stack
. 배열을 통해 스택에 직접 액세스 할 수도 있습니다 . 예를 들어 스택 a
과 b
스택에 모두 밀어 넣으 려면 $stack<<a<<b
보다 골퍼 gpush a;gpush b
입니다.
[
어레이 시작 마커 의 위치는 어레이에 저장됩니다 $lb
. 이 gpop
기능은 스택이 해당 위치 아래로 축소되는 경우 이러한 마커 조정을 처리하지만 $stack
배열을 직접 조작 해도 그렇지 않습니다.
.cc
문자열에서 Ruby 코드를 GolfScript 연산자로 컴파일 하는 문자열 메소드는 편리한 래퍼 Gblock.new()
입니다. 또한 변형을 가지고 .cc1
, .cc2
그리고 .cc3
그 운전자가 자동으로 스택에서 1, 2 또는 3 인수를 팝업 변수에 할당 할 a
, b
하고 c
. 유형 우선 순위 별로 인수를 자동으로 정렬한다는 점을 제외하고 .order
는 작동 하는 메소드 도 있습니다 ..cc2
GolfScript 스택의 모든 값은 (와!이어야 함) 형식의 개체 Gint
, Garray
, Gstring
또는 Gblock
. 필요한 경우 기본 네이티브 정수 또는 배열에 .val
메소드 를 통해 액세스 할 수 있습니다 .
- 그러나 s
Gstring.val
배열 을 반환합니다 Gint
. Gstring
a를 네이티브 Ruby 문자열로 바꾸려면 .to_s
대신 호출 하십시오 (또는 문자열 보간과 같이 자동으로 수행하는 컨텍스트에서 사용하십시오). .to_gs
GS 값을 호출 하면이 Gstring
값이로 바뀌므로 모든 GS 값을로 문자열화할 수 있습니다 .to_gs.to_s
.
이 gpush
함수는 네이티브 Ruby 숫자, 문자열 또는 배열을 해당 GS 유형으로 자동 랩핑하지 않으므로, 명시 적으로 eg를 호출하여 직접 수행해야합니다 Gstring.new()
. GS 값 유형 중 하나 이외의 것을 스택에 푸시하면 나중에 해당 코드를 조작하려고 시도하는 코드가 충돌 할 수 있습니다.
GS 값 형식 .factory
에는 형식의 생성자를 호출 하는 메서드 도 있습니다.이 메서드는 내용을 조작 한 후 배열 / 문자열을 다시 래핑하는 데 유용 할 수 있습니다. 모든 유형은 또한이 .coerce
수행하는 것이 방법 강제 형 변환이 : a.coerce(b)
포함 된 한 쌍의 반환 a
과 b
동일한 유형 강제 변환합니다.
... x
에가... [x]
? 내가 볼 수있는 최고는[.;]
입니다.