다른 언어로 좋아하는 언어로 프로그램 작성 [닫기]


168

결정된 Real Programmer는 모든 언어로 Fortran 프로그램을 작성할 수 있습니다.

실제 프로그래머가 파스칼을 사용하지 않음

귀하의 임무는 선택한 프로그래밍 언어로 프로그램을 작성하는 것이지만 다른 언어 만 사용할 수 있습니다. 즉, 한 언어에서 모든 코딩 규칙을 버리고 다른 언어의 코딩 규칙으로 바꿉니다. 더 좋습니다. 프로그램이 다른 언어로 작성된 것처럼 보이게하십시오.

예를 들어, Java를 싫어하는 Python 팬은 다음 Python 프로그램을 Java로 작성할 수 있습니다.

void my_function()                                                             {
    int i = 9                                                                  ;
    while(i>0)                                                                 {
        System.out.println("Hello!")                                           ;
        i = i - 1                                                              ;}}

C를 사용해야하는 파스칼 애호가는 다음과 같이 쓸 수 있습니다.

#define begin {
#define end }
#define then
#define writeln(str) puts(str)

if (i == 10) then
begin
    writeln("I hate C");
end

완전한 프로그램을 작성해야합니다. 이 프로그램은 유용한 것을 할 필요가 없습니다.

행운을 빕니다. 이것은 인기 콘테스트이므로 가장 많은 표를 얻은 코드가 승리합니다!


1
@ m.buettner는 확장자를 가진 파일을 만듭니다 .litcoffee. 도움이 될 수 있습니다.
Ismael Miguel

답변에 대한 약간 길고 (이전에 작성된; 자체 포함되어 있지는 않지만) C : Postscript의 Postscript 스캐너 .
luser droog

51
나는 당신 (또는 대부분의 답변)이 인용의 요지를 이해하지 못한다고 생각합니다. 실제 프로그래머가 Pascal이나 LISP로 작성하더라도 Fortran과 유사한 어휘 적으로 보이는 코드를 작성하는 것은 아닙니다. Pascal 또는 LISP로 작성할 때도 Fortran 사고 방식을 적용합니다. 예를 들어 " 모든 Real Programmer가 알고 있듯이 유용한 데이터 구조는 Array뿐입니다. ". 좋은 답변은 Prolog의 절차 코드, C의 기능 코드, Pascal의 객체 지향 코드입니다.
피터 테일러

1
누군가 다른 Lisp 방언 이외의 다른 언어로도 Lisp 방언을 사용하길 바랍니다 .
itsjeyd

6
@itsjeyd Greenspun의 10 번째 프로그래밍 규칙 : "충분히 복잡한 C 또는 Fortran 프로그램에는 CommonLisp의 절반에 대한 비공식적으로 지정되고 버그가 적고 느린 임시 구현이 포함되어 있습니다."
Joshua Taylor

답변:


142

C ++의 C

#include <stdio.h>

int main(int argc, char** argv)
{
        printf("Hello world!\n");
        return 0;
}

60
나는 당신이 거기
봅니다

27
글쎄, C ++이 C와 '뒤로 호환'
된다는 것을 알면

5
@AlexM. 이것이 더 긴 (절차 적) 예라면 일부 클래스를 사용하면 분명히 이익이되고 일부 STL 장점이 훨씬 합리적 인 다른 C 관용구를 사용하면 (예 : char*대신 std::string) 질문의 정신에 더 가깝다고 생각합니다 .
Martin Ender

47
C, C ++, Objective-C Objective-C ++ 에서 유효합니다 ! 정말 훌륭한 폴리 글 로트 답변입니다.
nneonneo

7
@ BenJackson Psh, 실제 C 프로그래머가 사용합니다 char *argv[]!
Thomas

122

GNU C의 x86 어셈블리

아니요, asm키워드를 사용하지 않았습니다 . 질문은 실제 프로그래머를 위한 것이므로 ARM에서 제대로 실행되어야합니다.

(요점을 증명하기 위해 어셈블리를 전혀 쓰지 않았습니다. GCC Clang (503.0.38)에서 맨 위에 주석이 달린 코드를 맹목적으로 매크로로 번역 한 결과물입니다.)

이것은 32 비트 모드에서만 작동합니다. 실제 프로그래머는 어쨌든 단어 크기로 코딩하기 때문에 괜찮 습니다.

#include <stdio.h>
#include <stdint.h>
/*
int fac(int x) {
    if (x < 1) return 1; else return x * fac(x - 1);
}

int fib(int x) {
    if (x < 2) return x; else return fib(x - 1) + fib(x - 2);
}

int main(void) {
    int a = fib(10), b = fac(10);
    printf("%d %d\n", a, b);
    return 0;
}
*/

typedef union REG {
    intptr_t i; int _i; void * v; union REG * r;
} REG;

#define LPAREN (
#define RPAREN )
#define MACRO(N) ); N##_MACRO LPAREN

#define push MACRO(PUSH)
#define pop  MACRO(POP)
#define mov  MACRO(MOV)
#define sub  MACRO(SUB)
#define add  MACRO(ADD)
#define imul MACRO(IMUL)
#define cmp  MACRO(CMP)
#define jge  MACRO(JGE)
#define jmp  MACRO(JMP)
#define call MACRO(CALL)
#define ret  MACRO(RET) _
#define label MACRO(LABEL)

#define NO_OP(X) 

#define PUSH_MACRO(VAL) *(esp -= 4) = (REG)(VAL)
#define POP_MACRO(DST) (DST) = (typeof(DST))(esp->i); esp += 4
#define MOV_MACRO(VAL, DST) (DST) = (typeof(DST))((REG)VAL).i;
#define SUB_MACRO(VAL, DST) CMP_MACRO(VAL, DST); \
    (DST) = (typeof(DST))(((REG)DST).i - ((REG)VAL).i)
#define ADD_MACRO(VAL, DST) DST = (typeof(DST))(((REG)DST).i + ((REG)VAL).i); \
    ZF = ((REG)DST).i == 0; OF = 0; SF = ((REG)DST).i < 0
#define IMUL_MACRO(VAL, DST) DST = (typeof(DST))(((REG)DST).i * ((REG)VAL).i); \
    ZF = ((REG)DST).i == 0; OF = 0; SF = ((REG)DST).i < 0
#define CMP_MACRO(L, R) CMP_MACRO_(((REG)L).i, ((REG)R).i)
#define CMP_MACRO_(L, R) (OF = 0, ZF = L == R, SF = (R - L) < 0)
#define JGE_MACRO(TGT) if (SF == OF) { goto TGT; } else {}
#define JMP_MACRO(TGT) goto TGT;
#define CALL_MACRO(PROC) CALL_MACRO_(PROC, __COUNTER__)
#define CALL_MACRO_(PROC, CTR) PUSH_MACRO(CTR - STARTIP); \
    goto PROC; case CTR - STARTIP:
#define RET_MACRO(_) eip = esp->i; esp += 4; if (eip) { continue; } else { goto *finalreturn; }
#define LABEL_MACRO(NAME) NAME

#define MY_ASM(X) do { const int STARTIP = __COUNTER__; \
    switch(eip) { case 0: MY_ASM_1 X } } while (1);
#define MY_ASM_1(X) MY_ASM_2(NO_OP LPAREN 0 X RPAREN;)
#define MY_ASM_2(X) X

#define CAT(L, R) _CAT(L, R)
#define _CAT(L, R) L##R

#define callASM(F) callASM_(F, CAT(_TMP_, __COUNTER__))
#define callASM_(F, LABEL) (({ PUSH_MACRO(0); stackbase = esp; finalreturn = &&LABEL; \
    goto F; LABEL:; }), (intptr_t)eax)


const int STACKSIZE = 4096;
REG callstack[STACKSIZE], * stackbase;
REG * eax, * ecx, * edx, * ebx, * esi, * edi, * esp, * ebp;
int SF, ZF, OF, eip; void * finalreturn;

int main(void) {
    eax = ecx = edx = ebx = esi = edi = esp = ebp = &callstack[STACKSIZE - 1];
    eip = 0;
    finalreturn = &&TOP; TOP:

    PUSH_MACRO(10);
    int a = callASM(_fac);
    PUSH_MACRO(10);
    int b = callASM(_fib);

    printf("%d %d\n", a, b);
    return 0;


    MY_ASM((
    label _fac:                                   // @fac
        push ebp
        mov esp, ebp
        sub 24, esp
        mov 8[ebp], eax
        mov eax, (-8)[ebp]
        cmp 1, (-8)[ebp]
        jge LBB0_2
        mov 1, (-4)[ebp]
        jmp LBB0_3
    label LBB0_2:
        mov (-8)[ebp], eax
        mov (-8)[ebp], ecx
        sub 1, ecx
        mov ecx, *esp
        mov eax, (-12)[ebp]         // 4-byte Spill
        call _fac
        mov (-12)[ebp], ecx         // 4-byte Reload
        imul eax, ecx
        mov ecx, (-4)[ebp]
    label LBB0_3:
        mov (-4)[ebp], eax
        add 24, esp
        pop ebp
        ret

    label _fib:                                   // @fib
        push ebp
        mov esp, ebp
        sub 24, esp
        mov 8[ebp], eax
        mov eax, (-8)[ebp]
        cmp 2, (-8)[ebp]
        jge LBB1_2
        mov (-8)[ebp], eax
        mov eax, (-4)[ebp]
        jmp LBB1_3
    label LBB1_2:
        mov (-8)[ebp], eax
        sub 1, eax
        mov eax, *esp
        call _fib
        mov (-8)[ebp], ecx
        sub 2, ecx
        mov ecx, *esp
        mov eax, (-12)[ebp]         // 4-byte Spill
        call _fib
        mov (-12)[ebp], ecx         // 4-byte Reload
        add eax, ecx
        mov ecx, (-4)[ebp]
    label LBB1_3:
        mov (-4)[ebp], eax
        add 24, esp
        pop ebp
        ret
    ))
}

모든 캐스트를보십시오. 캐스트는 내가 컴파일러보다 실제 프로그래머 라는 것을 의미합니다 .


8
+1, 그것은 ... 꼬인 것입니다. ;) 나는 당신 call이 특히 어떻게 처리했는지 정말 좋아합니다 .
Ilmari Karonen

2
와. 그것은 훌륭한 작품입니다.
Jack Aidley

나는 이런 식으로 작동하는 C64 용 어셈블러를 가지고있었습니다. 모든 6510 지침에 대한 BASIC 키워드를 추가했으며 그 내용을 잘 알고 for pass=1:3...next있습니다. BASIC 인터프리터에서 실행하여 조립했습니다.
벤 잭슨

5
이것은 순수한시입니다.
Nicu Stiurca

1
이것은 터프한 사람이며 컴파일러는 놀랍습니다.
인터넷은 catz에서 만들어집니다

102

C 영어

#include <stdio.h>
#define This
#define program     int main() {
#define aims
#define to
#define output      printf(
#define some
#define example
#define text(a)     #a
#define the
#define screen      "\n");
#define it          
#define also
#define will
#define calculate   ;int a = 
#define result
#define of
#define and
#define print       ; printf("%d\n", a);
#define seriously   return 0; }

This program aims to output some example text (Hello) to the screen;
it also will calculate the result of 3 + 4 and print the result; seriously

어떤 아이디어를 제거해야 ;합니까?


18
진심으로, 너희들.
Kyle Strand

2
the두 번 정의 합니까?
Joshua Taylor

16
죄송합니다.보다 안전합니다 ;-)
urzeit

20
이제 하이쿠를 만드십시오.
Nicu Stiurca

1
당신은#define . ;
mbomb007

74

JavaScript의 Brainfuck

자바 스크립트는 어려운 언어입니다! 더 이해하기 쉬운 언어 인 Brainfuck을 사용하자 : o)

eval(

//write your easy code below

"++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."

//end of easy code

.replace(/\]/g,'}')
.replace(/\[/g,'while(a[i]){')
.replace(/\+/g,'a[i]++;')
.replace(/-/g,'a[i]--;')
.replace(/>/g,'i++;')
.replace(/</g,'i--;')
.replace(/\./g,'o+=String.fromCharCode(a[i]);')
.replace(/,/g,'a[i]=u.charCodeAt(j++);')
.replace(/^/,'var a=new Array(1000).join(\'0\').split(\'\'),i=500,o=\'\',u=prompt(\'Enter input if needed\'),j=0;')
.replace(/$/,'alert(o)')
)

나는 자바 스크립트로 brainfuck 해석기를 썼다.

위의 예는 단순히 출력을 Hello World!하고 입력을 무시합니다 ( ,기호 없음 ).
그러나 그것은 입력에서도 작동합니다! 예를 들어, 대화 상자에 ,+>,+>,+>,+<<<.>.>.>.입력하고 입력 golf하십시오. ASCII 테이블에서 다음 문자를 출력합니다.hpmg

편집 : brainfuck를 모르는 사람들을위한 간단한 설명. 어디에서나 0으로 초기화 된
정수 a배열 i, 이 배열의 한 요소에 대한 포인터 및 사용자 입력을 상상해보십시오 u.
Brainfuck은 배우기 쉽지만 쓰기가 어렵습니다.

  • + 현재 값으로 증가 : a[i]++
  • - 그것을 감소시킵니다 : a[i]--
  • > 다음 요소를 가리키는 포인터를 만듭니다. i++
  • < 이전 : i--
  • []현재의 값이 0 일 때 중단 루프를 정의한다 :while (a[i]) { ... }
  • . 현재 요소를 인쇄하십시오. String.fromCharCode(a[i])
  • , 사용자 입력으로 현재 요소를 설정합니다. u.charCodeAt(...)

22
brainfuck이 JavaScript보다 이해하기 쉽다는 유머에 +1.
Agi Hammerthief

replace명령문 내부의 Brainfuck 문자 가 프로그램에 영향을 미치지 않습니까?
Fraxtil

3
@fra이 파일은 brainfuck 프로그램이 아니며 런타임에 javascript로 변환되는 brainfuck 프로그램을 포함하는 javascript 프로그램입니다.
undergroundmonorail

3
음, --i보다 빠르게 i--? jsperf.com/decrementgolf 년 이후 거짓으로 보입니다 .
Michael M.

4
이것은 컨테스트에 매우 창의적인 제출일뿐만 아니라 brainfuck 구문을 매우 명확하게 설명합니다. 내가 할 수 있다면 +10!
SebastianH

74

나는 훌륭한 Lennart Augustsson 이 이미 두 번 이겼다고 생각합니다 .

먼저, 2009 년부터 Haskell Monadic DSL로서 BASIC을 "주말 해킹"으로 구현 한 예가 있습니다.

import BASIC

main = runBASIC' $ do

    10 LET I =: 1
    20 LET S =: 0
    30 LET S =: S + 1/I
    40 LET I =: I + 1
    50 IF I <> 100000000 THEN 30
    60 PRINT "Almost infinity is"
    70 PRINT S
    80 END

숫자 유형을 오버로드하여 작동합니다. 행 번호는 실제로 인수를 허용하는 함수입니다. 나머지 줄은 함수에 대한 인수입니다. 이 함수는 BASIC 인터프리터가 작업하기 위해 추상 구문 트리의 표현을 리턴합니다.

또한 2006 년 국제 난독 화 C 경연 대회에 참가한 Augustsson의 4k에 참여한 것을 확인하는 것이 좋습니다.

  • C의 서브 세트로 작성된 바이트 코드 인터프리터 (Obfuscated C라고 함).
  • 난독 C -> 바이트 코드 바이트 코드로 작성 컴파일러.

byetecode가 C 주석 안에 있으므로 동일한 파일을 공유 할 수 있습니다.

내가 Augustsson의 작업을 따랐던 지 몇 년이 지났으므로 그 이후로 그가 겪은 다른 훌륭한 것들이있을 수 있습니다 ....


2
그것은 Augustssen이 아니라 Augustsson입니다.
Hans Lundmark

@HansLundmark 감사합니다. 고쳤다.
Pitarou

71

PHP와 자바 스크립트

이것은 폴리 글롯입니다.

이 코드는 두 언어로 모두 실행할 수 있습니다.

if("\0"=='\0')
{
    function printf(){
        $b=Array();
        $a=$b['slice']['call'](arguments);
        $a=$a['join']('');
        console.log($a);
        return $a.length;
    };

    function strtoupper($s){return $s['toUpperCase']();}

    function count($a){return $a['length'];}
}

printf('this is cool!');

$c=Array('a','b','c','d');

for($i=0,$l=count($c);$i<$l;++$i)printf("\n",strtoupper($c[$i]));

여기서 트릭은 Javascript가 'and로 시작하는 문자열에서 이스케이프 시퀀스를 사용한다는 것 "입니다.
반면에, PHP는 "and로 시작하는 문자열에서 이스케이프 시퀀스 만 사용합니다 <<<.

그런 다음 함수를 선언합니다 . PHP printf와 비슷 print하지만 형식화 된 문자열을 출력합니다.

PHP vars로 시작 해야$ 하지만 Javascript는 단순히 허용합니다.


Array(…)JS에서는 아무도 사용하지 않으며 array(…)PHP에서도 분명히 사용 됩니다. […]훨씬 나아질 것입니다;)!
Blackhole

12
사람들 Array()이 JS에서 사용하는지 여부는 상관하지 않습니다 . TRUE 폴리 글롯 이 있는지 걱정합니다 . 이 코드에 최악의 JS 범죄 중 하나를 만들고있어 있지만 실행하고 수행하는 것이 내가 원하는 모두는 정확한 모두에서 같은 일을하지만, 동시에 JS와 PHP처럼 보이는.
Ismael Miguel

그리고 btw [...]는 PHP <5.4.0에서 유효하지 않습니다. 나쁩니다 ....... 이것을 PHP 4, 5 또는 Javascript에 넣으면 어디서나 구문 오류를 발생시키는 대신 작동 할 것으로 예상됩니다.
Ismael Miguel

2
코드를 JS처럼 보이게 하려면[…] PHP에서 표준으로 보이는를 사용해야 합니다. 따라서 목표에 적합합니다. 그런데 PHP <5.4? 업데이트 시간, 남자…
Blackhole

8
"모양"보다 호환성이 더 중요합니다. 그리고 Array 객체 생성자 Array올바른 이름입니다. 기본적으로 사용은와 []동일합니다 Array(). 나는 그것으로 나쁜 것을 보지 못합니다. 그러나 한 가지 간단한 질문이 있습니다. (BTW, 나는 직장에서의 PHP 5.3.28을 사용합니다.)
이스마엘 미구엘

55

JS의 Brainfuck

[][(![]+[])[+[[+[]]]]+([][[]]+[])[+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(![]+[])[+[[
!+[]+!+[]]]]+(!![]+[])[+[[+[]]]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[
+!+[]]]]][([][(![]+[])[+[[+[]]]]+([][[]]+[])[+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(
![]+[])[+[[!+[]+!+[]]]]+(!![]+[])[+[[+[]]]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!
![]+[])[+[[+!+[]]]]]+[])[+[[!+[]+!+[]+!+[]]]]+([][(![]+[])[+[[+[]]]]+([][[]]+
[])[+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(![]+[])[+[[!+[]+!+[]]]]+(!![]+[])[+[[+[]]
]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[+!+[]]]]]+[])[+[[!+[]+!+[]+!+[
]+!+[]+!+[]+!+[]]]]+([][[]]+[])[+[[+!+[]]]]+(![]+[])[+[[!+[]+!+[]+!+[]]]]+(!!
[]+[])[+[[+[]]]]+(!![]+[])[+[[+!+[]]]]+([][[]]+[])[+[[+[]]]]+([][(![]+[])[+[[
+[]]]]+([][[]]+[])[+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(![]+[])[+[[!+[]+!+[]]]]+(!
![]+[])[+[[+[]]]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[+!+[]]]]]+[])[+
[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[+[]]]]+([][(![]+[])[+[[+[]]]]+([][[]]+[])[+[
[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(![]+[])[+[[!+[]+!+[]]]]+(!![]+[])[+[[+[]]]]+(!!
[]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[+!+[]]]]]+[])[+[[!+[]+!+[]+!+[]+!+[]
+!+[]+!+[]]]]+(!![]+[])[+[[+!+[]]]]]((![]+[])[+[[+!+[]]]]+(![]+[])[+[[!+[]+!+
[]]]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[+!+[]]]]+(!![]+[])[+[[+[]]]
]+([][(![]+[])[+[[+[]]]]+([][[]]+[])[+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(![]+[])[
+[[!+[]+!+[]]]]+(!![]+[])[+[[+[]]]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[
+[[+!+[]]]]]+[])[+[[+!+[]]]+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+[+!+[]]+([][(![]+[]
)[+[[+[]]]]+([][[]]+[])[+[[!+[]+!+[]+!+[]+!+[]+!+[]]]]+(![]+[])[+[[!+[]+!+[]]
]]+(!![]+[])[+[[+[]]]]+(!![]+[])[+[[!+[]+!+[]+!+[]]]]+(!![]+[])[+[[+!+[]]]]]+
[])[+[[+!+[]]]+[[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]]])()

12
나는 여기에 어떤 멍청이도 보이지 않습니다. 하나의 문자조차도><,.-
Michael M.

8
@ 마이클 : 누가 무한 루프를 만드는 프로그램이 아니라고 말했습니까?
Konrad Borowski

19
이것이 JSF * ck입니까?

8
얼마나 지구에 하는가 것을 ?
nandhp

4
우 누군가가 마침내 이것을했습니다. 문자 +! [] () 만 사용하여 JS 프로그램을 작성하는 방법을 알아 내려고 시간을 보냈지 만 결코 알아낼 수 없었습니다. 시간이있을 때 이것을 분석해야합니다 ...
Matti Virkkunen

54

이것은 2005 IOCCC 수상자 중 하나입니다. 정의를 제외하고는 Java 프로그램처럼 보이는 C 프로그램입니다.

/*
 * Sun's Java is often touted as being "portable", even though my code won't
 * suddenly become uber-portable if it's in Java. Truth is, Java's one of
 * the most ugly, slow, and straitjacketed languages ever. It's popular
 * mainly because people hear the word "portable" and go "ewww".
 *
 * This program, then, is dedicated to bringing about the death of Java. We
 * good coders have been oppressed for too long by the lame language
 * decisions of pointy-haired bosses and academics who should know better. 
 * It's time we stand up against this junk, and bring back the fun in
 * programming! Viva La Revolution!
 */

#define aSet c
#define BufferedReader(x)1
#define byte Y[I][_^1]?do(:):_&1?do(.):do(`):8;++y;}
#define class int N=0,_,O=328,l=192,y=4,Y[80][64]={0},I;struct
#define do(c)a(#c "\b")
#define err c,c
#define getAllStrings(x));q()
#define if(x)b(#x)
#define IOException
#define line c
#define main(a)b(char*x){write(1,"\033[",2),null}main()
#define new
#define null a(x);}a(char*x){write(1,x,strlen(x));try;try;try;try;
#define out c,c
#define println(x)c
#define private int d(int
#define public short c;}c;typedef int BufferedReader;char*F="JF>:>FB;;BII";
#define return {return
#define static f(x){N=(N+x)%6,y--?f(0),f(1),f(4),f(1):++Y[(I=O+N[F]-66)
#define String
#define System c
#define this if(D):1,O=I,I/=16,l<_/32?if(B):l>_/32?if(A):2,l=_,_/=16,byte
#define throws
#define toArray(x)c
#define try for(;--c.c;)
#define void /16][(_=l+N[6+F]-66)/16]?O/=16,l/=32,O<I/16?if(C):O>I/16?this
#define while(k)if(2J),if(7;21H),f(0),f(4),f(4),if(H),/*

import java.io.*;
import java.util.*;

/**
 * A lame Java program.
 * @author  J. Random Worker
 */
class LameJavaApp
{

    /** The infamous Long-Winded Signature From Hell. */
    public static void main(String[] args)
        throws IOException
    {
        /* Don't get me started on this. */
        BufferedReader reader =
            new BufferedReader(new FileReader(args[0]));

        /* What, this long incantation just to print a string? */
        System.err.println("Hello world!");

        /* At least this is sane. */
        String line;
        while ((line = reader.readLine()) != null)
            System.out.println(line.length());
    }

    /**
     * Method with a needlessly long name.
     * @param   aSet        a set (!)
     */
    private String[] getAllStrings(Set<String> aSet)
    {
        /*
         * This dance is needed even in J2SE 5, which has type
         * templates. It was worse before that.
         */
        return aSet.toArray(new String[0]);
    }

}

3
최고로 장황함.
qwr

39

C의 C ++

좋아, 그래서 당신은 C ++ 프로그래머이지만 C를 사용해야합니까? 문제 없습니다. C에서 누락 된 보충 헤더를 작성하면됩니다. 예를 들어 다음은 C의 유효한 Hello World 프로그램입니다.

보충 헤더 파일 iostream에서 다음을 작성하십시오.

#include <stdio.h>

#define using volatile int
#define namespace message
#define std = 0
#define message(x) printf("%s\n",x)
#define cout 0
#define endl 0

파일 string에 쓰기

#define string

파일 helloworld.c(실제 C 코드)에 다음을 작성하십시오.

#include <iostream>
#include <string>

using namespace std;

int main()
{
  string message("Hello world");
  cout << message << endl;
  return 0;
}

그리고 helloworld.cC 컴파일러로 컴파일 할 때 , 컴파일러가 <...>파일을 저장 한 곳마다 헤더 파일을 찾도록 지시 iostream하고 string, 예를 들어 gcc로 컴파일하고 파일 iostreamstring현재 디렉토리에 넣고

gcc helloworld.c -o helloworld -I.

참고 : volatilein 헤더 iostream는 최대 경고 수준에서도 경고없는 컴파일을 가능하게합니다 (휘발성 변수에서 읽은 것이 효과가있는 것으로 간주 됨).


3
이것은 약간의 코드 트롤링입니다.
Mr Lister

글쎄, 프로그램은 정확히 보이는 것처럼 행동하지 않습니까?
celtschk

8
C ++의 C보다 훨씬 재미 있고 인상적입니다.
Kyle Strand

volatile여기서 사용하지 않으면 어떤 종류의 컴파일러가 경고 하고 어떤 종류의 경고가 발생합니까?
R. Martinho Fernandes

1
@KyleStrand 그러나 "C ++의 C"는 질문의 인용문과 더 조화를 이룹니다. C ++ 컴파일러가 있더라도 실제 프로그래머는 C로 프로그램합니다.
Mr Lister

36

CQL-카페인 쿼리 언어

(또는 "카페인에 대한 SQL")

이것은 다소 야심적 일 수 있습니다. 다음은 CoffeeScript 에서 SQL (ish) 선언 코드를 작성하려는 시도 입니다. 이를 위해서는 ECMAScript 6 프록시 기능 이 필요합니다 . 노드에서 테스트 할 수 있습니다.--harmony-proxies .

프록시 정의를위한 템플릿을 설정해 봅시다. ( 이 문제에 대한 Benvie의 의견 에서 발췌 )

forward = (->
  _slice  = Array.prototype.slice
  _bind   = Function.prototype.bind
  _apply  = Function.prototype.apply
  _hasOwn = Object.prototype.hasOwnProperty

  Forwarder = (target) ->
    @target = target
    this

  Forwarder.prototype =
    getOwnPropertyNames: -> Object.getOwnPropertyNames(@target)
    keys: -> Object.keys(@target)
    enumerate: ->
      i = 0
      keys = []
      for value of @target
        keys[i++] = value
      keys
    getPropertyDescriptor: (key) ->
      o = @target;
      while o
        desc = Object.getOwnPropertyDescriptor o, key
        if desc
          desc.configurable = true;
          return desc;

        o = Object.getPrototypeOf o
    getOwnPropertyDescriptor: (key) ->
      desc = Object.getOwnPropertyDescriptor @target, key
      if desc
        desc.configurable = true
      desc
    defineProperty: (key, desc) -> Object.defineProperty @target, key, desc
    get: (receiver, key) -> @target[key]
    set: (receiver, key, value) ->
      @target[key] = value;
      true
    has: (key) -> key of @target
    hasOwn: (key) -> _hasOwn.call @target, key
    delete: (key) ->
      delete @target[key]
      true
    apply: (receiver, args) -> _apply.call @target, receiver, args
    construct: (args) -> new (_bind.apply @target, [null].concat args);

  forward = (target, overrides) ->
    handler = new Forwarder target;
    for k of Object overrides
      handler[k] = overrides[k]

    if typeof target is 'function'
      return Proxy.createFunction handler,
                                  -> handler.apply this, _slice.call arguments,
                                  -> handler.construct _slice.call arguments
    else
      return Proxy.create handler, Object.getPrototypeOf Object target

  forward
)();

이제 프록시 객체와 의심스러운 전역 변수 및 함수를 정의하십시오.

sql = forward {
  tables: {}

  finalize: ->
    if typeof @activeRows isnt 'function'
      @result = []
      for row in @activeRows
        @result.push (val for val, i in row when @activeTable.columns[i] in @activeColumns)
    delete @activeRows
    delete @activeColumns
    delete @activeTable

  run: (q) ->
    q.call(this)
    @finalize()
    result = @result
    delete @result
    if typeof result isnt 'function' then console.log result
    return result
}, {
  get: (o,name) ->
    if name of @target
      return @target[name];
    (args...) -> {
      name
      args
    }
}

int = Number
varchar = (l) -> String

TABLE = (x) -> x
INTO = (x) -> x
CREATE = (tableData) ->
  name = tableData.name
  table =
    columns: []
  column = tableData.args[0]
  table[column.name] = []
  table.columns.push(column.name)
  while column = column.args[1]
    table[column.name] = []
    table.columns.push(column.name)

  sql.tables[name] = table

  sql.result = "Created table '#{name}'"

INSERT = (table) -> sql.activeTable = sql.tables[table().name]
VALUES = (rows...) ->
  for row in rows
    for val, i in row
      column = sql.activeTable.columns[i]
      sql.activeTable[column].push val

  sql.result = "Inserted #{rows.length} rows"

FROM = (table) ->
  sql.activeTable = sql.tables[table().name]
SELECT = (columns...) ->
  sql.activeColumns = []
  for col in columns
    if typeof col is 'function'
      col = col()

    sql.activeColumns.push col.name

  sql.activeRows = []
  for val in sql.activeTable[sql.activeTable.columns[0]]
    sql.activeRows.push []

  for col in sql.activeTable.columns
    for val, i in sql.activeTable[col]
      sql.activeRows[i].push val

IN = (list) -> { op: 'in', list }
WHERE = (column) ->
  i = sql.activeTable.columns.indexOf(column.name)
  if column.args[0].op is 'in'
    list = column.args[0].list
    sql.activeRows = (row for row in sql.activeRows when row[i] in list)
  else
    console.log 'Not supported!'

ASC = 'asc'
DESC = 'desc'
BY = (x) -> x
ORDER = (column) ->
  i = sql.activeTable.columns.indexOf(column.name)
  order = if column.args[0] is sql.ASC then 1 else -1
  sql.activeRows.sort (a,b) ->
    if a[i] < b[i]
      return -order
    else if a[i] > b[i]
      return order
    else
      return 0

글쎄 그것은 꽤 많은 설정이었습니다! 그러나 이제 다음을 수행 할 수 있습니다 (콘솔 스타일의 입력 / 출력).

> sql.run ->
    CREATE TABLE @books(
      @title varchar(255),
      @author varchar(255),
      @year int
    );

Create Table 'books'

> sql.run ->
    INSERT INTO @books
    VALUES ['The C++ Programming Language', 'Bjarne Stroustrup', 1985],
           ['Effective C++', 'Scott Meyers', 1992],
           ['Exceptional C++', 'Herb Sutter', 2000],
           ['Effective STL', 'Scott Meyers', 2001];

Inserted 4 rows

> sql.run ->
    SELECT @title, @year FROM @books
    WHERE @author IN ['Bjarne Stroustrup', 'Scott Meyers']
    ORDER BY @year DESC;

[ [ 'Effective STL', 2001 ],
  [ 'Effective C++', 1992 ],
  [ 'The C++ Programming Language', 1985 ] ]

실제 폴리 글롯은 아니지만 실제로는 중요하지 않습니다. 나는 그것이 @SQL의 변수에 사용 된다는 것을 알고 있지만@ 전역 객체를 프록시하는 방법을 찾지 못했기 때문에 열과 테이블 이름에 대한 s 하다. 좋은 이유).

또한 일부 괄호를 괄호로 변경했습니다 (특히 VALUESIN). 불행히도, 내가 전혀 알 수 없었던 것은 정상적인 조건을 허용하는 방법입니다.year > 2000 입니다. 부울로 즉시 평가되기 때문입니다.

여전히 이것은 SQL과 매우 유사하며 명령형 / 기능 / 객체 지향보다 확실히 선언적이므로 질문에 잘 맞아야합니다. 실제로 코드를 약간 연마하고 몇 가지 추가 기능을 지원하면 유용한 CoffeeScript 모듈이 될 수 있다고 생각합니다.

여하튼, 이것은 재미 있었다! :)

CoffeeScript에 익숙하지 않은 사용자를 위해 SQL 쿼리는 다음 JavaScript로 컴파일됩니다.

sql.run(function() {
  return CREATE(
    TABLE(
      this.books(
        this.title(varchar(255), 
        this.author(varchar(255), 
        this.year(int)))
      )
    )
  );
});

sql.run(function() {
  INSERT(INTO(this.books));
  return VALUES([...], ['Effective C++', 'Scott Meyers', 1992], [...], [...]);
});

sql.run(function() {
  SELECT(this.title, this.year(FROM(this.books)));
  WHERE(this.author(IN(['Bjarne Stroustrup', 'Scott Meyers'])));
  return ORDER(BY(this.year(thisESC)));
});

그것은 꽤 많은 설정이지만 잘 보입니다. 나는 CoffeeScript 프로그래머가 아니지만 멋지게 보입니다. @SQL에서이 세션 변수에 사용됩니다.
Ismael Miguel

나는 지금 키워드를 세계화하기로 결정했습니다. 이제는 @열 및 테이블 이름에 대한 s 만 있습니다.
Martin Ender

이제는 SQL과 매우 비슷합니다! 당신은 이것으로 좋은 일을했습니다!
Ismael Miguel

1
나는 커피를별로 신경 쓰지 않지만 훌륭합니다.
KRyan

2
@ tac 감사합니다,하지만이 도전을 위해 함께 해킹했습니다. 재밌는 우연의 일치 : 이것을 깨끗하게 다시 작성하고 GitHub에 올리는 것은 오늘 아침에 제거 할 때까지 잠재적 / 장기 코딩 프로젝트 목록에있었습니다.
Martin Ender

27

Visual Basic 6 (JavaScript)

'; Main sub-routine \
'; function Main() { ' \
Sub Main() '
    ' Do not throw any errors... \
    On Error Resume Next '; MsgBox = alert

    ' Show a message box... \
    MsgBox(1 / 0) '

    ' Show errors again... \
    On Error GoTo 0 '

    ' Show another message box... '
    MsgBox("Hello")
    ' ' } ' \
End Sub '

Main()

VBScript에서도 작동합니다.


1
영리한. 대부분의 세미콜론도 필요하지 않습니다.
js1568

감사합니다! 필요하지 않은 세미콜론을 제거했습니다.
칫솔

20

C ++의 F #

전 처리기의 상상력이없고 불쾌한 학대. Java 또는 PHP처럼 보이기 위해 몇 가지 별칭을 사용하는 대신 완전히 다른 언어처럼 보이도록 C ++를 변경하는 것이 재미 있다고 생각했습니다. 나는 이것이 엄청나게 많은 투표를 할 것으로 기대하지는 않습니다. 재미있는 항목입니다.

#define let int
#define args ( int __, char* args[] ) { int ___ 
#define println printf(
#define exit "\n" ); return 0; }
#include <stdio.h>

let main args =
    println "F# is better than C++"
    exit

여기에서 시도 하십시오 .

슬프게도 STDOUT에 무언가를 쓰는 것은 그것이 할 수있는 모든 것에 관한 것입니다. 그러나 누군가가 그것에 마법을 충분히 던지면 더 많은 것을 할 수 있다고 확신합니다.


2
마지막 줄이 F #에서 작동하려면 exit 0또는 이어야 0합니다.
Jwosty

20

파이썬과 ... 아무도 추측하지 않을 것입니다 (편집 : dc)

유효한 파이썬 코드가 있지만 실제로는 프로그램이 매우 다른 언어로 작성되었습니다.

# Initialize systems 1 and 2
# frame 1, divergency speed and divergency latency
f1ds, f1dl, z1 = [2,2,0]
# frame 2, divergency speed and divergency latency
f2ds, f2dl, z2 = [4,4,1]

# Set the most relevant value of ax (detected by low-energy collision)
ax = 42.424242

# Initialize list of successive energy states
s = [17.98167, 21.1621, 34.1217218, 57.917182]

# Most common value for nz parameter
# TODO: check if value from the article of A. Einstein is better
nz = 10

if z2>nz or ax in s:
  ax += 6
  f1ds = 8
  f2ds = 16
  z1 = 4
  z2 = 9

f1dl += z1
f2dl += z2

# main loop, iterate over all energy states
# Warning: hit Ctrl-C if nuclear explosion occurs and adjust either z or nz
for k in s:
  z = nz + k
  f1dl = f1ds + f2dl * z - z1 + 3.14
  f2dl = f2ds + f1dl * z - z2 + 10
  if k > 10 or z-2 in s:
    nz += 0xac  # hexadecimal coefficient found in famous article by E. Fermi

코드는 오류없이 두 언어로 실행됩니다.

조합은 매우 미쳤다. 어느 언어가 다른 언어인지 말하기 전에 하루나 이틀을 기다릴 수 있습니다. 추측에 대한 의견을 남겨주세요.

편집 : 언어는 dc의 스택 기반 언어였습니다. 다음과 같은 잘 알려진 키워드가 표시 될 수 있습니다.for , if, or, in,하지만 문자는 중요! ,나타나는 처음 문자 이후이므로 DC에서 아무 의미가없는는 레지스터로된다 s(에 대해 동일 :).


1
코드가 두 언어에서 모두 동일한 작업을 수행하지 않는 한 Befunge와 같은 언어가 트릭을 수행 할 수 있다고 가정합니다.
Thomas Eding

좋아, 실제로 선택한 언어를 넣으려면 코드를 편집하십시오.
Thomas Baruchel

18

C ++에서는 InteLib 라이브러리를 사용하여 lisp와 유사한 코드를 작성할 수 있습니다.

(L|DEFUN, ISOMORPHIC, (L|TREE1, TREE2),
   (L|COND, 
     (L|(L|ATOM, TREE1), (L|ATOM, TREE2)),
     (L|(L|ATOM, TREE2), NIL),
     (L|T, (L|AND,
       (L|ISOMORPHIC, (L|CAR, TREE1), 
                      (L|CAR, TREE2)),
       (L|ISOMORPHIC, (L|CDR, TREE1), 
                      (L|CDR, TREE2))
 )))).Evaluate();

cf. http://www.informatimago.com/articles/life-saver.html


4
어서 오십시오! 답변이 자신의 작품이 아닌 경우 사용자에게 게시물을 Community Wiki로 표시하도록 요청합니다. (그리고 적절한 속성을 제공하지만 이미 그렇게 했으므로 감사합니다!)
Jonathan Van Matre

독창적이든
아니든

15

공백의 C #

좋아, 먼저 이것들 중 하나를 시도해 보자. 어떻게되는지 보자.

using System; //very important  

namespace ConsoleApplication1  //namespace: name whatever you want      
{ 
 //start    
 class  Program  //class name:  also anything    
    {
    //main function 
    static void Main(string[] args) {
        for(int i=0;i<10;i++)   writeOutput(i); 
    } //end main    
    static void writeOutput(int i) { Console.WriteLine(i); }    //display output    


    } //class ends here         

}  //close namespace:   also very important     





//yay!

그리고 각 줄 앞에 4 개의 공백을 넣지 않아도 서식이 까다로워지면 여기에 다시 표시됩니다. 공간과 탭의 경우 :

using.System;.//very.important#

namespace.ConsoleApplication1..//namespace:#name.whatever.you.want##
{.
.//start#
.class#Program..//class.name:#also.anything#.
#{
....//main.function#
#static.void.Main(string[].args).{
....#for(int.i=0;i<10;i++)#writeOutput(i);#
#}.//end.main#
#static.void.writeOutput(int#i).{.Console.WriteLine(i);.}#//display.output#

.
.#}.//class.ends.here.##

}..//close.namespace:#also.very.important#.#
.




//yay!

12

HTML과 CSS

프로그래밍 언어는 아니지만 ...이 문서는 유효한 HTML CSS입니다.

<!-- p{color:red} /* -->
<!Doctype html>
<title>This is HTML and CSS</title>
<p>Hi!</p>
<!-- */ -->
<!-- p{color:red} /* -->
<!Doctype html>
<title>This is HTML and CSS</title>
<p>Hi!</p>
<!-- */ -->

역사적 이유로 HTML 시트는 스타일 시트에서 허용되기 때문에 작동합니다. 아, 그리고 모든 유효한 HTML 문서도 유효한 PHP 프로그램이므로 PHP 이기도 합니다. :)



이후 CSS가 완료 튜링 고려 될 수있다 , 이것은 올바른 해답이 될 수 있습니다.
Adam Davis

2
HTML과 CSS는 프로그래밍 언어가 아닙니다 :)
Jet

9

스칼라의 C

브리징 레이어는 문자열이 여전히 null로 끝나는 바이트 배열 일 때보 다 낭만적 인 시대를 모방합니다.

// Scala is a dynamic language
import scala.language.{ dynamics, postfixOps }

val self = this

val argc = args.length
val argv = args.map(_.getBytes)

type char = Array[Byte]
object char extends Dynamic {
  // This program uses expanded memory
  val buffers = new scala.collection.mutable.LinkedHashMap[String, char]

  // Malloc char buffer
  def applyDynamic(name: String)(length: Int) =
    buffers(name) = new Array(length)

  def **(argv: Array[Array[Byte]]) = argv
}

object & extends Dynamic {
  // dereference char pointer
  def selectDynamic(name: String) = char.buffers(name)
}

def printf(format: String, buffers: char*) =
  println(
    (format /: buffers){ case (msg, buffer) =>
      // Read string until \0 terminator
      val value = new String(buffer.takeWhile(0 !=))
      // Replace next %s token
      msg.replaceFirst("%s", value)
    }
  )

def scanf(format: String, buffers: char*) =
  buffers foreach { buffer =>
    val line = Console.readLine()
    // Write string to char* buffer
    line.getBytes(0, line.length, buffer, 0)
    // Remember to always null terminate your strings!
    buffer(line.length) = 0
  }

val PATH_MAX = 4096

implicit class Argumenter(args: Pair[_, _]) {
  def apply[T](f: => T) = f
}

object int {
  // Passthrough
  def main[T](f: => T) = f
  def argc = self.argc
}

// terminates the string after the first character
// investigate switching to "xor eax, eax" instead of having a hardcoded 0
// might save 3 bytes and valuable CPU time with this trick
val initialize = (_: char)(1) = 0

def exit(value: Int) = sys.exit(value)
// ---HOMEWORK-ASSIGNMENT-START---

int main(int argc, char **argv) {
  if (argc != 0) {
    printf("This program does not take parameters!");
    exit(1);
  }

  // I've copy pasted this code from somewhere
  // Code reuse is essential if we want to be DRY
  char first(PATH_MAX + 1);
  char last(PATH_MAX + 1);

  printf("Enter your first and last name:\n");
  scanf("%s%s", &first, &last);

  // Still learning references, do I need these here?
  // I've performed benchmarks on printf and I think it's faster this way
  printf("Your full name is %s %s", &first, &last);

  initialize(&first);
  printf("Your signature is %s. %s", &first, &last);

  exit(0);
}

"This program does not take parameters!"바보
아웃 골퍼 에릭

8

sed와 APL

상사는 sed 스크립트를 작성하기를 원하지만 하루 종일 APL을 쓰는 것이 좋습니다. 그럼에도 불구하고 그는 그러한 스크립트가 sed 버전과 완벽하게 실행되기 때문에 내 일에 매우 만족합니다.

i ← g ← 42
a ← d ← 10
s/s←2⊤42/s←2⊤43/g
s/s[01]*1/s⊣1/g
g

이 새 링크를 사용 하여 새 웹 사이트 에서 시도해 볼 수 있습니다 . GNU APL의 자바 스크립트 버전으로 컴파일되었습니다. 최종 릴리스는 나중에 GNU APL의 공식 릴리스 v. 1.3과 함께 제공되지만 GNU APL을 즐기면 영구 링크에 완벽하게 사용할 수 있습니다.


7

하스켈의 C

import Foreign.C.String
import Foreign.C.Types
import Foreign.Marshal.Array
import Foreign.Ptr
import System.Environment
import System.Exit

-- The meat of the program

cmain :: (CInt, Ptr (Ptr CChar)) -> IO CInt
cmain(argc, argv) = do {
    putStr("hello, world\n");
    return 0;
}

-- Of course, the above function doesn't do anything unless we write a wrapper
-- around it.  This could have been done more simply, using higher-level library
-- functions, but where's the fun in that?

main :: IO ()
main = do {
    args <- getArgs;
    argPtrs <- sequence [do {
        argPtr <- mallocArray0(length(arg)) :: IO (Ptr CChar);
        pokeArray0(0)(argPtr)(map(castCharToCChar)(arg));
        return argPtr;
    } | arg <- args ];
    argv <- mallocArray(length(argPtrs)) :: IO (Ptr (Ptr CChar));
    pokeArray(argv)(argPtrs);

    exitCode <- cmain(fromIntegral(length(args)),argv);

    if (exitCode == 0) then do {
        exitWith(ExitSuccess);
    } else do {
        exitWith(ExitFailure(fromIntegral(exitCode)));
    };
}

물론 또는로 cmain아무 작업도 수행하지 않기 때문에 인수 마샬링 코드는 아무런 영향을 미치지 않으며 항상 0을 반환하므로 "if"문의 "else"분기는 죽었습니다. 그러나 "if"문은 어쨌든 아무 것도하지 않습니다.argcargvcmain

대부분의 괄호와 do키워드 와 마찬가지로 모든 중괄호와 세미콜론은 필요하지 않습니다. "if"문은 다음과 같이 쓸 수 있습니다 if exitCode == 0 then exitWith ExitSuccess else exitWith (ExitFailure (fromIntegral exitCode)).


7

Forth의 C ++

: #include ; : <iostream> ; : { ; : } ; : int ; : using ;
: namespace ; : std; ; : main() ; : cout ; : << ;
: "Hello,  ; : world!\n"; S" Hello, world!" type ; : return ; : 0; ;

#include <iostream>
using namespace std;

int main() {
    cout << "Hello, world!\n";
}

가장 유연한 솔루션은 아니지만 표시된대로 정확하게 작성하면 작동합니다.


7

자바 하스켈

(Java 8이 아닌 "vanilla"Java 7,) (예, 권투가 성능을 저하 시킨다는 것을 알고 있습니다.

Java는 매우 엄격한 구문을 사용하므로 구문을 변경하는 대신 코드를 의미 적으로 Haskell 스타일과 더 유사하게 만들려고했습니다.

편집-부분 기능 응용 프로그램이 추가되었습니다.

import java.util.Iterator;

interface Function1<A, B> {
    A call(B arg);
}

interface Function2<A, B, C> {
    A call(B arg1, C arg2);
}

class Reduce<A> implements Function2<A, Function2<A, A, A>, Iterable<A>> {

    @Override
    public A call(Function2<A, A, A> arg1, Iterable<A> arg2) {
        final Iterator<A> i = arg2.iterator();
        A r = i.next();
        while (i.hasNext())
            r = arg1.call(r, i.next());
        return r;
    }
}

class Range implements Iterable<Integer> {

    private final int min;
    private final int max;

    public Range(int min, int max) {
        this.min = min;
        this.max = max;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int i = min;

            @Override
            public boolean hasNext() {
                return i <= max;
            }

            @Override
            public Integer next() {
                return i++;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}

public class Main {

    public static <A, B, C> Function1<A, C> applyPartial(final Function2<A, B, C> f, final B arg2) {
        return new Function1<A, C>() {
            @Override
            public A call(C arg) {
                return f.call(arg2, arg);
            }
        };
    }

    public static void main(String[] args) {

        final Function1<Integer, Iterable<Integer>> product = applyPartial(new Reduce<Integer>(), new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer arg1, Integer arg2) {
                return arg1 * arg2;
            }
        });

        final Function1<Integer, Integer> fact = new Function1<Integer, Integer>() {

            @Override
            public Integer call(Integer arg) {
                return product.call(new Range(1, arg));
            }
        };

        final Integer x = fact.call(6);

        System.out.println(x.toString());
    }
}

(예,이 광기가하는 것은 컴퓨팅입니다 6!)


6

AWK의 COBOL

인용의 정신으로. COBOL 프로그래머가 작성했을 수있는 순수한 AWK.

이 작업은 파일의 레코드를 계산하는 것입니다. 이 초기 개발 버전은 테스트를 위해 자체적으로 계산됩니다. 단위 테스트에서 릴리스되면 올바른 파일이 나중에 하드 코딩됩니다.

검정에서 인광-녹색을 수행하도록 구문 강조를 얻을 수 있다면 좋을 것입니다 ...

이 행에서 열 번호가 정확합니다. 각 줄의 시작 부분에 7 개의 공백이 있으며 (이전에는 한 번도하지 않았 음) 열 72의 긴 인쇄 문을 깨뜨립니다.

   BEGIN { 
       PERFORM_000_INITIALISATION() 
       PERFORM_100_OPEN_FILES() 
       PERFORM_200_PROCESS_FILE() 
       PERFORM_300_CLOSE_FILES() 
       PERFORM_400_SHOW_THE_COUNTS() 
       exit 
   } 
   function PERFORM_000_INITIALISATION() { 
       INPUT_FILE_NAME = "COBOL.AWK" 
       RECORD_COUNT = 0 
   } 
   function PERFORM_100_OPEN_FILES() { 
   } 
   function PERFORM_200_PROCESS_FILE() { 
       PERFORM_210_PRIMING_READ() 
       PERFORM_220_PROCESS_INPUT_UNTIL_END() 
   } 
   function PERFORM_300_CLOSE_FILES() { 
   } 
   function PERFORM_400_SHOW_THE_COUNTS() { 
       print "COBOL.AWK: NUMBER OF RECORDS READ IS " RECORD_COUNT        
   } 
   function PERFORM_210_PRIMING_READ() { 
       PERFORM_900_READ_THE_FILE() 
       if ( FILE_STATUS < 0 ) { 
           print "COBOL.AWK ERR0001: INVALID FILE, HALTING, FILE N" \
                 "AME IS: " INPUT_FILE_NAME 
           exit 
           } 
       if ( FILE_STATUS == 0 ) { 
           print "COBOL.AWK ERR0002: NO RECORDS ON INPUT, HALTING," \
                 "FILE NAME IS: " INPUT_FILE_NAME 
           exit 
           } 
   } 
   function PERFORM_220_PROCESS_INPUT_UNTIL_END() {
       while ( FILE_STATUS != 0 ) { 
           INPUT_RECORD = $0 
           RECORD_COUNT = RECORD_COUNT + 1 
           PERFORM_900_READ_THE_FILE() 
           } 
   } 
   function PERFORM_900_READ_THE_FILE() { 
       FILE_STATUS = getline < INPUT_FILE_NAME 
   }        

6

라켓의 Brainfuck (또는 다른 것)

Racket의 유연한 모듈 및 매크로 시스템을 통해 도메인 별 및 범용의 완전히 새로운 언어에 대한 모듈 지원을 구현할 수 있습니다. DatalogAlgol 60 모두 기본적으로 지원 되므로 다음은 모두 유효한 라켓 프로그램입니다.

#lang datalog
edge(a, b). edge(b, c). edge(c, d). edge(d, a).
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
path(X, Y)?

#lang algol60
begin
  integer procedure SIGMA(x, i, n);
    value n;
    integer x, i, n;
  begin
    integer sum;
    sum := 0;
    for i := 1 step 1 until n do
      sum := sum + x;
    SIGMA := sum;
  end;
  integer q;
  printnln(SIGMA(q*2-1, q, 7));
end

다른 언어에 대한 지원을 추가 할 수도 있습니다. 예를 들어 다음과 같은 라켓 프로그램을 허용하는 Brainfuck 지원을 구현하는 방법에 대한 Danny Yoo의 설명 을 참조하십시오 .

#lang planet dyoo/bf
++++++[>++++++++++++<-]>.
>++++++++++[>++++++++++<-]>+.
+++++++..+++.>++++[>+++++++++++<-]>.
<+++[>----<-]>.<<<<<+++[>+++++<-]>.
>>.+++.------.--------.>>+.

또한 지원은 컴파일 된 모듈 수준에서 추가되므로 다른 언어로 작성된 모듈을 연결하거나 다른 언어로 작성된 모듈에 한 언어의 스 니펫을 포함시킬 수 있습니다.


5

Java의 SML

Java를 배우기 시작하고 기능적 스타일로 사용하려고 시도했을 때부터 고대 코드가 여전히 있습니다. 약간 청소 :

/**
 * Genericised ML-style list.
 */
public class FunctionalList<T> 
{
    private final T head;
    private final FunctionalList<T> tail;

    public FunctionalList(T x, FunctionalList<T> xs) {
        this.head = x;
        this.tail = xs;
    }

    public static <T> FunctionalList<T> cons(T x, FunctionalList<T> xs) {
        return new FunctionalList<T>(x, xs);
    }

    public static <T> T hd(FunctionalList<T> l) {
        return l.head;
    }

    public static <T> FunctionalList<T> tl(FunctionalList<T> l) {
        return l.tail;
    }

    public static int length(FunctionalList<?> l) {
        return len(l, 0);
    }

    private static int len(FunctionalList<?> l, int n) {
        return l == null ? n : len(tl(l), n + 1);
    }

    public static <T> FunctionalList<T> rev(FunctionalList<T> l) {
        return rev(l, null);
    }

    private static <T> FunctionalList<T> rev(FunctionalList<T> a, FunctionalList<T> b) {
        return a == null ? b : rev(tl(a), cons(hd(a), b));
    }

    public static <T> FunctionalList<T> append(FunctionalList<T> a, FunctionalList<T> b) {
        return a == null ? b : cons(hd(a), append(tl(a), b));
    }
}

5

Perl의 Java

규칙 위반으로 간주 될 수 있지만 상관하지 않습니다. 분명히, 그것은 Java 프로그램처럼 보이기위한 것입니다. 명확하지 않은 경우 피보나치 숫자 20 개를 인쇄합니다.

필요 인라인 :: 자바 모듈이 설치된다.

use Inline Java => <<'JAVA';
/**
 * @author  Konrad Borowski <x.fix@o2.pl>
 * @version 0.1.0
 */
class Fibonacci
{
    /**
     * Responsible for storing the number before last generated number.
     */
    private long beforeLastNumber = 0;

    /**
     * Responsible for storing the last generated number.
     */
    private long lastNumber = 1;

    /**
     * Receives the next Fibonacci number.
     * 
     * @return long integer that is the next Fibonacci number
      */
    public long next()
    {
        long temponaryLastNumber = lastNumber;
        lastNumber = beforeLastNumber + lastNumber;
        beforeLastNumber = temponaryLastNumber;
        return temponaryLastNumber;
    }

    /**
     * Outputs the Fibonacci number to standard output.
     */
    public void printFibonacci()
    {
        System.out.println(next());
    }

    /**
     * Outputs the Fibonacci number to standard output given number of
     * times.
     * 
     * @param times number of times to print fibonacci number
     */
    public void printFibonacciTimes(int times)
    {
        int i;
        for (i = 0; i < times; i++) {
            printFibonacci();
        }
    }

    /**
     * Constructor for Fibonacci object. Does nothing.
     */
    public Fibonacci()
    {
        // Do nothing.
    }
}
JAVA

###
 # The executable class that shows 20 Fibonacci numbers.
 ##
package OutputFibonacci
{
    ###
     # Shows 20 Fibonacci numbers. This method is public,
     # static, and returns void.
     ##
    sub main()
    {
        # In Perl, -> is object method separator, not a dot. This is stupid.
        new Fibonacci()->printFibonacciTimes(20);
    }
}

# Perl doesn't automatically call main method.
OutputFibonacci::main();

4

J와 ... 아무도 추측하지 않을 것입니다 (편집 : dc)

이것은 나의 두 번째 항목입니다. 다음은 유효한 J 코드입니다. 1을 반환합니다.

10 o. 1 r. 2 i. 4 [ ( 0:`1: @. (2&|)) ] 8 #: *:@+: 42

나는 어느 언어가 오류없이 매우 동일한 코드를 실행하고 있는지 말하기 전에 하루나 이틀을 기다리고 있습니다. 추측하려고 코멘트를 남겨주세요.

편집 : 다른 언어는 고대 유닉스 계산기 dc의 스택 기반 언어입니다.


3
그것은 PeterScript, BF, HQ9 +, ...에서 오류없이 실행됩니다.
Peter Taylor

좋아, 나는 그렇게 많은 언어가 그것을 할 수 있다는 것을 몰랐다. 실제로 선택한 언어를 적용하기 위해 코드를 편집합니다.
Thomas Baruchel

@ ברוכאל 해당 언어에는 오류가 없거나이 코드에 적용 가능한 오류가 없기 때문에 해당 언어로 오류없이 실행됩니다. 예 : Brainfuck은 포함되지 않은 모든 문자를 무시 .,+-<>[]하므로 프로그램은 ...[.]+유효하지만 무의미한 brainfuck 과 동일합니다 . AFAIK brainfuck 프로그램은 일치하지 않는 경우에만 유효하지 않습니다 [].
immibis

@immibis. 이것은 거짓입니다. dc는 오래된 계산기이며 코드에서 한 가지를 변경하면 오류가 발생할 수 있습니다. 나는 문자의 올바른 순서로 까다로운 방법을 알아 내기 위해 코드의 일부에 많은 시간을 보냈다. 내 코드 Postscript / dc는 매우 극단적입니다. 오류는 없지만 아무것도 변경하면 오류가 발생합니다. dc는 "이 언어들"과 아무 관련이 없습니다. dc는 "이 언어들"보다 약 20 세 또는 30 세입니다. 일반적으로 모든 Linux 배포에 설치됩니다. 들어 보지 못했다면 조금 찾아보세요.
Thomas Baruchel

1
@ ברוכאל 당신이 오해했습니다-나는 brainfuck, HQ9 +, golfscript 등에 대해 이야기하고있었습니다-dc는 아닙니다.
immibis

4

포스트 스크립트 파일을 실행하는 dc

dc는 다음 코드를 오류없이 실행할 수 있습니다.

10 10 10 10 10 42 32 10 10
stop % first send a stop
0 0 srand rand
le pop pop 3.14 sin
lt 2 3 lt and pop
le 2 10 le xor
pop pop pop 1 0 0
<< /sox 2 >> [ exch begin sox end ] aload
3.14 floor

3

자바의 ML / (Strict) Haskell

이것은 실제 실제 프로젝트에서 온 것입니다. 영구 불변 데이터 구조를 사용하고 필요하지 않은 경우에도 재귀를 사용합니다. 실제로 Java에서 Kore (프로젝트가 구현하는 언어)와 비슷하지만 스타일은 기본적으로 ML과 동일합니다. 그러나 Kore의 철학은 작성자가 코드를 형식화해서는 안되므로 Java 코드 중 어느 것도 형식화되지 않습니다 (이클립스에 의해 자동 형식화 됨).

목록에서 n 개의 요소를 삭제하십시오 .

  public static <T> List<T> drop(List<T> l, Integer n) {
    return n == 0 ? l : drop(l.cons().tail, n - 1);
  }

ML / Haskell에서 머리와 꼬리를 추출하기 위해 패턴 일치를하는 곳에서 여기 list.cons().x와 라고 말합니다 list.cons().tail.

목록에 요소를 삽입하십시오 .

  public static <T> List<T> insert(List<T> l, Integer i, T x) {
    if (i == 0)
      return cons(x, l);
    return cons(l.cons().x, insert(l.cons().tail, i - 1, x));
  }

리스트는 문자 그대로 대수 데이터 유형 이 정의되는 방식으로 정의됩니다. 다음은 일식 생성 상용구가 제거 된 버전입니다.

public final class List<T> {

  public static final class Nil<T> {
  }

  public static final class Cons<T> {
    public final T x;
    public final List<T> tail;

    public Cons(T x, List<T> tail) {
      if (x == null)
        throw new RuntimeException("null head");
      if (tail == null)
        throw new RuntimeException("null tail");
      this.x = x;
      this.tail = tail;
    }
  }

  private final Nil<T> nil;
  private final Cons<T> cons;

  private List(Nil<T> nil, Cons<T> cons) {
    this.nil = nil;
    this.cons = cons;
  }

  public boolean isEmpty() {
    return nil != null;
  }

  public Nil<T> nil() {
    if (nil == null)
      throw new RuntimeException("not nil");
    return nil;
  }

  public Cons<T> cons() {
    if (cons == null)
      throw new RuntimeException("not cons");
    return cons;
  }

  public static <T> List<T> cons(Cons<T> cons) {
    if (cons == null)
      throw new RuntimeException("constructor received null");
    return new List<T>(null, cons);
  }

  public static <T> List<T> nil(Nil<T> nil) {
    if (nil == null)
      throw new RuntimeException("constructor received null");
    return new List<T>(nil, null);
  }
}

다음trie로 구현 된 맵 데이터 구조입니다 .

public final class Map<K, V> {
  private final Tree<Character, Optional<Pair<K, V>>> tree;
  // keys are sorted in reverse order so entrySet can use cons instead of append
  private final Comparer<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> comparer =
      new PairLeftComparer<Character, Tree<Character, Optional<Pair<K, V>>>>(
          new ReverseComparer<Character>(new CharacterComparer()));

  private Map(Tree<Character, Optional<Pair<K, V>>> tree) {
    this.tree = tree;
  }

  public static <K, V> Map<K, V> empty() {
    return new Map<K, V>(new Tree<Character, Optional<Pair<K, V>>>(
        OptionalUtils.<Pair<K, V>> nothing(),
        ListUtils
            .<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> nil()));
  }

  public Optional<V> get(K k) {
    Tree<Character, Optional<Pair<K, V>>> t = tree;
    for (char c : k.toString().toCharArray()) {
      Tree<Character, Optional<Pair<K, V>>> t2 = getEdge(t, c);
      if (t2 == null)
        return nothing();
      t = t2;
    }
    if (t.v.isNothing())
      return nothing();
    return some(t.v.some().x.y);
  }

  public Map<K, V> put(K k, V v) {
    return new Map<K, V>(put(tree, k.toString(), v, k));
  }

  private Tree<Character, Optional<Pair<K, V>>> put(
      Tree<Character, Optional<Pair<K, V>>> t, String s, V v, K k) {
    if (s.equals(""))
      return new Tree<Character, Optional<Pair<K, V>>>(some(Pair.pair(k, v)),
          t.edges);
    char c = s.charAt(0);
    Tree<Character, Optional<Pair<K, V>>> t2 = getEdge(t, c);
    if (t2 == null)
      return new Tree<Character, Optional<Pair<K, V>>>(
          t.v,
          sort(
              cons(
                  pair(
                      c,
                      put(new Tree<Character, Optional<Pair<K, V>>>(
                          OptionalUtils.<Pair<K, V>> nothing(),
                          ListUtils
                              .<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> nil()),
                          s.substring(1), v, k)), t.edges), comparer));
    return new Tree<Character, Optional<Pair<K, V>>>(t.v, sort(
        replace(pair(c, put(t2, s.substring(1), v, k)), t.edges), comparer));
  }

  private List<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> replace(
      Pair<Character, Tree<Character, Optional<Pair<K, V>>>> edge,
      List<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> edges) {
    if (edges.cons().x.x.equals(edge.x))
      return cons(edge, edges.cons().tail);
    return cons(edges.cons().x, replace(edge, edges.cons().tail));
  }

  // I consider this O(1). There are a constant of 2^16 values of
  // char. Either way it's unusual to have a large amount of
  // edges since only ASCII chars are typically used.
  private Tree<Character, Optional<Pair<K, V>>> getEdge(
      Tree<Character, Optional<Pair<K, V>>> t, char c) {
    for (Pair<Character, Tree<Character, Optional<Pair<K, V>>>> p : iter(t.edges))
      if (p.x.equals(c))
        return p.y;
    return null;
  }

  public Map<K, V> delete(K k) {
    return new Map<K, V>(delete(tree, k.toString()).x);
  }

  private Pair<Tree<Character, Optional<Pair<K, V>>>, Boolean> delete(
      Tree<Character, Optional<Pair<K, V>>> t, String k) {
    if (k.equals(""))
      return pair(
          new Tree<Character, Optional<Pair<K, V>>>(
              OptionalUtils.<Pair<K, V>> nothing(), t.edges), t.edges.isEmpty());
    char c = k.charAt(0);
    Tree<Character, Optional<Pair<K, V>>> t2 = getEdge(t, c);
    if (t2 == null)
      return pair(t, false);
    Pair<Tree<Character, Optional<Pair<K, V>>>, Boolean> p =
        delete(t2, k.substring(1));
    List<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> edges = nil();
    for (Pair<Character, Tree<Character, Optional<Pair<K, V>>>> e : iter(t.edges))
      if (!e.x.equals(c))
        edges = cons(e, edges);
    if (!p.y)
      return pair(
          new Tree<Character, Optional<Pair<K, V>>>(t.v, cons(pair(c, p.x),
              edges)), false);
    boolean oneEdge = t.edges.cons().tail.isEmpty();
    return pair(new Tree<Character, Optional<Pair<K, V>>>(t.v, edges), oneEdge
        && t.v.isNothing());

  }

  public static class Entry<K, V> {
    public Entry(K k, V v) {
      this.k = k;
      this.v = v;
    }

    public final K k;
    public final V v;

  }

  public List<Entry<K, V>> entrySet() {
    return entrySet(ListUtils.<Entry<K, V>> nil(), tree);
  }

  private List<Entry<K, V>> entrySet(List<Entry<K, V>> l,
      Tree<Character, Optional<Pair<K, V>>> t) {
    if (!t.v.isNothing()) {
      Pair<K, V> p = t.v.some().x;
      l = cons(new Entry<K, V>(p.x, p.y), l);
    }
    for (Pair<Character, Tree<Character, Optional<Pair<K, V>>>> e : iter(t.edges))
      l = entrySet(l, e.y);
    return l;
  }
}

유형은 코드만큼 많은 공간을 차지하기 시작합니다. 예를 들어, put 에서 메소드는 302 문자 유형과 343 문자 코드 (공백 / 줄 바꾸기 제외)를 갖습니다.


2

루비의 기본

이 오래 전에 구현되었습니다. 소스는 GitHub의에 있습니다 . 스칼라에서 비슷한 일에서 영감을 얻음

설정

#!/usr/bin/env ruby

if caller.empty? && ARGV.length > 0
  $file = ARGV[0]
else
  $file = caller.last.split(':').first
end

require 'pp'

class String
  def %(other)
    self + other.to_s
  end
end

class RBaysick
  @@variables = {}
  @@code = []
  @@line = 0

  def initialize(contents)
    $DONT_RUN = true # To avoid endless loops.

    contents.gsub!(/( |\()'([^\W]+)/, '\1:\2 ')

    contents.gsub!(/(^| |\()(:[^\W]+)/, '\1GET(\2)')

    contents.gsub!(/ IF (.*) THEN (.*)/, ' IF { \1 }.THEN { GOTO \2 }')
    contents.gsub!(/LET *\(([^ ]+) *:= *(.*)\)/, 'LET(\1) { \2 }')
    contents.gsub!(/(LET|INPUT)(\(| )GET\(/, '\1\2(')
    contents.gsub!(/ \(/, '(')

    contents.gsub!(/^(\d+) (.*)$/, 'line(\1) { \2 }')

#    contents.gsub!(/(\)|\}|[A-Z]) ([A-Z]+)/, '\1.\2')

    contents.gsub!(/ END /, ' __END ')
    contents.gsub!(/^RUN/, '__RUN')

    puts contents if $DEBUG
    eval contents
  end

  def __RUN
    while @@line > -1
      puts "#{@@line}: #{@@code[@@line].inspect}" if $DEBUG
      unless @@code[@@line].nil?
        @@increment = true
        @@code[@@line].call
        next unless @@increment
      end
      @@line += 1
    end
  end

  class If < Struct.new(:value)
    def THEN
      yield if value
    end
  end

  def method_missing(name, *args)
    puts "Missing: #{name.to_s}(#{args.map(&:inspect).join(', ')})" if $DEBUG
  end

  def variables
    @@variables
  end

  def line(line, &block)
    @@code[line] = block
  end

  def add(line, cmd, *args)
    puts "DEBUG2: #{cmd.to_s}(#{args.map(&:inspect).join(', ')})" if $DEBUG
    @@code[line] = send(cmd, *args)
  end

  def IF
    ::RBaysick::If.new(yield)
  end

  def PRINT(str)
    puts "PRINT(#{str.inspect})" if $DEBUG
    puts str
    true
  end

  def LET(name, &block)
    puts "LET(#{name.inspect}, #{block.inspect})" if $DEBUG
    @@variables[name] = block.call
  end

  def GET(name)
    puts "GET(#{name.inspect}) #=> #{@@variables[name].inspect}" if $DEBUG
    @@variables[name]
  end

  def INPUT(name)
    puts "INPUT(#{name.inspect})" if $DEBUG
    LET(name) { $stdin.gets.chomp.to_i }
  end

  def ABS(val)
    puts "ABS(#{val.inspect}) #=> #{val.abs.inspect}" if $DEBUG
    val.abs
  end

  def GOTO(line)
    @@increment = false
    @@line = line
  end

  def __END
    exit
  end
end

RBaysick.new(open($file).read) unless $DONT_RUN || ($0 != __FILE__)

기본 코드

#!./rbaysick.rb

10 PRINT "Welcome to Baysick Lunar Lander v0.0.1"
20 LET ('dist := 100)
30 LET ('v := 1)
40 LET ('fuel := 1000)
50 LET ('mass := 1000)

60 PRINT "You are a in control of a lunar lander."
70 PRINT "You are drifting towards the surface of the moon."
80 PRINT "Each turn you must decide how much fuel to burn."
90 PRINT "To accelerate enter a positive number, to decelerate a negative"

100 PRINT "Distance " % 'dist % "km, " % "Velocity " % 'v % "km/s, " % "Fuel " % 'fuel
110 INPUT 'burn
120 IF ABS('burn) <= 'fuel THEN 150
130 PRINT "You don't have that much fuel"
140 GOTO 100
150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
160 LET ('fuel := 'fuel - ABS('burn))
170 LET ('dist := 'dist - 'v)
180 IF 'dist > 0 THEN 100
190 PRINT "You have hit the surface"
200 IF 'v < 3 THEN 240
210 PRINT "Hit surface too fast (" % 'v % ")km/s"
220 PRINT "You Crashed!"
230 GOTO 250
240 PRINT "Well done"

250 END

RUN

2

C ++ 템플릿의 Haskell

몇 달 전에이 FizzBuzz를 몇 달 전에 C ++ 템플릿으로 만들었습니다. C ++ 템플릿에서 다음 Haskell 코드를 거의 구현 한 것입니다. 실제로 정수 산술조차도 유형 수준에서 다시 구현됩니다. --- 어떤 템플릿도 int 매개 변수를 사용하지 않습니다.

하스켈 코드 :

import Control.Monad

m `divides` n = (n `mod` m == 0)

toFizzBuzz n
    | 15 `divides` n = "FizzBuzz"
    |  5 `divides` n = "Buzz"
    |  3 `divides` n = "Fizz"
    |      otherwise = show n

main = mapM_ putStrLn $ take 100 $ map toFizzBuzz [1..]

그리고 C ++ 템플릿 메타 프로그래밍 버전 :

//  
//  Lazy compile-time fizzbuzz computed by C++ templates,
//  without conditionals or the use of machine arithmetic.
//
//         -- Matt Noonan (mnoonan@grammatech.com)

#include <iostream>

using namespace std;

//
//  The natural numbers: Nat = Zero | Succ Nat
//

template <typename n>
struct Succ
{
  typedef Succ eval;
  static const unsigned int toInt = 1 + n::toInt;
  static void print(ostream & o) { o << toInt; }
};

struct Zero
{
  typedef Zero eval;
  static const unsigned int toInt = 0;
  static void print(ostream & o) { o << toInt; }
};

//
//  Arithmetic operators
//    Plus Zero n = n
//    Plus Succ(n) m = Plus n Succ(m)
//    Times Zero n = Zero
//    Times Succ(n) m = Plus m (Times n m)
//

template <typename a, typename b>
struct Plus
{
  typedef typename Plus<typename a::eval,
                        typename b::eval>::eval eval;
};

template <typename M>
struct Plus <Zero, M>
{ typedef typename M::eval eval; };

template <typename N, typename M>
struct Plus <Succ<N>, M>
{ typedef typename Plus<N, Succ<M> >::eval eval; };

template <typename a, typename b>
struct Times
{
  typedef typename Times<typename a::eval,
                         typename b::eval>::eval eval;
};

template <typename M>
struct Times <Zero, M>
{ typedef Zero::eval eval; };

template <typename N, typename M>
struct Times <Succ<N>, M>
{ typedef typename Plus<M,
                        typename Times<N,M>::eval
                        >::eval eval; };

//
//  Lists
//

struct Nil
{
  typedef Nil eval;
  static void print(ostream & o) { }
};

template <typename x, typename xs>
struct Cons
{
  typedef Cons eval;
  static void print(ostream & o) {
    x::eval::print(o); o << endl; xs::eval::print(o);
  }
};

//
//  Take the first n elements of a list
//

template <typename, typename> struct Take;

template <typename _> struct Take<Zero,_>
{ typedef Nil eval; };

template <typename n, typename x, typename xs>
struct Take<Succ<n>, Cons<x,xs> >
{
  typedef Cons<x, Take<n, xs> > eval;
};

template <typename a, typename b>
struct Take
{
  typedef typename Take<typename a::eval,
                        typename b::eval>::eval eval;
};

//
//  Iterate f x0 makes the infinite list
//  x0, f(x0), f(f(x0)), ...
//

template <template<typename> class f, typename x0> struct Iterate
{
  typedef Cons<x0, Iterate<f, f<x0> > > eval;
};

//
//  Map a function over a list
//

template <template<typename> class a, typename b> struct Map
{ typedef typename Map<a,
                       typename b::eval>::eval eval;
};

template <template<typename> class f>
struct Map<f, Nil>
{ typedef Nil eval; };

template <template<typename> class f, typename x, typename xs>
struct Map<f, Cons<x,xs> >
{
  typedef Cons<f<x>, Map<f,xs> > eval;
};

//
//  Some useful things for making fizzes and buzzes
//

struct Fizz
{ static void print(ostream & o) { o << "Fizz"; } };

struct Buzz
{ static void print(ostream & o) { o << "Buzz"; } };

struct FizzBuzz
{ static void print(ostream & o) { o << "FizzBuzz"; } };

//
//  Some useful numbers
//

typedef Succ<Zero> One;
typedef Succ<One> Two;
typedef Succ<Two> Three;
typedef Plus<Two, Three> Five;
typedef Times<Two, Five> Ten;
typedef Times<Three, Five> Fifteen;
typedef Times<Ten, Ten> OneHundred;

//
//  Booleans
//

struct True {};
struct False {};

//
//  If/then/else
//

template <typename p, typename t, typename f>
struct If
{
  typedef typename If<typename p::eval, t, f>::eval eval;
  static void print(ostream & o) { eval::print(o); }
};

template <typename t, typename _>
struct If<True, t, _>
{
  typedef t eval;
};

template <typename _, typename f>
struct If<False, _, f>
{ typedef f eval; };

//
//  Testing if x divides y
//

template <typename a, typename b, typename c>
struct _Divides
{
  typedef typename _Divides<typename a::eval,
                            typename b::eval,
                            typename c::eval>::eval eval;
};

template <typename _, typename __>
struct _Divides<_, __, Zero> { typedef False eval; };

template <typename a>
struct _Divides<a, Zero, Zero> { typedef True eval; };

template <typename a, typename b>
struct _Divides<a, Zero, b>
{
  typedef typename _Divides<a, a, b>::eval eval;
};

template <typename _, typename n, typename m>
struct _Divides<_, Succ<n>, Succ<m> >
{
  typedef typename _Divides<_, n, m>::eval eval;
};

template <typename a, typename b>
struct Divides
{
  typedef typename _Divides<a, a, b>::eval eval;
};

//
//  "Otherwise" sugar
//

template <typename a>
struct Otherwise
{
  typedef typename a::eval eval;
  static void print(ostream & o) { a::eval::print(o); }
};

//
//  Convert a number to fizzes, buzzes as appropriate
//

template <typename n>
struct toFizzBuzz
{
  typedef typename
    If< Divides<Fifteen, n>, FizzBuzz,
    If< Divides<   Five, n>,     Buzz,
    If< Divides<  Three, n>,     Fizz,
    Otherwise<                   n
    > > > >::eval eval;
};

int main(void)
{
  // Make all of the natural numbers
  typedef Iterate<Succ, One> Naturals;

  // Apply fizzbuzz rules to every natural number
  typedef Map<toFizzBuzz, Naturals> FizzBuzzedNaturals;

  // Print out the first hundred fizzbuzzed numbers
  Take<OneHundred, FizzBuzzedNaturals>::eval::print(cout);

  return 0;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.