(~!)(!)((~)~*):((!)~^)*(:^)(~(!)~^(~)~*)(()~(~)~^~*)
Try it online! (includes a testsuite and text identifying parts of the program)
This scores surprisingly well for a very low-level esolang. (Church numerals, Church booleans, etc. are very commonly used in Underload for this reason; the language doesn't have numbers and booleans built in, and this is one of the easier ways to simulate them. That said, it's also common to encode booleans as the Church numerals 0 and 1.)
For anyone who's confused: Underload lets you define reusable functions, but doesn't let you name them in the normal way, they just sort of float around on the argument stack (so if you define five functions and then want to call the first one you defined, you need to write a new function that takes five arguments and calls the fifth of them, then call it with insufficiently many arguments so that it looks for spare arguments to use). Calling them destroys them by default but you can modify the call to make it non-destructive (in simple cases, you just need to add a colon to the call, although the complex cases are more common because you need to make sure that the copies on the stack don't get in your way), so Underload's function support has all the requirements we'd need from the question.
Explanation
true
(~!)
( ) Define function:
~ Swap arguments
! Delete new first argument (original second argument)
이것은 매우 간단합니다. 우리는 원하지 않는 인수와 원하는 인수를 제거하여 반환 값으로 사용합니다.
그릇된
(!)
( ) Define function:
! Delete first argument
이것은 훨씬 더 간단합니다.
아니
((~)~*)
( ) Define function:
~* Modify first argument by pre-composing it with:
(~) Swap arguments
이것의 재미 : not
인수를 전혀 부르지 않고 단지 함수 구성을 사용합니다. 이것은 Underload의 일반적인 트릭입니다. 데이터를 전혀 검사하지 않고 데이터를 사전 및 사후 구성하여 데이터의 기능을 변경하기 만하면됩니다. 이 경우 실행하기 전에 인수를 바꾸도록 함수를 수정하여 교회 숫자를 분명히 무시합니다.
과
:((!)~^)*
( ) Define function:
~^ Execute its first argument with:
(!) false
{and implicitly, our second argument}
* Edit the newly defined function by pre-composing it with:
: {the most recently defined function}, without destroying it
문제는 다른 기능과 관련하여 기능을 정의하는 것을 허용합니다. "최근"이 아닌 "정의"가 정의되었으므로 사용하기가 더 쉽기 때문에 "다음"을 정의합니다. (이것은 우리가 전혀 "이름"이 아니기 때문에 점수에서 차감하지는 않지만 정의를 다시 작성하는 것보다 바이트를 절약합니다. 어떤 함수를 참조하기 때문에 한 함수가 다른 함수를 참조하는 유일한 시간입니다. 그러나 가장 최근에 정의 된 바이트는 너무 많은 비용이 듭니다.)
여기서 정의는 and x y = (not x) false y
입니다. 다시 말해, 만약 그렇다면 not x
, 우리는 false
; 그렇지 않으면을 반환 y
합니다.
또는
(:^)
( ) Define function:
: Copy the first argument
^ Execute the copy, with arguments
{implicitly, the original first argument}
{and implicitly, our second argument}
@Nitrodon or x y = x x y
은 일반적으로보다 짧은 의견에서 지적 or x y = x true y
했으며 Underload에서도 올바른 것으로 나타났습니다. 그것의 순진한 구현은 될 (:~^)
것이지만, 우리는 원래의 첫 번째 인수를 실행하든 그것의 사본을 실행하든 상관없이 결과가 동일하다는 것을 지적함으로써 추가 바이트를 골라 낼 수 있습니다.
언더로드는 실제로 일반적인 의미에서 카레를 지원하지 않지만 이와 같은 정의는 마치 커리처럼 보이게합니다! (비소비 된 인수는 그대로 사용되므로 호출하는 함수는 해당 인수를 자체 인수로 해석합니다.)
암시
(~(!)~^(~)~*)
( ) Define function:
~ Swap arguments
~^ Execute the new first (original second) argument, with argument:
(!) false
{and implicitly, our second argument}
(~)~* Run "not" on the result
여기에 사용 된 정의는 implies x y = not (y false x)
입니다. y가 참이면 not false
, 즉으로 단순화됩니다 true
. y가 거짓이면, 이것은로 단순화되어 not x
원하는 진리표를 우리에게줍니다.
이 경우에는 not
코드를 참조하는 대신 코드를 다시 작성 하여 다시 사용 합니다. (~)~*
괄호없이 직접 작성 되었으므로 정의되지 않고 호출됩니다.
xor
(()~(~)~^~*)
( ) Define function:
~ ~^ Execute the first argument, with arguments:
(~) "swap arguments"
() identity function
~* Precompose the second argument with {the result}
이번에는 두 가지 인수 중 하나만 평가하고이를 사용하여 두 번째 인수에 구성 할 항목을 결정합니다. Underload를 사용하면 arity로 빠르고 느슨하게 연주 할 수 있으므로 첫 번째 인수를 사용하여 두 개의 인수가 두 개인 리턴 함수를 선택합니다. 둘 다 반대 순서로 반환하는 인수 스왑과 둘 다 동일한 순서로 반환하는 identity 함수
첫 번째 인수가 참이면, 실행하기 전에 인수를 교체하는 즉, "swap arguments"로 사전 구성되는 두 번째 인수의 편집 된 버전을 생성합니다 not
. 따라서 첫 번째 인수 not
는 두 번째 인수를 반환한다는 의미 입니다. 다른 한편으로, 첫 번째 잘못된 주장은 우리가 정체성 기능, 즉 아무것도하지 않는 것을 구성한다는 것을 의미합니다. 결과는의 구현입니다 xor
.