모든 표현이 이해되는 프로그래밍 언어


23

권장 사항에 따라 Stack Overflow 에서 이것을 다시 게시하고 있습니다 .

최근에 나는 다음과 같은 문제에 대해 생각하고있다.

표준 "Hello world!"의 코드를 고려하십시오. 프로그램:

main()
{
    printf("Hello World");

}

이제이 코드의 거의 모든 변경은 코드를 완전히 쓸모 없게 만들며, 실제로 거의 모든 변경으로 인해 코드가 컴파일되지 않습니다. 예를 들면 다음과 같습니다.

main(5
{
    printf("Hello World");

}

이제 실제 질문입니다. 가능한 모든 기호 조합, 즉 모든 표현이 의미가있는 프로그래밍 언어가 있습니까? 나는 일종의 해결책에 대해 생각하고 두 가지를 생각해 냈습니다.

  1. 제한된 수의 변수가있는 접미사. 기본적으로 모든 변수는 코드를 작성하기 전에 이미 정의되어 있으므로 변수로 작업해야합니다. 이론적으로 많은 간단한 프로그램 체인을 구성하여 임의의 수의 작업을 수행 할 수 있습니다. 각 프로그램은 다른 프로그램에 결과를 제공합니다. 코드는 접미사 표기법으로 일련의 문자로 작성 될 수 있습니다.

  2. 변수 스택이있는 "Postfix" 변수는 스택에 저장됩니다. 모든 작업은 상단에서 두 개의 변수를 가져와 결과를 제자리에 둡니다. 프로그램이 마지막 작업 또는 변수에 도달하면 종료됩니다.

개인적으로 나는이 두 가지를 모두 싫어합니다. 그것들은 제한적일뿐만 아니라 우아하지도 않습니다. 그것들은 대안과 같은 실제 솔루션이 아니며, 본질적으로 일부 작업을 외부 프로세스에 "오프 쇼어"합니다.

누구 든지이 문제를 해결하는 방법에 대한 다른 아이디어가 있습니까?


48
컴파일러 주어지면 다음과 같이 작동 하는 새 컴파일러 를 작성하십시오 . 주어진 소스 을 전달하십시오 . 경우 그것으로 행복하고 실행을 생산, 그입니다 만, 그 경우 출력을 다음 밖으로 인쇄 실행 불평 컴파일러 유효한 프로그램으로 모든 문자열을 받아들입니다. C ' s C C C C 'CCsCCCYou are a bimbo.C
Andrej Bauer

1
BF [ ]는 Wiki 페이지에 따라 일치하는 명령이 필요합니다 . 내 생각은 CPU opcode를 보는 것이었다. 그러나 그럼에도 불구하고 일부 패턴은 문제를 일으킬 수 있습니다 (예 : opcode가 3 비트이지만 프로그램이 2 비트 인 경우). 0 비트로 채워질 가능성이있는 문제를 제외하고는 어떤 CPU에서도 "모든 문자열은 유효한 프로그램"이라는 주장을 충족시키는 완전한 opcode 세트입니다. 의미가 없지만 여전히 유효합니다.
Ran G.

1
하드웨어가 64k RAM의 Z-80 CPU가되도록하십시오. ASCII 코드 소스 코드를 64k 메모리에 복사하는 컴파일러를 작성하십시오 (필요한 경우 잘 리거나 패딩 없음). 이 컴파일러는 구문 오류를 제공하지 않습니다.
벤 크로 웰

1
@RanG. 비트 스트림을 처리하고 주어진 프로세서에 대해 유효한 비트의 객체 코드로 수정하는 '컴파일러'는 OP 요구 사항을 충족한다고 생각합니다. x86과 같은 복잡한 명령어 세트를 가진 시스템의 경우에도 그리 어렵지 않을 것입니다. 몇 년 전 x86 프로그램으로서의 랜덤 바이트의 유효성에 대한 논문을 읽었으며 x86이 실제로 저자가 예상했던 것보다 훨씬 강력하다는 것을 알았습니다.
otakucode

2
추가 조건이 없으면이 질문은 지루합니다. Andrej의 의견과 David의 답변은 "사소한"답변을 제공합니다. 당신은 당신이 원하는 것을 더 정확하게 정체해야합니다.
Raphael

답변:


31

codewars 뒤에있는 어셈블리 언어 인 Redcode는 코드가 최종적으로 제공되기 전에 종종 엉망이되고 중단해야 할 기회가 많을수록 게임의 재미는 떨어지기 때문에 정지 명령이 거의 없도록 명시 적으로 작성되었습니다.

우리는 프로그램이 실행되기를 원하지 않고 예상 한 방식으로 실행되기를 원하기 때문에 실제로 그러한 언어는 거의 볼 수 없습니다. 오타를 작성하고 프로그램 실행 방식을 변경할 수있는 경우 원래 예상되는 동작과 거의 비슷하거나 프로그래머가 불만을 느끼고 있어야합니다.

공식 언어가 아닌 자연 언어를 사용하여 이러한 것들에 우선 순위가 있지만 공식 언어의 사용과 비교할 때 큰 분야라고 부르지는 않습니다. 그러한 프로그래밍 언어에 관심이 있으시면 자연어 처리 커뮤니티가 내가 볼 곳입니다.

당신이 볼 수있는 또 다른 분야는 유전학입니다. 단순히 유효하지 않은 유전자 서열은 현저히 적습니다. 재생산에는 그다지 효과적이지 않지만 유효하지 않은 것들이 거의 없습니다.


1
유전학은 좋은 예가 아닌 것 같습니다. 유효 또는 무효의 관점에서, 당신은 단지 복제에 대해 이야기하고 있습니까? 물론 모든 문자열은 가능한 유일한 명령어는 언어에 유효한 프로그램입니다 replicate this string. Turing Complete 근처에 없기 때문에 실제로 의미있는 프로그래밍 언어는 아닙니다.
tel

2
@tel : Cort는 복제보다는 mRNA를 통한 단백질 합성에 대해 이야기하고있을 것입니다. 거의 모든 유전자 서열을 전사 한 다음 단백질 합성 기계에 넣을 수 있습니다. 나오는 단백질이 충분히 안정되어 단백질이 만들어 질 때까지 이미 분해되지 않았는지, 그렇다면 어떤 것이 유용한 지 여부 유기체는 또 다른 문제입니다.
Steve Jessop

3
유전자 코드는 자체를 재현하는 코드가 아닙니다. (일반적으로) 단백질 코드입니다. 단백질이 유용한 지 여부는 종종 다른 질문입니다. 물론 더 흥미 롭습니다. 유전자 서열에서 "코드"의 일부 비트는 "몇 줄을 더 아래로 코딩하는 라인을 따르는 지시와 비슷합니다. 때로는 무시해야합니다." 모든 종류의 멋진 "프로그램"셀과 바이러스가 서로 싸우고 있습니다.
Joel

TECO 는 또 다른 실제 예입니다.
cjm

1
@cjm 와우. "모든 것을 추가 한 것이 아니라 모든 것을 꺼내고 나면 API가 완성 된 것입니다." TECO가 아닌 이상 의미를 부여 할 문자가 부족하면 완료됩니다.
Cort Ammon-복원 Monica Monica

16

보편적 인 튜링 머신의 아이디어는 "프로그래밍 언어"만을 사용합니다. 예를 들어 이진법으로 표현 된 튜링 머신을 자연수로 코딩하여 모든 자연수가 튜링 머신, 즉 프로그램을 나타냅니다. 이 언어에서 0과 1의 모든 문자열은 프로그램입니다.

nn

모든 문자열이 프로그램 인 난해한 프로그래밍 언어도 있습니다. 그러나 당신이 그 목록을 요구한다면, 나는 당신의 질문이 여기서 논외라고 생각합니다.


13

모든 표현이 이해되도록 프로그래밍 언어를 확장하는 것은 항상 가능하지만 흥미롭지는 않습니다. 예를 들어, 원래 언어가 거부하는 표현에 "아무것도하지 않음"이라는 의미를 지정할 수 있습니다.

모든 표현이 "실행할 수있는"방식으로 의미가있는 프로그래밍 언어를 디자인하는 것은 특별히 유용하지 않습니다. 좋은 프로그래밍 언어는 원숭이가 키보드로 입력하고 유효한 프로그램을 작성할 수있는 언어가 아니라 프로그래머가 작성하려는 프로그램을 쉽게 작성할 수있는 언어입니다. 유효한 프로그램을 작성하는 것은 프로그래밍의 어려운 부분이 아닙니다. 어려운 부분은 예상 한 것을 수행하는 프로그램을 작성하는 것입니다. 분명히 잘못된 프로그램을 거부하는 것은이 점에서 매우 도움이됩니다.

이 문제를 해결하는 또 다른 방법은 각 입력에 대해 컴파일 시간,로드 시간 또는 런타임 오류를 생성해야하는 경우를 지정하는 것을 비롯하여 가능한 모든 입력의 의미를 완전히 정의하는 것입니다. 즉, " Syntax error at line 42표준 오류 스트림에 인쇄 한 후 프로그램 중단 "은 언어의 정의 된 의미의 일부입니다. 모든 표현은 정의 된 의미를 갖는다는 점에서 "이해됩니다". 이것이 유용한 의미입니까? 어쩌면 – 결국 프로그램이 틀렸다면 거부하는 것이 유용 할 것입니다.


12

조합 논리에 기반한 Turing-complete language 인 Jot를 확인하십시오 . 여기서 0과 1의 모든 시퀀스 (빈 시퀀스 포함)는 유효한 프로그램입니다.


2
이것은 컴퓨터 과학 답변 이 아닙니다 .
Raphael

2
@Abdulrhman 이진 문자열과 자연수 사이의 형용사를 정의하는 것은 간단합니다. 원하는 경우 모든 프로그램을 자연수로 인코딩 할 수 있습니다.
코드 InChaos

7
@Raphael 정교하게 답변 하시거나 답변의 개선을 제안하십시오. 귀하의 비평에 근거를 제공 할 경우 기꺼이 개선하겠습니다.
Petr Pudlák

+1, 자연수를 기반으로 가상의 프로그래밍 언어에 대해 비슷한 대답을하려고했지만 비슷합니다. AFAIK이 기능을 가진 프로그래밍 (실제로 사용되는)은 없지만 숫자 만 사용하여 프로그래밍 할 수는 있지만 모든 조합에 의미가있는 곳 (연산자 및 피연산자 역할)이 핵심입니다
Nikos M.

8

좋은 예가 공백 입니다. 적절한 언어에서는 모든 연산자 조합이 유효합니다. 연산자는 공백, 탭 및 줄 바꿈 (특히 "\ n")입니다. 다른 모든 문자는 주석으로 간주됩니다 .

이 답변과 실제로 귀하의 질문 (및 전체 웹 페이지)은 유효한 공백 프로그램의 예입니다 (특히 흥미로운 것은 없습니다).


나는 내 brainfuck 답변을 게시 한 후 이것에 대해 생각하고 있었지만 (정확하기 때문에 더 낫다) 궁금합니다. 빈 프로그램이 여전히 프로그램입니까? (즉,이 세 문자가 전체 파일 스트림에서 누락 된 경우). -내 차에 차를 만든 모든 것이 빠졌다면 여전히 차일까요?
BrainSlugs83

이것은 컴퓨터 과학 답변 이 아닙니다 . (또한 "모든 공백 문자열"! = "모든 문자열")
Raphael

2
@Raphael : 그러나 가능한 모든 문자열 (공백이없는 문자열 포함)은 유효한 공백 프로그램입니다. 공백이 아닌 문자는 단순히 공백 프로그래밍 언어의 주석입니다.
slebetman

2
@slebetman 괄호 주석이 문자 그대로 해석되었습니다. 나는 짝을 이루지 않은 루프 토큰에 대해 이야기하고있었습니다. 공백에서 비슷한 문제가 발생할 수 있습니다. 선행 통화없이 돌아 오는 것이 작동합니까? (로 인코딩 [LF][Tab][LF])은 빈 스택을 팝하면 어떻게됩니까? 정의되지 않은 레이블로 이동하면 어떻게됩니까? 중복 레이블을 정의하면 어떻게됩니까?
코드 InChaos

7

나는 많은 포스터들이 그 같은 언어가 "무용지물"이라는 아이디어를 말하고 싶다. 아마도 어떤 특정 과제를 해결하려는 의도로 인간이 수동으로 글을 쓰는 것은 쓸모가 없을 것입니다. 그러나 프로그래밍 언어의 대다수 유스 케이스 임에도 불구하고 이것이 유일하게 유스 케이스는 아닙니다. 그러한 언어가 유용한 곳에서 몇 가지 유스 케이스가 떠오를 것이며 그러한 언어의 예를 위해 해당 필드를 살펴볼 수 있습니다.

첫째 유전학에 콜트 암몬의 암시가 장소입니다 : 문제의 프로그램 변환 (대체 )를 위해 5)을 볼 수있다 돌연변이 . 이런 종류의 조작은 진화 계산 분야에서 일반적입니다 . 특히 유전자 알고리즘문자열 에서 이러한 변환을 수행 하는 반면, 유전자 프로그래밍프로그램을 변환 합니다 . 두 경우 모두 가장 작은 검색 공간을 생성하므로 모든 가능성에 의미를 부여하려고합니다.

유전자 알고리즘은 문자열 에 대한 일종의 평가 함수 에 의존합니다 . 프로그래밍 언어 해석기를 평가 함수로 사용하는 경우 가능한 모든 문자열에 의미를 부여하는 프로그래밍 언어가 유용한 시나리오가 있습니다. 유전자 프로그래밍에서, 우리의 평가 기능은 프로그래밍 언어 해석기라고 가정하지만, 우리는 프로그램에 대한 다양한 표현 을 선택할 수 있습니다 . 예를 들어, 많은 시스템이 추상 구문 트리에서 작동합니다. 표현으로 문자열을 선택하면 유전자 알고리즘과 동일한 시나리오를 복구 할 수 있습니다.

모든 문자열이 유효한 프로그램이되기를 원하는 또 다른 상황은 프로그램을 열거 할 때 입니다. 이것은 코드 인 카오스 (CCodeInChaos)가 언급 한 단어와 관련이 있지만 몇 가지 이유로 자연수 (Natural Number)보다는 문자열 (string)에서 작동하는 것을 선호 할 수 있습니다.

  • 언어에 어떤 구조가 있다면, 예를 들어. 하위 문자열에 의미를 할당 할 수 있습니다. 자연수로 변환 할 때 손실 될 수 있습니다. 이 경우 전체 프로그램을 숫자로 나타내지 않고 하위 문자열을 추론하고 로컬로 변환하기 위해 문자열을 사용하는 것이 좋습니다. 이것은 각 비트가 개별적인 의미를 가질 때 산술식이 아닌 int에서 비트 단위 연산을 선호하는 방법과 유사합니다. 이것은 기본적으로 진화 시나리오의 일반화입니다.
  • 필요에 따라 프로그램을 생성 할 수도 있습니다. 예를 들어, 우리는 완전히 결정되지 않은 프로그램의 실행을 시작하고, 명령 포인터가 그들에 도달 할 때 개별 명령들 (예를 들어, 문자들)만을 생성 (예를 들어, 무작위로) 할 수있다. 이는 프로그램이 Turing machine tape 인 알고리즘 정보 이론에서 일반적이며, 무작위로 생성 된 프로그램의 동작을 특성화하는 것이 목표입니다. 예를 들어, 임의의 문자열보다 솔로몬 오프 이전에 임의 테이프를 사용하는 범용 Turing 기계가 해당 문자열을 출력 할 확률로 공식화 할 수 있습니다.

예시적인 언어와 관련하여, 많은 진화 계산 시스템은 푸시 패밀리 와 같은 스택 언어를 기반으로 합니다. 이것들은 임의의 토큰 스트림을 허용하는 경향이 있습니다 (개별 문자로 나타낼 수 있음). 때때로 (BrainSlugs83의 Brainfuck 예제와 같이) 괄호 균형에 제한이 있습니다. 그러나, 우리는이를 관련시킬 수 자가 구분 프로그램 같은 문자열이 점에서, [유효하지 않을 수 있습니다 프로그램 , 그러나 그것은 이다 유효한 프로그램 접두사 . stdin에서 소스 코드를 읽는 컴파일러 / 인터프리터가 다음 과 같은 문자열을 거부 하지 않으면 [계속하기 전에 더 많은 입력을 기다릴 것입니다.

이진 조합 논리 및 이진 람다 미적분학과 같은 언어는 알고리즘 정보 이론에 대한 작업에서 직접 발생했습니다. ...에서 http://tromp.github.io/cl/cl.html

이 미니멀리즘 유니버설 컴퓨터의 디자인은 개별 객체의 무작위성을 연구하는 Kolmogorov Complexity의 구체적인 정의를 생각해 내고자하는 바람에 동기를 부여했습니다.


2

실제 프로그래밍 언어는 의미를 전달합니다 컴퓨터가 아닌 사람에게 합니다. 'net 쇼 주위에 거의 무작위로 섞인 글자가 떠 다니는 재미있는 텍스트가 많기 때문에 사람들은 맹 글링을 눈치 채지 않고도 횡설수설을 읽고 이해할 수 있습니다. 텍스트에서 오타 및 기타 오류를 찾는 것이 얼마나 어려운지 다시 생각해보십시오.

당신이 요구하는 것과 같은 프로그래밍 언어는 사람들이 글로 쓰여진 것이 아니라 읽고 싶은 것을 이해하게 할 것입니다. 가능한 모호성이 많지 않은 제한된 법적 진술이있는 언어로 디버깅하는 것은 이미 어렵습니다. 좋은 언어 는 예를 들어 기호 나 오타가 바뀌어 해석이 줄어 듭니다 . 자연어도 같은 이유로 중복성으로 유명합니다.


0

에서 브레인 퍽 프로그래밍 언어 , 거의 모든 가능한 바이너리 표현 프로그램으로 해석 될 수있다. 즉, 당신은 완전히 좋은 프로그램을 가져다가 많은 쓰레기를 넣을 수 있으며 문제없이 컴파일 가능하고 해석 할 수 있습니다.

( 편집 : 여는 대괄호와 닫는 대괄호가 일치해야하지만 그렇지 않으면 위의 사항이 적용됩니다.)

다음 두 가지 간단한 방법을 통해이를 달성합니다.

  1. 이해하는 모든 명령은 단일 바이트입니다 (BF에서는 예를 들어 모두 단일 ASCII 문자 임).

  2. 이해하지 못하는 모든 문자는 주석으로 삭제됩니다.

프로그래밍 언어는 Turing complete입니다 (즉, 다른 언어로 할 수있는 모든 것을 할 수 있음).

* : 모든 BF 명령이 단일 ASCII 바이트 인 것은 아닙니다. 즉, 대괄호가 일치해야합니다. 따라서 언어가 첫 번째 기준을 충족하지 않습니다. 그러나 두 기준을 모두 충족하는 모든 언어는 OP가 요구하는 것을 충족시킬 것입니다.


2
이것은 질문에 대한 답변이 아니라 컴퓨터 과학의 답변 이 아닙니다 .
Raphael

1
합리적인 방식으로 언어를 처리하도록 언어를 재정의 할 수 있습니다. 예를 들어 프로그램 시작시 충분한 개방 브래킷을 삽입하고 프로그램 끝에서 폐쇄 브래킷을 삽입하여 균형을 잡습니다. 실제로 프로그램을 다시 작성하지 않고 대괄호가 존재하는 것처럼 프로그램을 처리하는 인터프리터를 작성하는 것이 간단합니다. 물론 여는 괄호로 brainfuck 프로그램을 시작하는 것은 쓸모가 없습니다. 일치하는 닫는 괄호까지 모든 것을 무시하기 때문입니다.
코드 InChaos

1
@Raphael OP의 질문은 "가능한 모든 기호 조합, 즉 모든 표현이 의미가있는 프로그래밍 언어가 있는가?"였습니다. 내 대답은 "그렇습니다. 여기에 가까운 예가 있습니다. 여기에 이론 이 있습니다." -OP의 요구 사항을 충족시키는 한 가지 언어 클래스에 대한 정확한 규칙을 제시하는 것 외에 과학에 대한 더 많은 공간이 있는지 확실하지 않습니다 . 여기에서 정확히 당신이 바라는 것에 대한 예를 들거나 자원에 대한 링크를 줄 수 있습니까? -- 고맙습니다.
BrainSlugs83

2
David와 Gilles는 컴퓨터 과학에 대한 답변을 제공합니다. 그들은 원칙을 탐구 하고 단지 "언어 X는 (거의) 그렇게합니다"라고 말하지 않습니다. 답변을 읽으면 후자의 답변도 지루하다는 것을 알게 될 것입니다. 그것은 당신의 잘못이 아니지만 OP의 것입니다-(컴퓨터 과학 질문) 질문은 지루합니다. 복잡한 복잡함이 있습니다.
Raphael

모든 문자열을 받아 들일 수 있도록 BF를 쉽게 "수정"할 수 있습니다 ]. 소스의 끝에 일치하지 않는 모든 문자를 일치시키기에 충분한 문자 가 있고 처음에는 일치 [하지 않는 모든 문자를 일치시키는 것으로 충분 [합니다 ]. 이것의 의미 []그것들 의 의미를 쉽게 바꿀 수 있습니다. (일치가없는 경우 예를 들어, ]다음 [데이터 포인터의 바이트가 0 인 경우 만 실행을 중단합니다. ]다만 비슷한 상황에서 프로그램의 시작 부분으로 이동합니다.) 그 결과 언어가 완료 튜링 될 것입니다 및 모든 문자열을 받아 들일 것입니다.
Nathaniel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.