val()=hd[(fn s=>let val$ =s^"\""^String.toString s^"\"]"val(189,%)=(size$,$)in print%end)"val()=hd[(fn s=>let val$ =s^\"\\\"\"^String.toString s^\"\\\")\"val(189,%)=(size$,$)in print%end)"]
온라인으로 사용해보십시오!
MLton를 들어, 전체 SML 프로그램 중 하나에 의해 구분 및 종료 표현식 ;
(예 : print"Hello";print"World";
포함) 또는 선언 var
및 fun
키워드 (예 var _=print"Hello"var _=print"World"
) _
또한 모든 변수의 이름으로 대체 할 수있는 와일드 카드이다는.
첫 번째 옵션은 ;
자체적으로 유효한 프로그램 이므로 아무것도하지 않지만 오류는 발생하지 않기 때문에 원시 프로그래밍에는 쓸모 가 없습니다. 두번째 접근 방식의 문제는 같은 선언 var _=print"Hello"
을 단축 할 수있는 것과 var _="Hello"
(또는 var _=print
)을 선언하기 때문에 var
긴 우측만큼 작품 유효한 SML 식 또는 값 (기능 수 있도록 SML는, 기능적인 언어이다 값으로도 사용됨).
이 시점에서 우연히-선언에서 패턴 일치 를 우연히 발견했을 때 SML에서 원시 프로그래밍을 불가능하게 선언 할 준비가되었습니다 val
. 선언의 구문은가 val <variable_name> = <expression>
아니라 val <pattern> = <expression>
패턴이며 변수 이름, 상수 및 생성자로 구성 될 수 있습니다. 는 AS print
기능 유형을 가지고 string -> unit
, 우리는에 패턴 일치를 사용할 수 있습니다 unit
- 값 ()
인쇄 기능이 실제로 문자열에 적용되어 시행 : val()=print"Hey"
. 이 방법을 어느 제거 print
또는 "Hey"
A의 결과 Pattern and expression disagree
-error.
이러한 원시 인쇄 방식을 사용하면 다음 단계는 퀴네를 작성하는 것입니다. 마지막으로 저장 보호 기능을 추가해야합니다. 이전에는 쉬운 SML quine 기술을 사용 했지만 ( 개정 기록 참조 ) Anders Kaseorg는 자신의 경우 일부 바이트를 절약 할 수있는 다른 접근 방식을 지적했습니다. 내장 String.toString
함수를 사용하여 문자열 이스케이프를 처리하고 일반적인 형식 <code>"<data>"
이며 여기서 "<data>"
이스케이프 된 문자열은 다음과 code
같습니다.
val()=(fn s=>print(s^"\""^String.toString s^"\""))"val()=(fn s=>print(s^\"\\\"\"^String.toString s^\"\\\"\"))"
이것은 작동하는 헛소리이지만 아직 깨끗하지는 않습니다. 우선 Anders Kaseorg는 MLton이 작은 따옴표 "
를 오류없이 코드로 받아들이는 것을 발견했습니다. 즉 , 위와 같이 따옴표로 끝나는 코드를 가질 수 없습니다. 이를 방지하는 가장 짧은 방법 val()=
은 괄호로 묶은 후 모든 것을 래핑하는 것이지만 코드를로 줄일 수 있습니다 val()=()
. 내가 찾은 두 번째 가장 짧은 방법은을 사용하는 것입니다 val()=hd[ ... ]
. 즉, 모든 것을 목록으로 묶고 첫 번째 요소를 반환하여 형식 검사기를 행복하게 만듭니다.
데이터 문자열의 일부를 눈치 채지 않고 제거 할 수 없도록하기 위해 val
선언 에서 패턴 일치를 다시 사용하면 편리합니다. 인쇄 할 최종 문자열의 길이 (및 프로그램 길이)는 195와 같아야합니다. 대신에 추상화 let val t=... val 195=size t in print t end
의 본문에 쓸 수 있습니다 . 문자열의 일부를 제거하면 길이가 189보다 작으므로 예외가 발생합니다.fn
print(...)
Bind
여전히 문제가 남아 있습니다. 전체 val 195=size t
검사를 간단히 취소 할 수 있습니다. : 우리는 튜플에 일치의 체크를 확장하여이 문제를 방지 할 수 있습니다 val t=... val(216,u)=(n+size t,t)in print u end
, 언 바운드 변수에 검사 결과를 제거하도록 u
.
전체적으로 다음과 같은 195 바이트 솔루션이 생성됩니다.
val()=hd[(fn s=>let val t=s^"\""^String.toString s^"\")"val(195,u)=(size t,t)in print u end)"val()=hd[(fn s=>let val t=s^\"\\\"\"^String.toString s^\"\\\")\"val(195,u)=(size t,t)in print u end)"]
같은 조작 변수 이름 이용하는 골프 트릭인가 !
, $
그리고 %
대신 n
, t
및 u
일부 흰 공간을 절약하기 위하여이 (볼 이 팁 마지막 182 바이트 버전 리드).
설명에 명시 적으로 언급되지 않은 다른 모든 하위 문자열 제거는 구문 또는 유형 오류를 발생시킵니다.
편집 1 : length(explode t)
그냥 size t
입니다.
편집 2 : 다른 quine 접근법과 "취약점"을 지적한 Anders Kaseorg에게 감사드립니다.