Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
Zeile 385: | Zeile 385: | ||
</pre> | </pre> | ||
== Die Enterprise-Loesung == | |||
Das Schlimmste aus beiden Welten. | |||
<pre> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <stdint.h> | |||
#include <string.h> | |||
#include <jni.h> | |||
const char *flos[] = { "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" }; | |||
const int n_flos = sizeof(flos)/sizeof(char*); | |||
unsigned char class[] = { | |||
0xca, 0xfe, 0xba, 0xbe, | |||
0x00, 0x00, | |||
0x00, 0x33, | |||
0, 0, | |||
0x01, 0x00, 16, 'j', 'a', 'v', 'a', '/', 'l', 'a', 'n', 'g', '/', 'O', 'b', 'j', 'e', 'c', 't', | |||
0x01, 0x00, 4, 'F', 'l', 'o', 's', | |||
0x01, 0x00, 18, 'L', 'j', 'a', 'v', 'a', '/', 'l', 'a', 'n', 'g', '/', 'S', 't', 'r', 'i', 'n', 'g', ';', | |||
0x01, 0x00, 6, '<', 'i', 'n', 'i', 't', '>', | |||
0x01, 0x00, 3, '(', ')', 'V', | |||
0x07, 0, 1, | |||
0x07, 0, 2, | |||
0x0C, 0, 4, 0, 5, | |||
0x0A, 0, 6, 0, 8, | |||
0x01, 0x00, 4, 'C', 'o', 'd', 'e', | |||
}; | |||
int cp_i = 11; | |||
FILE *cout; | |||
void fputc16(uint16_t in, FILE *out) { | |||
fputc(in >> 8, out); fputc(in & 0xFF, out); | |||
} | |||
uint16_t add_utf8(const char *string) { | |||
size_t len = strlen(string); | |||
fputc(0x01, cout); | |||
fputc16(len, cout); | |||
fputs(string, cout); | |||
return cp_i++; | |||
} | |||
uint16_t add_string(const char *string) { | |||
uint16_t utf8 = add_utf8(string); | |||
fputc(0x08, cout); | |||
fputc16(utf8, cout); | |||
return cp_i++; | |||
} | |||
uint16_t add_name_and_type(const char *name, uint16_t type) { | |||
uint16_t namei = add_utf8(name); | |||
fputc(0x0C, cout); | |||
fputc16(namei, cout); | |||
fputc16(type, cout); | |||
return cp_i++; | |||
} | |||
uint16_t add_field(uint16_t class, const char *name, uint16_t type) { | |||
int nat = add_name_and_type(name, type); | |||
fputc(0x09, cout); | |||
fputc16(class, cout); | |||
fputc16(nat, cout); | |||
return cp_i++; | |||
} | |||
void make_flontainer(void) { | |||
cout = fopen("Flos.class", "w"); | |||
class[9] = 1 + 10 + 5 * n_flos; | |||
for(int i = 0; i < sizeof(class); i++) { | |||
fputc(class[i], cout); | |||
} | |||
for(int i = 0; i < n_flos; i++) { | |||
int ref; | |||
char varbuf[16]; | |||
snprintf(varbuf, 16, "flo%u", i); | |||
add_field(7, varbuf, 3); | |||
add_string(flos[i]); | |||
} | |||
fputc16(0x0001, cout); | |||
fputc16(0x0007, cout); | |||
fputc16(0x0006, cout); | |||
fputc16(0, cout); | |||
fputc16(n_flos, cout); | |||
for(int i = 0; i < n_flos; i++) { | |||
fputc16(0x0001, cout); | |||
fputc16(11 + i * 5, cout); | |||
fputc16(3, cout); | |||
fputc16(0, cout); | |||
} | |||
fputc16(1, cout); | |||
fputc16(0x0001, cout); | |||
fputc16(4, cout); | |||
fputc16(5, cout); | |||
fputc16(1, cout); | |||
fputc16(10, cout); | |||
fputc16(0, cout); | |||
fputc16(17 + n_flos * 6, cout); | |||
fputc16(2, cout); | |||
fputc16(1, cout); | |||
fputc16(0, cout); | |||
fputc16(5 + n_flos * 6, cout); | |||
fputc(0x2A, cout); | |||
fputc(0xB7, cout); fputc16(0x0009, cout); | |||
for(int i = 0; i < n_flos; i++) { | |||
fputc(0x2A, cout); | |||
fputc(0x12, cout); fputc(15 + 5 * i, cout); | |||
fputc(0xB5, cout); fputc16(13 + 5 * i, cout); | |||
} | |||
fputc(0xB1, cout); | |||
fputc16(0, cout); | |||
fputc16(0, cout); | |||
fputc16(0, cout); | |||
fclose(cout); | |||
} | |||
const char *printer = "\ | |||
import java.lang.reflect.Field;\n\ | |||
\n\ | |||
public class Printer {\n\ | |||
public static void print() throws Exception {\n\ | |||
Flos floContainer = new Flos();\n\ | |||
Field[] flos = floContainer.getClass().getFields();\n\ | |||
\n\ | |||
for(Field flo : flos) {\n\ | |||
System.out.println(flo.getName() + \": \" + flo.get(floContainer));\n\ | |||
}\n\ | |||
}\n\ | |||
}\n"; | |||
void make_printer(void) { | |||
FILE *out = fopen("Printer.java", "w"); | |||
fputs(printer, out); | |||
fclose(out); | |||
system("javac Printer.java"); | |||
} | |||
void print_flos(void) { | |||
JNIEnv *env; | |||
JavaVMInitArgs args; | |||
memset(&args, 0, sizeof(JavaVMInitArgs)); | |||
args.version = JNI_VERSION_1_6; | |||
JavaVM *jvm; | |||
JNI_CreateJavaVM(&jvm, (void**)&env, &args); | |||
jclass printer = (*env)->FindClass(env, "Printer"); | |||
jmethodID print = (*env)->GetStaticMethodID(env, printer, "print", "()V"); | |||
(*env)->CallStaticVoidMethod(env, printer, print); | |||
} | |||
int main(void) { | |||
make_flontainer(); | |||
make_printer(); | |||
print_flos(); | |||
return EXIT_SUCCESS; | |||
} | |||
</pre> | |||
== Fußnoten == | == Fußnoten == |
Version vom 21. Februar 2013, 20:26 Uhr
Wir sind die Flo, Widerstand ist zwecklos!
Beiträge, die die Anforderungen erfüllen
#!/usr/bin/env ruby flo = [ "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" ] # flos sind keine arrayss1! for i in 0..flo.size-1 eval "flo#{i} = flo[#{i}]" puts "flo#{i} == \"" + eval("flo#{i}") + "\"" end
Dieses Perl (*duck*) kann ja keiner lesen!1) Daher:
Dreckiges C:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> const int flolen = 6; static const char *flos[] = {"dividuum","syb","fiji","flowhase","florolf", "FlorianJW"}; static const char *proghead = "#include <stdio.h>\nint main(void){\n"; static const char *progend = " return(0);\n}\n"; int main(void){ int i; FILE *o; o=fopen("flo2.c","w"); fputs(proghead,o); for(i=0;i<flolen;i++){ fprintf(o," char *flo%d = \"%s\";\n",i,flos[i]); fprintf(o," printf(\"flo%%d ist %%s\\n\",%d,flo%d);\n",i,i); } fputs(progend,o); fclose(o); system("/usr/bin/gcc -o flos flo2.c;./flos;rm -f flo2.c flos"); return 0; }
Nu aber wirklich noch in Perl:
#!/usr/bin/perl @flo = ( "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" ); for $i (0..$#flo) { eval "\$flo$i = \$flo\[$i\]"; print "\$flo$i eq \"" . eval("\$flo$i") . "\"\n"; }
Perl:
#!/usr/bin/perl @flo = ( "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" ); for $i (0..$#flo) { ${"flo$i"} = $flo[$i]; print "\$flo$i eq \"" . ${"flo$i"} . "\"\n"; }
PHP:
<?php $flo = array( "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" ); foreach ($flo as $i => $x) { ${"flo$i"} = $flo[$i]; echo "\$flo$i = \"" . ${"flo$i"} . "\"\n"; } ?>
Gute alte Bash:
#!/bin/sh flo="dividuum syb fiji flowhase florolf FlorianJW" n=0 for f in $flo do eval flo$n=$f echo -n "flo$n == " eval echo \$flo$n n=$(($n+1)) done
Realisiert in PHP, Lisp, Perl, XML, Bash und XSLT und immernoch kürzer als die C-Version:
<?php $flo = array( "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" ); $l = fopen("flo.lisp", "w"); $p = fopen("flo.pl", "w"); fwrite($l, '(progn (format t "~a" "<flo>")'); fwrite($p,' print <<EOF <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/xhtml1/strict"> <xsl:template match="/">'); for($i=0;$i<count($flo);$i++) { fwrite($l, "(format t \"~a~a~a\" \"<flo$i>\" \"$flo[$i]\" \"</flo$i>\")"); fwrite($p, "flo$i == <xsl:value-of select=\"flo/flo$i\"/>\n"); } fwrite($l, '(format t "~a" "</flo>"))'); fwrite($p,' </xsl:template> </xsl:stylesheet> EOF'."\n"); fclose($l); fclose($p); system("sbcl --noinform --load flo.lisp --eval '(quit)' > flo.xml"); system("perl flo.pl > flo.xslt"); system("xsltproc flo.xslt flo.xml | grep -v xml"); ?> |
Noch einmal in Ruby:
#!/usr/bin/env ruby flo = [ "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" ] # flos sind keine arrayss1! flo.each_with_index do | f, i | instance_variable_set "@flo#{i}", f puts "flo#{i} = #{instance_variable_get "@flo#{i}"}" end
'cause JavaScript rocks:
flo = new Array("dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW"); for (i in flo) { eval("flo"+i+" = flo["+i+"]"); dump("flo"+i+" == "+eval("flo"+i)+"\n"); }
Wir moegen Lua:
#include <lua.h> #include <lualib.h> #include <lauxlib.h> lua_State *L; char *flos[] = {"dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW"}; char buf[1024]; void main() { char *p; int i; L = luaL_newstate(); luaL_openlibs(L); for(i=0; i < 6; i++) { sprintf(buf, "flo%d", i); lua_pushstring(L, flos[i]); lua_setglobal(L, buf); } p=buf; for(i=0; i < 6; i++) p += sprintf(p, "print(\"flo%d = \" .. flo%d);", i, i); luaL_dostring(L, buf); }
C++11:
#include <vector> #include <string> #include <cstdlib> #include <fstream> using namespace std; int main(){ vector<string> flo={"dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW"}; ofstream cpp_2("cpp_2.cpp"); cpp_2<<"#include <iostream>\n#include <string> \nusing namespace std;\nint main(){\n"; for(int i=0;i<flo.size();++i){ cpp_2<<"\tstring flo"<<i<<" =\""<<flo[i]<<"\";\n"; } cpp_2<<"\tcout\n"; for(int i=0;i<flo.size();++i){ cpp_2<<"\t\t<<flo"<<i; if(i+1==flo.size()){ cpp_2<<"<<endl;\n"; } else{ cpp_2<<"<<\", \"\n"; } } cpp_2<<"}"<<endl; cpp_2.close(); system("g++ cpp_2.cpp -o cpp_2; ./cpp_2"); return 0; }
Bloatiger Angebercode, der auch noch etwas völlig anderes macht
Und nochmal das, was das Ruby-Programm "mit viel bloatigem Metaprogramming-Foo" macht, allerdings wiederum in Common Lisp gegossen:
(Warnung: (Zumindest) als Lispprogramm ist dieses Beispiel ziemlich unsinning, und z.B. die PRINT-OBJECT-Methode widerspricht der gängigen Konvention.)
Ru^W Objektorientiertes C
// Das aendern: #include "/usr/local/lib/ruby/1.8/i386-freebsd5/ruby.h" VALUE flo_init(VALUE self) { char *flo[] = {"dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW"}; int i; for(i = 0; i < 6; i++) { char varname[7]; sprintf(varname, "@flo%i", i); // Insecure! rb_iv_set(self, varname, rb_str_new2(flo[i])); } } VALUE flo_each(VALUE self) { int i; VALUE vars = rb_funcall(self, rb_intern("instance_variables"), 0); VALUE varname = rb_ary_shift(vars); while(varname != Qnil) { rb_yield(rb_ary_new3(2, varname, rb_iv_get(self, RSTRING(varname)->ptr))); varname = rb_ary_shift(vars); } return(Qnil); } int main() { VALUE flo; ruby_init(); flo = rb_define_class("Flo", rb_cObject); rb_define_method(flo, "initialize", flo_init, 0); rb_define_method(flo, "each", flo_each, 0); rb_eval_string("Flo.new.each { |name,value| puts \"#{name.gsub(/^@/, '')} = #{value}\" }"); return(0); }
Die Enterprise-Loesung
Das Schlimmste aus beiden Welten.
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <string.h> #include <jni.h> const char *flos[] = { "dividuum", "syb", "fiji", "flowhase", "florolf", "FlorianJW" }; const int n_flos = sizeof(flos)/sizeof(char*); unsigned char class[] = { 0xca, 0xfe, 0xba, 0xbe, 0x00, 0x00, 0x00, 0x33, 0, 0, 0x01, 0x00, 16, 'j', 'a', 'v', 'a', '/', 'l', 'a', 'n', 'g', '/', 'O', 'b', 'j', 'e', 'c', 't', 0x01, 0x00, 4, 'F', 'l', 'o', 's', 0x01, 0x00, 18, 'L', 'j', 'a', 'v', 'a', '/', 'l', 'a', 'n', 'g', '/', 'S', 't', 'r', 'i', 'n', 'g', ';', 0x01, 0x00, 6, '<', 'i', 'n', 'i', 't', '>', 0x01, 0x00, 3, '(', ')', 'V', 0x07, 0, 1, 0x07, 0, 2, 0x0C, 0, 4, 0, 5, 0x0A, 0, 6, 0, 8, 0x01, 0x00, 4, 'C', 'o', 'd', 'e', }; int cp_i = 11; FILE *cout; void fputc16(uint16_t in, FILE *out) { fputc(in >> 8, out); fputc(in & 0xFF, out); } uint16_t add_utf8(const char *string) { size_t len = strlen(string); fputc(0x01, cout); fputc16(len, cout); fputs(string, cout); return cp_i++; } uint16_t add_string(const char *string) { uint16_t utf8 = add_utf8(string); fputc(0x08, cout); fputc16(utf8, cout); return cp_i++; } uint16_t add_name_and_type(const char *name, uint16_t type) { uint16_t namei = add_utf8(name); fputc(0x0C, cout); fputc16(namei, cout); fputc16(type, cout); return cp_i++; } uint16_t add_field(uint16_t class, const char *name, uint16_t type) { int nat = add_name_and_type(name, type); fputc(0x09, cout); fputc16(class, cout); fputc16(nat, cout); return cp_i++; } void make_flontainer(void) { cout = fopen("Flos.class", "w"); class[9] = 1 + 10 + 5 * n_flos; for(int i = 0; i < sizeof(class); i++) { fputc(class[i], cout); } for(int i = 0; i < n_flos; i++) { int ref; char varbuf[16]; snprintf(varbuf, 16, "flo%u", i); add_field(7, varbuf, 3); add_string(flos[i]); } fputc16(0x0001, cout); fputc16(0x0007, cout); fputc16(0x0006, cout); fputc16(0, cout); fputc16(n_flos, cout); for(int i = 0; i < n_flos; i++) { fputc16(0x0001, cout); fputc16(11 + i * 5, cout); fputc16(3, cout); fputc16(0, cout); } fputc16(1, cout); fputc16(0x0001, cout); fputc16(4, cout); fputc16(5, cout); fputc16(1, cout); fputc16(10, cout); fputc16(0, cout); fputc16(17 + n_flos * 6, cout); fputc16(2, cout); fputc16(1, cout); fputc16(0, cout); fputc16(5 + n_flos * 6, cout); fputc(0x2A, cout); fputc(0xB7, cout); fputc16(0x0009, cout); for(int i = 0; i < n_flos; i++) { fputc(0x2A, cout); fputc(0x12, cout); fputc(15 + 5 * i, cout); fputc(0xB5, cout); fputc16(13 + 5 * i, cout); } fputc(0xB1, cout); fputc16(0, cout); fputc16(0, cout); fputc16(0, cout); fclose(cout); } const char *printer = "\ import java.lang.reflect.Field;\n\ \n\ public class Printer {\n\ public static void print() throws Exception {\n\ Flos floContainer = new Flos();\n\ Field[] flos = floContainer.getClass().getFields();\n\ \n\ for(Field flo : flos) {\n\ System.out.println(flo.getName() + \": \" + flo.get(floContainer));\n\ }\n\ }\n\ }\n"; void make_printer(void) { FILE *out = fopen("Printer.java", "w"); fputs(printer, out); fclose(out); system("javac Printer.java"); } void print_flos(void) { JNIEnv *env; JavaVMInitArgs args; memset(&args, 0, sizeof(JavaVMInitArgs)); args.version = JNI_VERSION_1_6; JavaVM *jvm; JNI_CreateJavaVM(&jvm, (void**)&env, &args); jclass printer = (*env)->FindClass(env, "Printer"); jmethodID print = (*env)->GetStaticMethodID(env, printer, "print", "()V"); (*env)->CallStaticVoidMethod(env, printer, print); } int main(void) { make_flontainer(); make_printer(); print_flos(); return EXIT_SUCCESS; }
Fußnoten
1) Anmerkung zu: "Dieses Perl (*duck*) kann ja keiner lesen!"
Stimmt doch gar nicht! Ist ganz einfach:
map printf("%s = %s\n", [flo0..flo5]->[$_], [dividuum, syb, fiji, flowhase, florolf, FlorianJW]->[$_]), 0..$#{@{[flo0..flo5]}};
(Kommentar von mgr: Genau, "0..$#{@{[flo0..flo5]}}" ... q.e.d. Danke für das gute Beispiel. Aber ernsthaft, es ging hier eben gerade *nicht* um Einzeiler, die will niemand.)
Und auch in python kann man Einzeiler schreiben:
print "\n".join(["%s = %s" % (k, v) for k, v in {"flo0":"dividuum", "flo1":"syb", "flo2":"fiji", "flo3":"flowhase","flo4":"florolf", "flo5":"FlorianJW"}.items()])