Écrire un programme dans votre langue préférée dans une autre langue [fermé]


168

Le Real Programmer déterminé peut écrire des programmes en Fortran dans n’importe quelle langue.

de vrais programmeurs n'utilisent pas Pascal

Votre tâche consiste à écrire un programme dans le langage de programmation de votre choix, mais vous n'êtes autorisé à utiliser qu'un autre langage. En d’autres termes, éliminez toutes les conventions de codage d’une langue et remplacez-les par des conventions de codage d’une autre langue. Plus c'est mieux. Faites en sorte que votre programme ait l’impression d’être écrit dans une autre langue.

Par exemple, un fan de Python qui déteste Java pourrait écrire le programme Python suivant en Java:

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

Un passionné de Pascal forcé d’utiliser C pourrait écrire ceci:

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

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

Vous devez écrire le programme complet. Le programme n'a rien à faire d'utile.

Bonne chance. Il s’agit d’un concours de popularité et le code qui obtient le plus de votes gagne!


1
@ m.buettner créer votre fichier avec l'extension .litcoffee. Cela pourrait aider.
Ismael Miguel

Un peu long (et précédemment écrit, et non autonome) pour une réponse, mais: scanner Postscript en Postscript en C .
luser droog

51
Je ne pense pas que vous (ou la majorité des réponses) comprenez le but de la citation. Ce n'est pas qu'un vrai programmeur écrit un code qui ressemble lexicalement à Fortran même s'il écrit en Pascal ou en LISP: c'est qu'il applique une façon de penser fortran même lorsqu'il écrit en Pascal ou en LISP; Par exemple, " Comme tous les programmeurs réels le savent, la seule structure de données utile est le tableau ". Le code de procédure en Prolog, le code fonctionnel en C et le code orienté objet en Pascal seraient très utiles.
Peter Taylor

1
J'espère que quelqu'un va faire un dialecte Lisp, eh bien, tout sauf un autre dialecte Lisp ...
itsjeyd

6
Dixième règle de programmation de @itsjeyd Greenspun : "Tout programme C ou Fortran suffisamment compliqué contient une implémentation lente ad-hoc, spécifiée de manière informelle, corrigée de bogues et lente, de la moitié de CommonLisp."
Joshua Taylor

Réponses:


142

C en C ++

#include <stdio.h>

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

60
Je vois ce que tu as fait là;)
el.pescado

27
Eh bien, c'est un truc bon marché, vu que C ++ est "rétro-compatible" avec C.
Agi Hammerthief

5
@AlexM. Je pense que ce serait davantage dans l’esprit de la question s’il s’agissait d’un exemple plus long (de procédure) qui tirerait clairement avantage de l’utilisation de certaines classes et qui utiliserait d’autres idiomes du C où une qualité de TSL serait beaucoup plus raisonnable (par exemple char*au lieu de std::string).
Martin Ender

47
Valable en C, C ++, Objective-C et Objective-C ++! Quelle réponse merveilleusement polyglotte.
Nneonneo

7
@BenJackson Psh, les vrais programmeurs utilisent char *argv[]!
Thomas

122

Assemblage x86 dans GNU C

Non, je n'ai pas simplement utilisé le asmmot - clé, puisque la question posée était celle-ci, elle s'adressait à de vrais programmeurs ... elle devrait fonctionner correctement sous ARM.

(Juste pour prouver que je n'ai pas "écrit" l'assemblage, c'est la sortie produite par GCC Clang (503.0.38) pour le code commenté en haut, traduit aveuglément en macros.)

Cela ne fonctionne qu'en mode 32 bits. C'est bien, car les vrais programmeurs respectent la taille des mots.

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

Il suffit de regarder tous ces moulages. Un casting signifie que je suis un programmeur plus réaliste que le compilateur, non?


8
+1, c'est ... tordu. ;) J'aime beaucoup votre façon de gérer call, en particulier.
Ilmari Karonen

2
Sensationnel. C'est un excellent travail.
Jack Aidley

J'ai eu un assembleur pour le C64 qui a fonctionné un peu comme ça. Il a ajouté des mots-clés BASIC pour toutes les instructions 6510 et je me souviens que vous l’aviez enveloppée for pass=1:3...next. L'exécuter dans l'interprète BASIC l'a assemblé.
Ben Jackson

5
C'est de la pure poésie.
Nicu Stiurca

1
C'est un homme dur, le compilateur est surpris.
internets sont fabriqués en catz. Le

102

Anglais en 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

Des idées pour éliminer le ;?


18
Sérieusement, les gars.
Kyle Strand

2
pourquoi définir thedeux fois?
Joshua Taylor

16
mieux vaut prévenir que guérir ;-)
urzeit

20
Maintenant, faites-en un haïku.
Nicu Stiurca

1
Pouvez-vous#define . ;
mbomb007

74

Brainfuck en JavaScript

Javascript est une langue difficile! Utilisons Brainfuck, un langage plus compréhensible: 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)')
)

Je suppose que j'ai écrit un interprète de brainfuck en javascript.

L'exemple ci-dessus indique simplement Hello World!et ignore l'entrée (pas de ,symbole).
Mais cela fonctionne aussi avec les entrées! Par exemple, essayez de ,+>,+>,+>,+<<<.>.>.>.taper golfdans la boîte de dialogue. Il sortira les prochains caractères de la table ASCII:hpmg

EDIT : Brève explication pour les personnes qui ne savent pas brainfuck.
Imaginez un tableau infini d'entiers ainitialisé à zéro partout, un pointeur sur un élément de ce tableau iet une entrée utilisateur u.
Brainfuck est vraiment facile à apprendre mais difficile à écrire:

  • + incrémente à la valeur actuelle: a[i]++
  • - le décrémente: a[i]--
  • > fait pointer du doigt le prochain élément: i++
  • < la précédente : i--
  • [et ]définissez une boucle qui se rompt lorsque la valeur actuelle est égale à zéro:while (a[i]) { ... }
  • . imprimer l'élément actuel: String.fromCharCode(a[i])
  • , définit l'élément en cours avec entrée utilisateur: u.charCodeAt(...)

22
+1 pour l'humour en déclarant que brainfuck est plus compréhensible que JavaScript.
Agi Hammerthief

Êtes-vous sûr que les caractères Brainfuck à l'intérieur des replacedéclarations n'affectent pas le programme?
Fraxtil

3
@fra Ce fichier n'est pas un programme brainfuck, c'est un programme javascript qui contient un programme brainfuck qui est converti en javascript au moment de l'exécution.
undergroundmonorail

3
Eh bien, --iplus vite que i--? Cela semble faux depuis des années: jsperf.com/decrementgolf .
Michael M.

4
Ceci est non seulement une soumission très créative au concours, mais explique aussi très clairement la syntaxe brainfuck. +10 si je pouvais!
SebastianH

74

Je pense que le brillant Lennart Augustsson l’ a déjà remporté deux fois.

Premièrement, voici un exemple de son implémentation "week-end" de BASIC en tant que DSL Haskell Monadic, à partir de 2009:

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

Cela fonctionne en surchargeant le type de numéro. Les numéros de ligne sont vraiment des fonctions qui acceptent des arguments. Le reste de la ligne est constitué d'arguments de la fonction. La fonction renvoie une représentation de l'arbre de syntaxe abstraite sur laquelle l'interpréteur BASIC doit travailler.

Je vous recommande également de consulter l'entrée d'Augustsson au concours international 2006 de C Obfuscated Obfuscated, dans lequel il a réussi à se faufiler dans 4k:

  • Un interpréteur de bytecode, écrit dans un sous-ensemble de C (qu'il appelle C obscurci).
  • Un compilateur C -> Bytecode Obfuscated , écrit en Bytecode.

Ils peuvent partager le même fichier car le byetecode est placé dans les commentaires C.

Cela fait quelques années que je n'ai pas suivi le travail d'Augustson, il se peut qu'il y ait d'autres choses brillantes qu'il a proposées depuis ...


2
C'est Augustsson, pas Augustssen.
Hans Lundmark

@HansLundmark Merci. Fixe le.
Pitarou

71

PHP et Javascript

C'est un polyglotte:

Vous pouvez exécuter ce code dans les deux langues:

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

Le truc ici est que Javascript utilise des séquences d'échappement dans les chaînes commençant par 'et ".
D'autre part, PHP utilise uniquement des séquences d'échappement dans les chaînes commençant par "et <<<.

Ensuite, nous déclarons la fonction printf, qui est similaire à printmais génère une chaîne formatée en PHP.

PHP nécessite que vars commence par $, alors que Javascript le permet tout simplement.


Personne n'utilise Array(…)dans JS, et c'est clairement array(…)en PHP. […]serait bien mieux;)!
Blackhole

12
Je me moque de savoir si les gens utilisent Array()JS ou non: je tiens à ce que j’ai un VRAI polyglotte. Je commets l'un des pires crimes JS avec ce code mais tout ce que je veux, c'est qu'il fonctionne exactement de la même manière dans les deux cas, tout en ressemblant à JS et à PHP en même temps.
Ismael Miguel

Et btw, [...]n’est pas valide en PHP <5.4.0, ce qui est mauvais ....... Si je jette ceci en PHP 4, 5 ou en Javascript, j’espère que cela fonctionnera au lieu de donner des erreurs de syntaxe partout.
Ismael Miguel

2
Si vous voulez que votre code ressemble à JS, vous devez utiliser […], ce qui semble plutôt standard en PHP et convient donc à votre objectif. Et au fait, PHP <5.4? Il est temps de mettre à jour, mec…
Blackhole

8
La compatibilité est plus importante que "l'apparence". Et Arrayest le nom DROIT du constructeur de l'objet Array. Fondamentalement, utiliser []est identique à Array(). Je ne vois rien de mal avec ça. Mais j'ai une question simple: ça marche? (d'ailleurs, je dois utiliser PHP 5.3.28 au travail.)
Ismael Miguel

55

Brainfuck dans JS

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

12
Je ne vois aucun brainfuck ici. Pas même un seul personnage dans><,.-
Michael M.

8
@ Michael: Qui a dit que ce n'est pas un programme qui crée une boucle infinie?
Konrad Borowski

19
est-ce que c'est JSF * ck?

8
Comment sur terre fait-il cela ?
Nandhp

4
Oo. Quelqu'un a finalement fait ça. J'ai passé un certain temps à essayer de comprendre comment écrire un programme JS en utilisant uniquement les caractères +! [] (), Mais je n'ai jamais pu le comprendre. J'ai besoin d'analyser cela quand j'ai le temps ...
Matti Virkkunen

54

C’est l’ un des gagnants de l’IOCCC en 2005 , un programme C qui, à l’exception de ce groupe de définitions, ressemble à un programme 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
La verbosité à son meilleur.
qwr

39

C ++ en C

OK, vous êtes donc un programmeur C ++, mais vous êtes obligé d'utiliser C? Aucun problème, il vous suffit d'écrire quelques en-têtes supplémentaires manquants en C. Par exemple, voici un programme Hello World valide en C:

Dans le fichier d'en-tête supplémentaire iostream, écrivez:

#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

Dans le fichier string, écrivez

#define string

Dans le fichier helloworld.c(votre code C actuel), écrivez

#include <iostream>
#include <string>

using namespace std;

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

Et lors de la compilation helloworld.cavec un compilateur C, demandez au compilateur de rechercher également <...>les fichiers d’en-tête où que vous soyez stockés iostreamet string, par exemple, si vous compilez avec gcc et placez les fichiers iostreamet stringdans le répertoire en cours, compilez avec

gcc helloworld.c -o helloworld -I.

Remarque: L' volatileen-tête in iostreamest là pour permettre une compilation sans avertissement, même au niveau d'alerte maximal (une lecture d'une variable volatile est considérée comme ayant un effet).


3
Ceci est un peu de code trolling, n'est-ce pas.
M. Lister

Eh bien, le programme fait exactement ce qu'il semble faire, n'est-ce pas?
celtschk

8
Tellement plus drôle et plus impressionnant que C en C ++.
Kyle Strand

Quel type de compilateur vous avertit si vous n'utilisez pas volatileici, et quel type d'avertissement?
R. Martinho Fernandes Le

1
@KyleStrand Mais celui "C en C ++" est plus en phase avec la citation de la question. Les vrais programmeurs programment en C, même s'ils ont un compilateur C ++.
M. Lister

36

CQL - Langage d'interrogation caféiné

(ou "SQL sur la caféine")

C'était peut-être un peu trop ambitieux. Voici une tentative d'écriture de code déclaratif SQL (ish) dans CoffeeScript . Cela nécessite la fonction de proxy ECMAScript 6 . Vous pouvez le tester dans le noeud avec --harmony-proxies.

Configurons un modèle pour définir les mandataires. (Tiré du commentaire de Benvie sur cette question )

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

Définissez maintenant un objet proxy et certaines variables et fonctions globales suspectes:

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

Eh bien, c'était beaucoup de configuration! Mais maintenant, nous pouvons faire ce qui suit (entrée / sortie dans un style de console):

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

Ce n'est pas un véritable polyglotte, mais ce n'est pas vraiment le problème. Je sais que cela @est utilisé pour les variables en SQL, mais j'ai besoin de tous les @s pour les noms de colonnes et de tables car je n'ai pas trouvé de moyen de proxy pour l'objet global (et je ne serais pas surpris que ce ne soit vraiment pas possible - et pour une bonne raison).

J'ai aussi changé quelques parenthèses entre parenthèses (en particulier après VALUESet IN). Malheureusement, ce que je ne pouvais pas du tout trouver, c’est un moyen de permettre des conditionnels normaux comme year > 2000, car ils s’évalueraient immédiatement en booléens.

Néanmoins, cela ressemble beaucoup à SQL et est nettement plus déclaratif que impératif / fonctionnel / orienté objet, il devrait donc être qualifié pour la question. Je pense en fait que si je perfectionnais un peu le code et que je prenais en charge quelques fonctionnalités supplémentaires, cela pourrait être un module CoffeeScript utile.

Quoi qu'il en soit, c'était amusant! :)

Pour ceux qui ne sont pas trop familiarisés avec CoffeeScript, les requêtes SQL sont compilées avec le code JavaScript suivant:

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

C'est beaucoup de configuration, mais ça a l'air bien. Je ne suis pas un programmeur CoffeeScript, mais il a fière allure. Le @en SQL est utilisé pour les variables de session.
Ismael Miguel

J'ai décidé de rendre les mots-clés globaux maintenant. Maintenant, il n'y a plus que @s pour les noms de colonnes et de tables.
Martin Ender

Maintenant, il ressemble beaucoup à SQL! Vous avez fait un bon travail avec celui-ci!
Ismael Miguel

1
Je me fiche bien du café, mais c'est génial.
Kryan

2
@tac merci, mais non, je viens juste de le pirater pour relever ce défi. Coïncidence amusante: le refaire proprement et le placer sur GitHub figurait sur ma liste de projets de codage potentiels / à long terme jusqu'à ce que je le supprime ce matin.
Martin Ender

27

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

Cela fonctionne aussi en VBScript.


1
Intelligent. Vous n'avez même pas besoin de la plupart des points-virgules.
js1568

@ js1568 Merci! J'ai maintenant supprimé les points-virgules inutiles.
Brosse à dents

20

F # en C ++

Abus plutôt désagréable et méchant du pré-processeur. J'ai pensé qu'il serait amusant de modifier le langage C ++ pour lui donner l'apparence d'un langage complètement différent, au lieu d'utiliser quelques alias pour le faire ressembler à Java ou à PHP. Je ne m'attends pas vraiment à ce que cela obtienne une tonne de votes positifs, c'est une entrée juste pour le plaisir.

#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

Essayez ici .

Malheureusement, écrire quelque chose dans STDOUT est à peu près tout ce qu'il peut faire, même si je suis sûr que si quelqu'un y jette assez de sorcellerie, il pourrait en faire plus.


2
Pour que la dernière ligne fonctionne en fa #, il faut que ce soit exit 0ou simplement 0.
Jwosty

20

Python et ... personne ne devinera (edit: dc)

Voici un code python valide, mais en réalité le programme est écrit dans un langage très différent:

# 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

Le code est exécuté dans les deux langues sans erreur.

La combinaison est très folle; Je serais heureux d'attendre un jour ou deux avant de dire quelle est l'autre langue; s'il vous plaît laissez des commentaires pour deviner.

edit: La langue était la langue de pile de dc. Vous pouvez voir ici des mots - clés bien connus comme for, if, or, in, mais seulement les lettres d' importance! Le ,qui n'a pas de signification en dc est transformé en un registre car il apparaît pour la première fois après la lettre s(idem pour :).


1
À moins que le code ne fasse la même chose dans les deux langues, je suppose qu'un langage comme Befunge pourrait faire l'affaire.
Thomas Eding

OK, je modifie le code afin de mettre la langue que j'ai réellement choisie.
Thomas Baruchel

18

C ++ vous permet d'écrire du code de type lisisp, avec la bibliothèque 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();

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


4
Bienvenue! Nous demandons aux utilisateurs de signaler leurs publications en tant que Wiki de la communauté lorsque la réponse n’est pas leur propre travail. (Et donnez une attribution appropriée, mais vous l'avez déjà fait, alors merci!)
Jonathan Van Matre

Original ou pas, vous avez mon vote :)
itsjeyd

15

C # dans les espaces

D'accord, essayez d'abord l'un de ceux-ci, alors voyons comment ça se passe.

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!

Et au cas où la mise en forme deviendrait délicate de devoir mettre quatre espaces à l'avant de chaque ligne, la voici à nouveau. pour l'espace et # pour l'onglet:

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

Pas de langage de programmation, mais… ce document est valide HTML et 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>
<!-- */ -->

Cela fonctionne car les commentaires HTML sont autorisés dans les feuilles de style pour des raisons historiques. Oh, et chaque document HTML valide est également un programme PHP valide, il s'agit donc également de PHP . :)



Puisque CSS peut être considéré comme étant complet , cela peut être une réponse valable.
Adam Davis

2
HTML et CSS ne sont pas des langages de programmation :)
Jet

9

C en Scala

La couche de pontage émule une époque plus romantique où les chaînes étaient encore des tableaux d'octets terminés par zéro.

// 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!"trompé ya
Erik the Outgolfer

8

sed et APL

Mon patron veut que j'écrive des scripts sed, mais j'aime bien écrire APL toute la journée. Néanmoins, il est très content de mon travail car de tels scripts fonctionnent parfaitement avec sa version de sed:

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

Vous pouvez l'essayer sur mon nouveau site web avec ce lien permanent . C'est une version compilée en javascript de GNU APL. La version finale sera plus tardive avec la version officielle de GNU APL, v. 1.3, mais vous pouvez parfaitement l’utiliser pour vos permaliens si vous appréciez GNU APL.


7

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

Bien sûr, puisque cmainne fait rien avec argcou argv, le code d'argument-marshaling n'a aucun effet et, comme cmainil retourne toujours 0, la branche "else" de l'instruction "if" est morte. Mais la déclaration "si" ne fait rien de toute façon.

Tous les accolades et les points-virgules sont inutiles, de même que la plupart des parenthèses et certains des domots - clés. La déclaration "if" aurait pu être écrite ainsi if exitCode == 0 then exitWith ExitSuccess else exitWith (ExitFailure (fromIntegral exitCode)).


7

C ++ à 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";
}

Ce n’est pas la solution la plus flexible, mais cela fonctionne s’il est écrit exactement comme indiqué.


7

Haskell en Java

("vanilla" Java 7, pas Java 8) (Oui, je sais que la boxe nuit aux performances; et même essayer d'utiliser des fonctions d'ordre supérieur devient fou verbeux: D)

Java a une syntaxe très rigide, donc au lieu de changer de syntaxe, j'ai essayé de rendre le code sémantiquement plus semblable au style Haskell.

Modifier - application de fonction partielle ajoutée.

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

(Oui, tout ce que fait cette folie, c'est l'informatique 6!)


6

COBOL dans AWK

Dans l'esprit de la citation. AWK pur et pur, tel qu’il peut être écrit par un programmeur COBOL.

La tâche consiste à compter les enregistrements d'un fichier. Cette première version de développement se compte elle-même pour les tests. Le fichier correct sera codé en dur ultérieurement lorsqu'il sera publié par Unit Testing ...

Si je pouvais obtenir la syntaxe surlignée pour faire du vert phosphorescent sur du noir, ce serait génial ...

Même si les numéros de colonne sont corrects sur celui-ci, il y a sept espaces au début de chaque ligne (jamais fait cela auparavant dans awk) et briser les instructions en caractères gras de la colonne 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 (ou n'importe quoi d'autre) dans la raquette

Le module flexible et le système de macros de Racket lui permettent de mettre en œuvre la prise en charge de modules pour de tout nouveaux langages, à la fois spécifiques à un domaine et généraux. Il est hors du support de boîte pour les Datalog et Algol 60 , de sorte que les éléments suivants sont les deux programmes de Racket valides:

#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

Vous pouvez également ajouter du support pour d'autres langues: par exemple, voir la description de Danny Yoo expliquant comment implémenter le support pour Brainfuck, qui autorise les programmes Racket tels que:

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

Et comme le support est ajouté au niveau du module compilé, il est possible de lier des modules écrits dans différentes langues ou d’incorporer un extrait d’une langue dans un module écrit dans une autre.


5

SML en Java

J'ai encore du code ancien depuis que j'ai commencé à apprendre Java et à essayer de l'utiliser dans un style fonctionnel. Légèrement nettoyé:

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

Peut compter comme enfreindre la règle, mais je m'en fiche. De toute évidence, il est destiné à ressembler à un programme Java. Il imprime 20 nombres de Fibonacci, au cas où ce ne serait pas évident.

Nécessite l' installation du module 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 et ... personne ne devinera (edit: dc)

Ceci est ma deuxième entrée; voici un morceau de code J valide, qui retourne 1:

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

J'attends un ou deux jours avant de dire quelle est l'autre langue qui exécute le même morceau de code sans erreur. Laissez juste des commentaires pour essayer de deviner.

edit: L’autre langue est la langue empilée de la très ancienne calculatrice Unix en continu.


3
Il tourne sans erreurs dans GolfScript, BF, HQ9 +, ...
Peter Taylor

OK, je ne savais pas que tant de langues pouvaient le faire. Je modifie le code afin de mettre la langue que j'ai réellement choisie.
Thomas Baruchel

@ רוכאל il fonctionne sans erreur dans ces langues car ces langues ne comportent pas d'erreurs ou n'ont pas d'erreurs applicables à ce code. Par exemple. Brainfuck ignore tous les caractères qui ne sont pas .,+-<>[]dedans, votre programme est donc équivalent à ...[.]+brainfuck, programme valide mais inutile. D'après mes connaissances, un programme de brainfuck ne peut être invalide que s'il est mal assorti [].
Immibis

@immibis. C'est faux. dc est une vieille calculatrice et je peux assurer que le fait de changer une chose dans mes codes provoquerait une erreur. J'ai passé beaucoup de temps sur certaines parties du code pour trouver un moyen délicat de mettre les lettres dans le bon ordre. Mon morceau de code Postscript / dc est assez extrême: aucune erreur, mais changer quoi que ce soit le rendra défectueux. dc n'a rien à voir avec "ces langues"; dc a environ 20 ou 30 ans de plus que "ces langues"; il est généralement installé sur n'importe quelle distribution Linux. S'il vous plaît, naviguez un peu si vous n'en avez pas entendu parler.
Thomas Baruchel

1
@ ברוכאל vous avez mal compris - je parlais de brainfuck, HQ9 +, golfscript, etc. - pas dc.
Immibis

4

dc courir un fichier PostScript

dc peut exécuter le code suivant sans erreur:

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 en Java

Cela provient d'un projet réel réel. Il utilise des structures de données immuables persistantes et utilise la récursivité même lorsque cela n'est pas nécessaire. En réalité, cela ressemble plus à Kore (langage implémenté par le projet) en Java, mais le style est fondamentalement identique à ML. Mais la philosophie de Kore est que l'auteur ne devrait pas formater son code, de sorte qu'aucun code Java n'est formaté non plus (il est automatiquement mis en forme par eclipse).

déposer n éléments d'une liste :

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

Dans ML / Haskell, où vous voulez que les motifs correspondent pour extraire la tête et la queue, vous dites ici list.cons().xet list.cons().tail.

insérer un élément dans une liste :

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

List est défini littéralement comment le type de données algébrique serait défini. Voici une version avec le passe-partout généré par eclipse supprimé:

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

Voici une structure de données cartographiques implémentée sous forme de 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;
  }
}

Les types commencent à prendre autant de place que le code. Par exemple, en mettre , la méthode a 302 caractères de types et 343 caractères de code (sans compter l' espace / nouvelle ligne).


2

BASIC en rubis

Mis en œuvre depuis longtemps. La source est sur GitHub . Inspiré par une chose semblable à Scala

Installer

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

Code de base

#!./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 dans les modèles C ++

J'ai créé ce modèle FizzBuzz en C ++ il y a quelques mois sur une alouette. C'est à peu près une implémentation du code Haskell suivant, tous dans des modèles C ++. En fait, même l'arithmétique entière est réimplémentée au niveau du type - remarquez qu'aucun des modèles n'utilise des paramètres int!

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

et la version de métaprogrammation du modèle 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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.