Napisz program w swoim ulubionym języku w innym języku [zamknięte]


168

Zdecydowany prawdziwy programista może pisać programy Fortran w dowolnym języku.

od prawdziwych programistów nie używaj Pascala

Twoim zadaniem jest napisanie programu w wybranym języku programowania, ale możesz używać tylko innego języka. Oznacza to, że wyrzuć wszystkie konwencje kodowania z jednego języka i zastąp je konwencjami kodowania z innego języka. Im więcej tym lepiej. Spraw, aby Twój program wyglądał tak, jakby został napisany w innym języku.

Na przykład fan Pythona, który nienawidzi Java, może napisać następujący program Python w Javie:

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

Entuzjasta Pascala zmuszony do używania C mógłby napisać:

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

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

Musisz napisać kompletny program. Program nie musi robić nic pożytecznego.

Powodzenia. To konkurs popularności, więc wygrywa kod z największą liczbą głosów!


1
@ m.buettner utwórz plik z rozszerzeniem .litcoffee. To może pomóc.
Ismael Miguel

Trochę długo (a wcześniej napisane, a nie samowystarczalny) na odpowiedź, ale: Postscript skaner w Postscript w C .
luser droog

51
Nie sądzę, że ty (lub większość odpowiedzi) rozumiesz sens cytatu. To nie jest tak, że prawdziwy programista pisze kod, który wygląda leksykalnie jak Fortran, nawet jeśli pisze w Pascalu lub LISP: chodzi o to, że stosuje myślenie w Fortranie nawet podczas pisania w Pascalu lub LISP; np. „ Jak wiedzą wszyscy prawdziwi programiści, jedyną przydatną strukturą danych jest macierz ”. Świetnymi odpowiedziami byłyby kod proceduralny w Prologu, kod funkcjonalny w C, kod obiektowy w Pascal.
Peter Taylor

1
Mam nadzieję, że ktoś zrobi dialekt Lisp w, no cóż, tylko w innym dialekcie Lisp ...
itsjeyd

6
@itsjeyd Greenspun's Dziesiąta zasada programowania : „Każdy wystarczająco skomplikowany program C lub Fortran zawiera doraźną, nieformalnie określoną, opartą na błędach, powolną implementację połowy CommonLisp”.
Joshua Taylor

Odpowiedzi:


142

C w C ++

#include <stdio.h>

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

60
Widzę, co tam zrobiłeś;)
el.pescado

27
Cóż, to tania sztuczka, ponieważ C ++ jest „kompatybilny wstecz” z C.
Agi Hammerthief

5
@AlexM. Myślę, że byłoby bardziej w duchu pytania, gdyby był to dłuższy (proceduralny) przykład, który wyraźnie skorzystałby na użyciu niektórych klas i który używa innych idiomów C, gdzie pewna dobroć STL byłaby znacznie bardziej rozsądna (powiedzmy char*zamiast std::string).
Martin Ender

47
Prawidłowe w C, C ++, Objective-C i Objective-C ++! Cóż za cudownie poliglotyczna odpowiedź.
nneonneo

7
@BenJackson Psh, używają prawdziwych programistów C char *argv[]!
Thomas

122

Montaż x86 w GNU C.

Nie, nie użyłem tylko tego asmsłowa kluczowego, ponieważ ustalone pytanie dotyczy prawdziwych programistów ... powinno działać dobrze na ARM.

(Aby to udowodnić, wcale nie „napisałem” zestawu - jest to wynik wygenerowany przez GCC Clang (503.0.38) dla komentowanego kodu u góry, ślepo przetłumaczony na makra.)

Działa to tylko w trybie 32-bitowym. To w porządku, ponieważ prawdziwi programiści i tak kodują rozmiar słowa.

#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
    ))
}

Spójrz tylko na te wszystkie obsady. Obsada oznacza, że ​​jestem prawdziwszym programistą niż kompilator, prawda?


8
+1, to ... pokręcone. ;) callSzczególnie podoba mi się to, jak sobie poradziłeś .
Ilmari Karonen

2
Łał. To świetna robota.
Jack Aidley

Miałem asembler dla C64, który działał mniej więcej tak. Dodano słowa kluczowe PODSTAWOWE dla wszystkich instrukcji 6510 i pamiętam, że byłeś w nich zawinięty for pass=1:3...next. Wykonanie go w interpretera BASIC go zmontowało.
Ben Jackson,

5
To czysta poezja.
Nicu Stiurca

1
To twardy człowiek, kompilator z pewnością jest zdumiony.
internety są wykonane z kat.

102

Angielski w 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

Wszelkie pomysły na wyeliminowanie ;?


18
Poważnie, chłopaki.
Kyle Strand

2
dlaczego zdefiniować thedwa razy?
Joshua Taylor

16
lepiej bezpieczny niż przykro ;-)
urzeit

20
Teraz zrób z tego haiku.
Nicu Stiurca

1
Can you#define . ;
mbomb007

74

Brainfuck w JavaScript

JavaScript jest trudnym językiem! Użyjmy Brainfuck, bardziej zrozumiałego języka: 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)')
)

Wydaje mi się, że napisałem pieprzonego tłumacza w javascript.

Powyższy przykład po prostu wypisuje Hello World!i ignoruje dane wejściowe (bez ,symbolu).
Ale to też działa z wejściami! Na przykład spróbuj ,+>,+>,+>,+<<<.>.>.>.wpisać golfw oknie dialogowym. Wypisze kolejne znaki w tabeli ASCII:hpmg

EDYCJA : Krótkie wyjaśnienie dla osób, które nie wiedzą o pieprzeniu mózgów.
Wyobraź sobie nieskończoną tablicę liczb całkowitych ainicjowanych wszędzie na zero, wskaźnik na jednym elemencie tej tablicy ii dane wejściowe użytkownika u.
Brainfuck jest naprawdę łatwy do nauczenia, ale trudny do napisania:

  • + przyrosty do bieżącej wartości: a[i]++
  • - zmniejsza to: a[i]--
  • > sprawia, że ​​wskaźnik wskazuje następny element: i++
  • < poprzednie : i--
  • [i ]zdefiniuj pętlę, która pęka, gdy aktualna wartość wynosi zero:while (a[i]) { ... }
  • . wydrukuj bieżący element: String.fromCharCode(a[i])
  • , ustawia bieżący element na podstawie danych wprowadzonych przez użytkownika: u.charCodeAt(...)

22
+1 za humor w stwierdzeniu, że pieprzenie mózgu jest bardziej zrozumiałe niż JavaScript.
Agi Hammerthief

Czy jesteś pewien, że znaki Brainfuck w replaceinstrukcjach nie wpływają na program?
Fraxtil

3
@fra Ten plik nie jest programem do robienia mózgów, jest to program javascript zawierający program do robienia mózgów, który jest konwertowany na javascript w czasie wykonywania.
metro

3
Cóż, --iszybciej niż i--? Wydaje się fałszywy od lat: jsperf.com/decrementgolf .
Michael M.

4
Jest to nie tylko bardzo kreatywne poddanie się konkursowi, ale również bardzo jasno wyjaśnia składnię pieprzenia mózgów. +10, gdybym mógł!
SebastianH

74

Myślę, że genialny Lennart Augustsson już dwukrotnie to wygrał.

Po pierwsze, oto przykład jego implementacji BASIC pod hasłem „weekendowy hack” jako Haskell Monadic DSL z 2009 roku:

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

Działa poprzez przeciążenie typu numeru. Numery linii są tak naprawdę funkcjami, które akceptują argumenty. Reszta linii to argumenty funkcji. Funkcja zwraca reprezentację abstrakcyjnego drzewa składni dla interpretera BASIC, z którym można rozpocząć pracę.

Polecam również sprawdzić udział Augustsson w Międzynarodowym Konkursie Obfuscated C w 2006 roku, w którym udało mu się wcisnąć do 4k:

  • Interpretator kodu bajtowego, napisany w podzbiorze C (który nazywa Obfuscated C).
  • Zamaskowany C -> kod bajtowy kompilator, napisany w kodu bajtowego.

Mogą współdzielić ten sam plik, ponieważ kod bajtowy jest umieszczony w komentarzach C.

Minęło kilka lat, odkąd śledziłem prace Augustssona, więc od tego czasu mogą być inne genialne rzeczy ...


2
To Augustsson, nie Augustssen.
Hans Lundmark

@HansLundmark Thanks. Naprawione.
Pitarou

71

PHP i JavaScript

To jest poliglot:

Możesz uruchomić ten kod w obu językach:

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]));

Sztuczka polega na tym, że JavaScript wykorzystuje sekwencje specjalne w ciągach zaczynających się od 'i ".
Z drugiej strony PHP używa tylko sekwencji specjalnych w ciągach zaczynających się od "i <<<.

Następnie deklarujemy funkcję printf, która jest podobna do, printale wyświetla sformatowany ciąg znaków w PHP.

PHP wymaga, aby vars zaczynał od $, podczas gdy JavaScript po prostu pozwala.


Nikt nie używa Array(…)w JS, i to wyraźnie array(…)w PHP. […]byłoby znacznie lepiej;)!
Blackhole

12
Nie obchodzi mnie, czy ludzie używają Array()JS, czy nie: zależy mi na PRAWDZIWYM poliglocie. Robię jedną z najgorszych zbrodni JS za pomocą tego kodu, ale wszystko, czego chcę, to to, że działa i robi dokładnie to samo w obu przypadkach, ale jednocześnie wygląda jak JS i PHP.
Ismael Miguel

A btw, [...]jest niepoprawny w PHP <5.4.0, co jest złe ....... Jeśli wrzucę to do PHP 4, 5 lub JavaScript, spodziewam się, że zadziała, zamiast wszędzie podawać błędy składniowe.
Ismael Miguel

2
Jeśli chcesz, aby Twój kod wyglądał jak JS, musisz go użyć […], co wydaje się dość standardowe w PHP i dlatego jest w porządku dla twojego celu. A tak przy okazji, PHP <5.4? Czas na aktualizację, koleś…
Blackhole

8
Zgodność jest ważniejsza niż „wygląd”. I Arrayto jest PRAWA nazwa konstruktora obiektu Array. Zasadniczo używanie []jest takie samo jak Array(). Nie widzę w tym nic złego. Ale mam jedno proste pytanie: działa? (btw, ja mam korzystać z PHP 5.3.28 w pracy.)
Ismael Miguel

55

Brainfuck in JS

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

12
Nie widzę tu żadnego pieprzenia. Ani jednego znaku w><,.-
Michael M.

8
@Michael: Kto powiedział, że nie jest to program, który tworzy nieskończoną pętlę?
Konrad Borowski

19
czy to JSF * ck?

8
Jak na Ziemi to robi , że ?
nandhp

4
Oo Ktoś w końcu to zrobił. Spędziłem trochę czasu próbując wymyślić, jak napisać program JS, używając tylko znaków +! [] (), Ale nigdy nie byłem w stanie go rozgryźć. Muszę to przeanalizować, kiedy będę miał czas ...
Matti Virkkunen,

54

Jest to jeden ze zwycięzców IOCCC z 2005 r. , Program w C, który oprócz tego zestawu definicji wygląda jak program Java:

/*
 * 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
Szczegółowość w najlepszym wydaniu.
qwr

39

C ++ w C.

OK, więc jesteś programistą C ++, ale jesteś zmuszony używać C? Nie ma problemu, wystarczy napisać kilka uzupełniających nagłówków brakujących w C. Na przykład, tutaj jest poprawny program Hello World w C:

W dodatkowym pliku nagłówkowym iostreamnapisz:

#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

W pliku stringnapisz

#define string

W pliku helloworld.c(Twój aktualny kod C) napisz

#include <iostream>
#include <string>

using namespace std;

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

Podczas kompilacji helloworld.cz kompilatorem C poinstruuj kompilator, aby szukał również <...>plików nagłówkowych, gdziekolwiek je zapisałeś, iostreami stringna przykład, jeśli kompilujesz za pomocą gcc i umieścisz pliki iostreamoraz stringw bieżącym katalogu, skompiluj z

gcc helloworld.c -o helloworld -I.

Uwaga: W volatilenagłówku iostreamznajduje się kompilacja wolna od ostrzeżeń, nawet na maksymalnym poziomie ostrzeżenia (uważa się, że odczyt ze zmiennej lotnej ma wpływ).


3
To trochę trollowanie kodu, prawda?
Pan Lister

Program robi dokładnie to, co się wydaje, prawda?
celtschk

8
O wiele zabawniejsze i bardziej imponujące w ten sposób niż C w C ++.
Kyle Strand

Jaki kompilator ostrzega, jeśli go nie używasz volatilei jakie ostrzeżenie?
R. Martinho Fernandes

1
@KyleStrand Ale „C in C ++” jest bardziej zgodne z cytatem w pytaniu. Prawdziwi programiści programują w C, nawet jeśli mają kompilator C ++.
Panie Lister

36

CQL - Caffeinated Query Language

(lub „SQL na kofeinie”)

To mogło być nieco zbyt ambitne. Oto próba napisania deklaratywnego kodu SQL (ish) w CoffeeScript . Wymaga to funkcji proxy ECMAScript 6 . Możesz to przetestować w węźle za pomocą --harmony-proxies.

Ustawmy szablon do definiowania serwerów proxy. (Pochodzą z Na podstawie komentarza Benvie na ten temat )

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
)();

Teraz zdefiniuj obiekt proxy oraz niektóre podejrzane zmienne globalne i funkcje:

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

To była całkiem spora konfiguracja! Ale teraz możemy wykonać następujące czynności (wejście / wyjście w stylu konsoli):

> 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 ] ]

To nie jest prawdziwy poliglot, ale nie o to tak naprawdę chodzi. wiem to@ jest to używane w przypadku zmiennych w SQL, ale potrzebuję wszystkich @liter s dla nazw kolumn i tabel, ponieważ nie znalazłem sposobu na proxy obiektu globalnego (i nie zdziwiłbym się, gdyby to naprawdę nie było możliwe - i dla dobry powód).

Zmieniłem także niektóre nawiasy na nawiasy (w szczególności po VALUES iIN ). Niestety, to, czego w ogóle nie mogłem rozgryźć, jest sposobem na dopuszczenie normalnych warunków, takich jak year > 2000, ponieważ od razu zmieniliby się na wartość logiczną.

Mimo to wygląda to bardzo podobnie do SQL i jest zdecydowanie bardziej deklaratywne niż tryb imperatywny / funkcjonalny / obiektowy, więc powinien dobrze się nadawać do tego pytania. Właściwie myślę, że jeśli trochę dopracowałem kod i obsłużyłem kilka innych funkcji, może to być przydatny moduł CoffeeScript.

W każdym razie to było fajne! :)

Dla osób niezbyt zaznajomionych z CoffeeScript zapytania SQL kompilują się do następującego 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)));
});

To całkiem sporo konfiguracji, ale wygląda dobrze. Nie jestem programistą CoffeeScript, ale wygląda świetnie. W @SQL jest używany dla zmiennych sesji.
Ismael Miguel

Zdecydowałem, że słowa kluczowe będą teraz globalne. Teraz są tylko @s dla nazw kolumn i tabel.
Martin Ender

Teraz wygląda bardzo podobnie do SQL! Zrobiłeś miłą robotę z tym!
Ismael Miguel

1
Nie obchodzi mnie kawa, ale to jest niesamowite.
KRyan

2
@tac dzięki, ale nie, właśnie zhakowałem to razem dla tego wyzwania. Zabawny zbieg okoliczności: przerobienie tego w czysty sposób i umieszczenie go w GitHub było na mojej liście potencjalnych / długoterminowych projektów kodowania, dopóki nie usunąłem go dziś rano.
Martin Ender

27

Visual Basic 6 (w 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()

Działa również w VBScript.


1
Sprytny. Nie potrzebujesz nawet większości średników.
js1568

@ js1568 Dziękujemy! Teraz usunąłem średniki, które nie są potrzebne.
Szczoteczka do zębów

20

F # w C ++

Raczej niewyobrażalne i nieprzyjemne nadużycie preprocesora. Pomyślałem, że fajnie byłoby zmienić C ++, aby wyglądał jak zupełnie inny język zamiast używać kilku aliasów, aby wyglądał jak Java lub PHP. Tak naprawdę nie spodziewam się, że przyniesie to mnóstwo pozytywnych opinii, jest to wejście dla zabawy.

#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

Wypróbuj tutaj .

Niestety pisanie czegoś do STDOUT to wszystko, co może zrobić, chociaż jestem pewien, że jeśli ktoś rzuciłby na to wystarczająco dużo czarów, może zrobić to więcej.


2
Aby ostatni wiersz działał w F #, musiałby to być exit 0albo po prostu 0.
Jwosty

20

Python i ... nikt nie zgadnie (edytuj: dc)

Oto poprawny kod Pythona, ale tak naprawdę program jest napisany w zupełnie innym języku:

# 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

Kod działa w obu językach bez błędów.

Ta kombinacja jest bardzo szalona; Z przyjemnością poczekam dzień lub dwa, zanim powiem, który jest inny język; proszę zostawić komentarz do zgadnięcia.

edycja: Język był językiem stosu z dc. Można zobaczyć tu dobrze znane słowa kluczowe jak for, if, or, in, ale tylko litery znaczenia! To, ,co nie ma znaczenia w dc, jest zamieniane na rejestr, ponieważ po raz pierwszy pojawia się po literze s(to samo dla :).


1
O ile kod nie robi tego samego w obu językach, przypuszczam, że język taki jak Befunge mógłby załatwić sprawę.
Thomas Eding

OK, edytuję kod, aby wstawić wybrany język.
Thomas Baruchel

18

C ++ umożliwia pisanie kodu podobnego do seplenienia za pomocą biblioteki InteLib:

(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();

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


4
Witamy! Prosimy użytkowników o oznaczenie swoich postów jako Wiki Wiki, gdy odpowiedź nie jest ich własną pracą. (I podaj odpowiednie informacje, ale już to zrobiłeś, więc dziękuję!)
Jonathan Van Matre

Oryginalny czy nie, masz mój głos :)
itsjeyd

15

C # w spacji

Dobra, najpierw spróbuj jednego z nich, więc zobaczmy, jak idzie.

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!

I w przypadku, gdy formatowanie poszło nie tak z powodu konieczności umieszczenia czterech spacji na początku każdej linii, tutaj znowu jest. dla spacji i # dla tab:

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 i CSS

Nie języki programowania, ale… ten dokument jest prawidłowym HTML i 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>
<!-- */ -->

Działa to, ponieważ komentarze HTML są dozwolone w arkuszach stylów ze względów historycznych. Aha, i każdy ważny dokument HTML jest również prawidłowym programem PHP, więc jest to również PHP . :)



Ponieważ CSS można uznać za zakończony , może to być poprawna odpowiedź.
Adam Davis

2
HTML i CSS nie są językami programowania :)
Jet

9

C w Scali

Warstwa pomostowa emuluje bardziej romantyczną erę, gdy łańcuchy wciąż były tablicami bajtów zakończonymi zerami.

// 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!"oszukać
Erik the Outgolfer

8

sed i APL

Mój szef chce, żebym pisał skrypty sed, ale wolę pisać APL cały dzień. Niemniej jednak jest bardzo zadowolony z mojej pracy, ponieważ takie skrypty działają idealnie z jego wersją sed:

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

Możesz go wypróbować na mojej nowej stronie za pomocą tego bezpośredniego łącza . Jest to skompilowana do javascript wersja GNU APL. Ostateczne wydanie nastąpi później wraz z oficjalnym wydaniem GNU APL, wer. 1.3, ale możesz doskonale używać go do swoich bezpośrednich odnośników, jeśli lubisz GNU APL.


7

C w Haskell

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)));
    };
}

Oczywiście, ponieważ cmainnic nie robi z argclubargv , kod zestawiania argumentów nie ma żadnego efektu, a ponieważ cmainzawsze zwraca 0, gałąź „else” instrukcji „if” jest martwa. Ale stwierdzenie „jeśli” i tak nic nie robi.

Wszystkie nawiasy klamrowe i średniki są niepotrzebne, podobnie jak większość nawiasów i niektóre dosłowa kluczowe. Instrukcja „if” mogła zostać zapisana jako if exitCode == 0 then exitWith ExitSuccess else exitWith (ExitFailure (fromIntegral exitCode)).


7

C ++ in Forth

: #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";
}

Nie jest to najbardziej elastyczne rozwiązanie, ale działa, jeśli jest napisane dokładnie tak, jak pokazano.


7

Haskell w Javie

(„waniliowy” Java 7, nie Java 8) (Tak, wiem, że boks niszczy wydajność; nawet próba użycia funkcji wyższego rzędu staje się szalona: D)

Java ma bardzo sztywną składnię, więc zamiast zmieniać składnię, próbowałem uczynić kod semantycznie bardziej podobnym do stylu Haskell.

Edytuj - dodano aplikację funkcji częściowej.

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());
    }
}

(Tak, wszystko, co robi to szaleństwo, to informatyka 6!)


6

COBOL w AWK

W duchu cytatu. Czysty, nieskażony AWK, ponieważ może być napisany przez programistę COBOL.

Zadanie polega na zliczeniu rekordów w pliku. Ta wczesna wersja rozwojowa liczy się do testowania. Właściwy plik zostanie później zakodowany na stałe po zwolnieniu z testów jednostkowych ...

Gdybym mógł uzyskać podświetlanie składni, aby zrobić fosforyzujący zielony na czarnym, byłoby świetnie ...

Nawet poprawiłem liczby kolumn na tym, to siedem pustych znaków na początku każdej linii (nigdy nie robiłem tego w awk) i łamie instrukcje długiego drukowania w kolumnie 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 (lub cokolwiek innego) w Racket

Elastyczny moduł i system makr Racketa pozwala na implementację obsługi modułów dla zupełnie nowych języków, zarówno specyficznych dla domeny, jak i ogólnego przeznaczenia. Gotowe jest wsparcie zarówno dla Datalog, jak i Algol 60 , więc oba są poprawnymi programami dla rakiet:

#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

Możesz także dodać obsługę innych języków: np. Zobacz opis Danny'ego Yoo, jak zaimplementować obsługę Brainfuck, która zezwala na programy Racket, takie jak:

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

A ponieważ obsługa jest dodawana na poziomie skompilowanego modułu, możliwe jest łączenie modułów napisanych w różnych językach lub osadzanie fragmentu jednego języka wewnątrz modułu napisanego w innym.


5

SML w Javie

Nadal mam jakiś starożytny kod, od kiedy zacząłem uczyć się języka Java i próbowałem używać go w funkcjonalnym stylu. Lekko oczyszczone:

/**
 * 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

Java w Perlu

Może się liczyć jako łamanie zasad, ale mnie to nie obchodzi. Oczywiście ma to wyglądać jak program Java. Drukuje 20 liczb Fibonacciego, na wypadek, gdyby nie było to oczywiste.

Wymaga zainstalowania modułu Inline :: Java .

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 i ... nikt nie zgadnie (edytuj: dc)

To jest mój drugi wpis; oto fragment poprawnego kodu J, który zwraca 1:

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

Czekam jeden lub dwa dni, zanim powiem, który inny język uruchamia ten sam fragment kodu bez błędów. Po prostu zostaw komentarze, aby spróbować zgadnąć.

edycja: Drugi język to język oparty na stosie z bardzo starożytnego kalkulatora uniksowego dc.


3
Działa bez błędów w GolfScript, BF, HQ9 +, ...
Peter Taylor

OK, nie wiedziałem, że tak wiele języków może to zrobić. Edytuję kod, aby wstawić język, który faktycznie wybrałem.
Thomas Baruchel

@ כאלרוכאל działa bez błędów w tych językach, ponieważ te języki nie zawierają błędów lub nie zawierają błędów dotyczących tego kodu. Na przykład. Brainfuck ignoruje wszystkie znaki, których nie ma, .,+-<>[]więc twój program jest równoważny z ...[.]+brainfuck, który jest prawidłowym, ale bezcelowym programem. AFAIK program pieprzenia mózgu może być nieważny tylko przez niedopasowanie [].
immibis

@immibis. To nieprawda. dc to stary kalkulator i zapewniam, że zmiana jednej rzeczy w moich kodach spowodowałaby błąd. Spędziłem dużo czasu na niektórych częściach kodu, aby wymyślić jakiś trudny sposób na uporządkowanie liter we właściwej kolejności. Mój kawałek kodu Postscript / dc jest dość ekstremalny: brak błędu, ale zmiana czegokolwiek spowoduje, że będzie wadliwy. dc nie ma nic wspólnego z „tymi językami”; dc jest około 20 lub 30 lat starszy od „tych języków”; jest zwykle instalowany w dowolnej dystrybucji Linuksa. Przejrzyj trochę, jeśli jeszcze o tym nie słyszałeś.
Thomas Baruchel

1
@ כאלרוכאל, który źle zrozumiałeś - mówiłem o pieprzeniu mózgu, HQ9 +, golfscript itp. - nie dc.
immibis

4

dc z uruchomionym plikiem PostScript

dc może uruchomić następujący fragment kodu bez błędu:

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 w Javie

To pochodzi z prawdziwego prawdziwego projektu. Wykorzystuje trwałe niezmienne struktury danych i wykorzystuje rekurencję, nawet jeśli nie jest to konieczne. W rzeczywistości jest bardziej podobny do Kore (języka, który implementuje projekt) w Javie, ale styl jest w zasadzie taki sam jak ML. Ale filozofią Kore jest to, że autor nie powinien formatować swojego kodu, więc żaden z kodów Java też nie jest formatowany (jest automatycznie formatowany przez zaćmienie).

upuść n elementów z listy :

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

W ML / Haskell, gdzie wzorzec pasowałby do wyciągania głowy i ogona, tutaj mówisz list.cons().xi list.cons().tail.

wstaw element do listy :

  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));
  }

Lista jest zdefiniowana dosłownie, jak miałby być zdefiniowany typ danych algebraicznych. Oto wersja z usuniętym generatorem zaćmienia:

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);
  }
}

Oto struktura danych mapy zaimplementowana w kategoriach 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;
  }
}

Typy zaczynają zajmować tyle samo miejsca co kod. Na przykład, w Put , metoda ma 302 znaków rodzajów i 343 znaków kodu (nie licząc miejsca / znaki nowej linii).


2

BASIC w Ruby

Wdrożono to dawno temu. Źródłem jest na GitHub . Inspirowany podobną rzeczą w Scali

Ustawiać

#!/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__)

Kod podstawowy

#!./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

Haskell w szablonach C ++

Zrobiłem ten FizzBuzz w szablonach C ++ kilka miesięcy temu na skowronku. Jest to w zasadzie implementacja następującego kodu Haskell, wszystko w szablonach C ++. W rzeczywistości nawet arytmetyka liczb całkowitych jest reimplementowana na poziomie typu --- zauważ, że żaden z szablonów nie używa parametrów int!

Kod Haskell:

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..]

oraz wersja metaprogramowania szablonu 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;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.