(ruby noch edler) |
Mgr (Diskussion | Beiträge) (Lisp-Äquivalent zu dem Ruby-Programm "mit viel bloatigem Metaprogramming-Foo") |
||
Zeile 18: | Zeile 18: | ||
</pre> | </pre> | ||
Dieses Perl (*duck*) kann ja keiner lesen! <span id="footref1">[[#footnote1|<sup><small>1)</small></sup>]]</span> | Dieses Perl (*duck*) kann ja keiner lesen!<span id="footref1">[[#footnote1|<sup><small>1)</small></sup>]]</span> Daher: | ||
{| cellpadding=5 | {| cellpadding=5 | ||
Zeile 97: | Zeile 97: | ||
a = [ Flo0.new, Flo1.new, Flo2.new, Flo3.new ] | a = [ Flo0.new, Flo1.new, Flo2.new, Flo3.new ] | ||
a.each { |f| puts f } | a.each { |f| puts f } | ||
</pre> | |||
Und nochmal das, was das Ruby-Programm "mit viel bloatigem Metaprogramming-Foo" macht, allerdings wiederum in Common Lisp gegossen: | |||
<br>(Warnung: Als Lispprogramm ist dieses Beispiel ziemlich unsinning, und z.B. die PRINT-OBJECT-Methode widerspricht der gängigen Konvention.) | |||
<pre> | |||
(defclass flo () | |||
((name :initarg :name :reader flo-name) | |||
(skill :initarg :skill :reader flo-skill) | |||
(notebook :initarg :notebook :reader flo-notebook))) | |||
(defun slot-value-or-something (object &key (slot 'name) (something "without name")) | |||
(if (slot-boundp object slot) | |||
(slot-value object slot) | |||
something)) | |||
(defmethod print-object ((flo flo) stream) | |||
(format stream "~&~a is actually ~a and is good at ~a.~&He loves hacking on his ~a." | |||
(class-name (class-of flo)) | |||
(slot-value-or-something flo) | |||
(slot-value-or-something flo :slot 'skill :something "nothing") | |||
(slot-value-or-something flo :slot 'notebook :something "dulcimer"))) | |||
(defmacro def-flo-class (class-name &key name skill notebook) | |||
(macrolet ((make-slot-def (name) | |||
`(when ,name | |||
`(,',name :initform ,,name)))) | |||
`(defclass ,class-name (flo) | |||
,(remove nil (list | |||
(make-slot-def name) | |||
(make-slot-def skill) | |||
(make-slot-def notebook)))))) | |||
(def-flo-class |Flo0| | |||
:name "dividuum" | |||
:skill "DOOM" | |||
:notebook "old Dell") | |||
(def-flo-class |Flo1| | |||
:name "Peter" | |||
:skill "math" | |||
:notebook "IBM Thinkpad") | |||
(def-flo-class |Flo2| | |||
:name "Fiji" | |||
:skill "WOW" | |||
:notebook "I-have-no-idea") | |||
(def-flo-class |Flo3| | |||
:name "flohase" | |||
:skill "hoppeln" | |||
:notebook "hasIbook") | |||
(let ((flos (list (make-instance '|Flo0|) | |||
(make-instance '|Flo1|) | |||
(make-instance '|Flo2|) | |||
(make-instance '|Flo3|)))) | |||
(dolist (flo flos) | |||
(print flo))) | |||
</pre> | </pre> | ||
Zeile 130: | Zeile 189: | ||
<hr> | <hr> | ||
<span id="footnote1">[[#footref1|1)]]</span> Anmerkung zu: [[#footref1|"Dieses Perl (*duck*) kann ja keiner lesen!"]] | <span id="footnote1">[[#footref1|1)]]</span> Anmerkung zu: [[#footref1|"Dieses Perl (*duck*) kann ja keiner lesen!"]] | ||
Version vom 4. November 2005, 00:19 Uhr
#!/usr/bin/env ruby flo = [ "dividuum", "syb", "fiji", "flowhase" ] # 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:
Und nun nochmal Ruby mit viel bloatigem Metaprogramming-Foo (Und etwas völlig anderes machend. Anm. v. mgr):
#!/usr/bin/env ruby class Flo def self.metaclass; class << self; self; end; end def self.traits(*arr) return @traits if arr.empty? attr_accessor *arr arr.each do |a| metaclass.instance_eval do define_method( a ) do |val| @traits ||= {} @traits[a] = val end end end class_eval do define_method( :initialize ) do self.class.traits.each do |k,v| instance_variable_set("@#{k}", v) end end end end traits :name, :skill, :notebook def to_s s = "#{self.class} is actually #{self.name} and is good at #{self.skill}\n\tHe loves hacking on his #{self.notebook}" end end class Flo0 < Flo name "dividuum" skill "DOOM" notebook "old Dell" end class Flo1 < Flo name "Peter" skill "math" notebook "IBM Thinkpad" end class Flo2 < Flo name "Fiji" skill "WOW" notebook "i have no idea" end class Flo3 < Flo name "flowhase" skill "hoppeln" notebook "hasIbook" end a = [ Flo0.new, Flo1.new, Flo2.new, Flo3.new ] a.each { |f| puts f }
Und nochmal das, was das Ruby-Programm "mit viel bloatigem Metaprogramming-Foo" macht, allerdings wiederum in Common Lisp gegossen:
(Warnung: Als Lispprogramm ist dieses Beispiel ziemlich unsinning, und z.B. die PRINT-OBJECT-Methode widerspricht der gängigen Konvention.)
(defclass flo () ((name :initarg :name :reader flo-name) (skill :initarg :skill :reader flo-skill) (notebook :initarg :notebook :reader flo-notebook))) (defun slot-value-or-something (object &key (slot 'name) (something "without name")) (if (slot-boundp object slot) (slot-value object slot) something)) (defmethod print-object ((flo flo) stream) (format stream "~&~a is actually ~a and is good at ~a.~&He loves hacking on his ~a." (class-name (class-of flo)) (slot-value-or-something flo) (slot-value-or-something flo :slot 'skill :something "nothing") (slot-value-or-something flo :slot 'notebook :something "dulcimer"))) (defmacro def-flo-class (class-name &key name skill notebook) (macrolet ((make-slot-def (name) `(when ,name `(,',name :initform ,,name)))) `(defclass ,class-name (flo) ,(remove nil (list (make-slot-def name) (make-slot-def skill) (make-slot-def notebook)))))) (def-flo-class |Flo0| :name "dividuum" :skill "DOOM" :notebook "old Dell") (def-flo-class |Flo1| :name "Peter" :skill "math" :notebook "IBM Thinkpad") (def-flo-class |Flo2| :name "Fiji" :skill "WOW" :notebook "I-have-no-idea") (def-flo-class |Flo3| :name "flohase" :skill "hoppeln" :notebook "hasIbook") (let ((flos (list (make-instance '|Flo0|) (make-instance '|Flo1|) (make-instance '|Flo2|) (make-instance '|Flo3|)))) (dolist (flo flos) (print flo)))
dreckig:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> const int flolen = 4; static char *flos[] = {"dividuum","syb","fiji","flowhase"}; static char *proghead = "#include <stdio.h>\n" "int main(void){\n"; static 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); }
1) Anmerkung zu: "Dieses Perl (*duck*) kann ja keiner lesen!"
Stimmt doch gar nicht! Ist ganz einfach:
map printf("%s = %s\n", [flo0..flo3]->[$_], [dividuum, syb, fiji, flowhase]->[$_]), 0..$#{@{[flo0..flo3]}};
(Kommentar von mgr: Genau, "0..$#{@{[flo0..flo3]}}" ... 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"}.items()])