Ich habe gerade folgendes Quine von Yusuke Endoh gefunden:
1 2 |
# ruby l=92.chr;eval s="s=s.dump[r=1..-2].gsub(/("+l*4+"){4,}(?!\")/){|t|'\"+l*%d+\"'%(t.size/2)};5.times{s=s.dump[r]};puts\"# python\\nprint(\\\"# perl\\\\nprint(\\\\\\\"# lua"+l*4+"nprint("+l*7+"\"(* ocaml *)"+l*8+"nprint_endline"+l*15+"\"-- haskell"+l*16+"nimport Data.List;import Data.Bits;import Data.Char;main=putStrLn("+l*31+"\"/* C */"+l*32+"n#include<stdio.h>"+l*32+"nint main(void){char*s[501]={"+l*31+"\"++intercalate"+l*31+"\","+l*31+"\"(c(tail(init(show("+l*31+"\"/* Java */"+l*32+"npublic class QuineRelay{public static void main(String[]a){String[]s={"+l*31+"\"++intercalate"+l*31+"\","+l*31+"\"(c("+l*31+"\"brainfuck"+l*64+"n++++++++[>++++<-]+++++++++>>++++++++++"+l*31+"\"++(concat(snd(mapAccumL h 2("+l*31+"\"110"+l*31+"\"++g(length s)++"+l*31+"\"22111211100111112021111102011112120012"+l*31+"\"++concatMap("+l*32+"c->let d=ord c in if d<11then"+l*31+"\"21002"+l*31+"\"else"+l*31+"\"111"+l*31+"\"++g d++"+l*31+"\"22102"+l*31+"\")s++"+l*31+"\"21002111010120211222211211101000120211021120221102111000110120211202"+l*31+"\"))))))++"+l*31+"\","+l*63+"\""+l*64+"n"+l*63+"\"};int i=0;for(;i<94;i++)System.out.print(s[i]);}}"+l*31+"\")))))++"+l*31+"\",0};int i=0;for(;s[i];i++)printf("+l*63+"\"%s"+l*63+"\",s[i]);puts("+l*63+"\""+l*63+"\");return 0;}"+l*31+"\");c s=map("+l*32+"s->"+l*31+"\""+l*63+"\""+l*31+"\"++s++"+l*31+"\""+l*63+"\""+l*31+"\")(unfoldr t s);t[]=Nothing;t s=Just(splitAt(if length s>w&&s!!w=='"+l*31+"\"'then 501else w)s);w=500;f 0=Nothing;f x=Just((if x`mod`2>0then '0'else '1'),x`div`2);g x= reverse (unfoldr f x);h p c=let d=ord c-48in(d,replicate(abs(p-d))(if d<p then '<'else '>')++"+l*31+"\"."+l*31+"\");s="+l*31+"\"# ruby"+l*32+"n"+l*31+"\"++"+l*31+"\"l=92.chr;eval s=\"+(z=l*31)+\"\\\"\"+s+z+\"\\\""+l*31+"\"++"+l*31+"\""+l*32+"n"+l*31+"\""+l*15+"\""+l*7+"\")"+l*4+"n\\\\\\\")\\\")\"########### (c) Yusuke Endoh, 2009 ###########\n" |
Das besondere an diesem Quine?
1 2 3 4 5 6 7 8 9 10 11 |
$ ruby QuineRelay.rb > QuineRelay.py $ python QuineRelay.py > QuineRelay.pl $ perl QuineRelay.pl > QuineRelay.lua $ lua QuineRelay.lua > QuineRelay.ml $ ocaml QuineRelay.ml > QuineRelay.hs $ runghc QuineRelay.hs > QuineRelay.c $ gcc -Wall -o QuineRelay QuineRelay.c && ./QuineRelay > QuineRelay.java $ javac QuineRelay.java && java QuineRelay > QuineRelay.bf $ beef QuineRelay.bf > QuineRelay.ws $ wspace QuineRelay.ws > QuineRelay.unl $ unlambda QuineRelay.unl > QuineRelay2.rb |
Und abschliessend:
$ diff QuineRelay.rb QuineRelay2.rb |
Ich bin verstört…
Method chaining - also die implementierung einer Methode durch verketten mehrerer anderer ist durch Ruby on Rails zu einer gewissen Popularität gelangt. Während sich Rails hier auf ein einfaches Namenschema und alias verlässt, bietet DataMapper hier eine Technik an, die sich vorzüglich für einen Ausflug in Rubys Objektmodell eignet. Diese Gelegenheit will ich nicht an mir vorüber gehen lassen und die Implementierung namens Chainable hier vorstellen.
David Brady hat einen Mandelbrot Einzeiler geschrieben:
60.times{|a|puts((0..240).map{|b|x=y=i=0;until(x*x+y*y>4||i==99);x,y,i=x*x-y*y+b/120.0-1.5,2*x*y+a/30.0-1,i+1;end;i==99?'#':'.'}*'');} |
Ich liebe Code der das Layout hinrichtet. Wobei sich streitet lässt, ob ein Stück Code mit mehr als 80 Zeichen wirklich noch ein Einzeiler ist.
Optimierte Version von Jan:
60.times{|a|puts (0..240).map{|b|x=y=i=0;x,y=x*x-y*y+b/120.0-1.5,2*x*y+a/30.0-1until x*x+y*y>4||98<i+=1;i>98?'#':'.'}*''} |
Seit ein paar Tagen gibt es eine neue Hookmethode mit dem Namen respond_to_missing? im Rubytrunk.
Es ist zwar noch eine ganze Weile bis Weihnachten, aber eins ist sicher: Ruby 1.9.2 kommt. Und mit ihm ein Herzenswunsch Yehuda Katz's, der es wegen später Einreichung nicht mehr in 1.9.1 geschafft hat, aber im trunk vorhanden ist: Proc#parameters. Einen kleinen Spass, den man sich damit leisten kann, findet ihr unter dem Link.
(Deutsche Übersetzung; Original auf murfy.de.)
Ich bin gerade dabei, den Java Scanner für CodeRay (Ticket #42 ^^) zu schreiben, und dachte, es wäre nett, eine Liste von eingebauten Typen zu haben, um sie hervorzuheben – wie String oder IllegalStateException. Ich wusste, dass TextMate recht gute Unterstützung für Java bietet, also schaute ich mir das Bundle genauer an.
Tatsächlich, irgendein schlauer Kerl hat dort einen ziemlich langen regulären Ausdruck in die Tokendefinitionen geschrieben:
support-type-built-ins-java = {
name = 'support.type.built-ins.java';
match = '\b(R(GBImageFilter|MI(S(ocketFactory|e(curity(Manager|Exception)|
rver(SocketFactory|Impl(_Stub)?)?))|C(onnect(ion(Impl(_Stub)?)?|
or(Server)?)|l(ientSocketFactory|assLoader(Spi)?))|IIOPServerImpl|
JRMPServerImpl|FailureHandler)|SA(MultiPrimePrivateCrtKey(Spec)?|
...und so weiter über mehrere Bildschirmseiten...Offenbar haben sie eine lange Liste von Typen in eine minimale Regexp umgewandelt, sicher mit Hilfe eine Scripts. Das war nicht ganz das, wonach ich gesucht hatte. Wie komme ich jetzt an die ursprüngliche Liste?
Wann hast Du das letzte mal die Bibliothek benchmark aus der Ruby Standardbibliothek benutzt? Kannst Du Dich noch erinnern, wie die Methoden heißen, die man braucht, um einen Benchmarkbericht zu erzeugen?
Ich muss jedes mal neu in der API-Dokumentation nachschauen, weil die Bibliothek für mich nicht gerade intuitiv ist, so dass ich die Benutzung immer wieder vergesse. Aber dem kann man ja Abhilfe schaffen…
Quines sind bekanntermassen Programme die ihren eigenen Quelltext ausgeben.
Aber jetzt gibts was neues: Quines der 3. Ordnung. sigfpe hat ein kleines Haskell-Programm entwickelt:
q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']
main=q "q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']" "def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'" "def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end"Führt man dieses Programm aus, erhält man ein Python-Programm:
def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'
q("def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'","def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end","q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']")… welches wiederum ein Ruby-Programm produziert:
def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end q("def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end","q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']","def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'")
Und dieses Ruby-Programm produziert wieder das Haskell-Programm. Toll, oder?
Jawohl :)
class Feeling def ~ p :drunk end def ! p :alert end def -@ p :bad end def +@ p :good end end feeling = Feeling.new -feeling # => :bad +feeling # => :good !feeling # => :alert ~feeling # => :drunk # >> :bad # >> :good # >> :alert # >> :drunk
Der Fachmann/Die Fachmassaigiraffe sieht hier mehrere Dinge:
p gibt seine Argumente nicht nur aus, sondern auch zurück (statt nil.)matz sagt:
For good news, I have no big change left.
Laurent Sansonetti ist der Herr der bei Apple für Ruby verantwortlich ist. Neben dem Ruby Interpreter kümmert er sich auch um so sachen wie RubyCocoa, einer Ruby-ObjectiveC-Bridge, mit der man native OS X Programme in Ruby schreiben kann.
Und jetzt hat er RubyInject veröffentlicht.
Rails hat Symbol#to_proc populär gemacht. So sehr dass es sogar Teil von Ruby 1.9 werden wird.
String#to_proc implementiert. Das sieht folgendermassen aus:
'x+1'.to_proc[2] # => 3 'x+2*y'.to_proc[2, 3] # => 8
Symbol#to_proc verwendet wird, braucht man String#to_proc nicht. Verglichen mit
%w[dsf fgdg fg].map(&:capitalize)
%w[dsf fgdg fg].map(&'.capitalize')
(1..5).map &'*2' # => [2, 4, 6, 8, 10]
(1..5).inject &'+' # => 15

Endlich kann man auch Musik beim Programmieren hören ;-)
Dass man Methoden in Ruby auch groß schreiben darf, ist ja allgemein bekannt. Es gibt sogar Methoden wie Array, die genauso heißen wie eine Konstante. Die Namensräume von Konstanten und Methoden sind also getrennt.
Doch wie geht defined? damit um? Erkennt es, dass es zwei Objekte mit demselben Namen gibt?
# Ruby 1.8/1.9 Foo = 'Konstante' def Foo 'Methode' end Foo # => "Konstante" Foo() # => "Methode" defined? Foo # => "constant" defined? Foo() # => "method"
Also: Wenn man eine großgeschriebene Methode auf Existenz testen will, muss man Klammern dahinter setzen.