Die Programmiersprache Ruby

Blog|

Forum|

Wiki  


Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]

Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Code-Golf: Methodennamen sortieren
BeitragVerfasst: 30 Jul 2012, 19:25 
Offline
Interpreter
Benutzeravatar

Registriert: 18 Sep 2008, 22:32
Beiträge: 1412
Wohnort: NRW → UN
Hallo Leute,

nachdem ich gerade wieder an meinem Papyrus-Projekt gearbeitet habe, stand ich gerade vor der netten Aufgabe, Methodennamen zu sortieren (Papyrus ist ein RDoc-Template). Das soll natürlich kurz und bündig vonstatten gehen, und ist damit eine prima Aufgabe für Code-Golf ;)

Folgendes: Gegeben ist ein unsortiertes Array mit RDoc::ClassModule-Objekten. Damit ihr die Doku nicht quälen müsst: Diese Klasse bietet eine Methode #method_list (und falls interessant auch #each_method) an, die ihrerseits ein unsortiertes Array von RDoc::AnyMethod-Objekten zurückgibt. Diese wiederum bieten die Methode #pretty_name, welche den Methodennamen je nach Typ als "::foo" oder "#foo" zurückgibt. Außerdem bieten sie die Methode #full_name, welche den voll qualifizierten Methodennamen à la "Foo::Bar#foo" oder "Foo::Bar::foo" zurückgibt und #name_prefix für das Zeichen "::" oder "#" je nach Typ.

Ziel ist es nun, das ganze in der für Ruby-Dokumentation üblichen Ordnung in ein Array, das nur noch die RDoc::AnyMethod-Objekte enthält, zu sortieren. Das heißt: Auf oberster Ebene wird nach Klassen/Modulnamen geordnet (Klasse oder Modul ist gleichwertig). Innerhalb einer Klasse/Modul werden dann zunächst die Klassenmethoden gelistet, danach folgen die Instanzmethoden. Diese wiederum sollen jeweils alphabetisch sortiert sein.

Konkret also soll eine solche Ordnung entstehen:

Bar::class_method
Bar::this_is_another_class_method
Bar#instance_method
Bar#instance_method2
Foo::a_class_meth
Foo::Bar#an_inst_meth

Ich hab mich schon dran versucht, aber mit dem Ergebnis bin ich nicht zufrieden. ary.map{|mod| mod.method_list.sort{|m1, m2| tm1, tm2 = [m1, m2].map{|m|m.pretty_name.tr(":#", "ab")}; tm1 <=> tm2}}.flatten

Oder im zweiten Anlauf: ary.map{|mod| mod.method_list}.flatten.sort{|m1, m2| m1.full_name.tr(":#", "ab") <=> m2.full_name.tr(":#", "ab")}

Das geht kürzer :)

Und weil die bloße Theorie langweilig ist, hier eine vollständige Datei, mit der ihr euren Code testen könnt: # -*- coding: utf-8 -*-
require "rdoc/rdoc"
require "pathname"

# Dateien und Verzeichnisse, die dokumentiert werden sollen
DOC_TARGETS = [Pathname.pwd + "lib"]
# Ausgabeverzeichnis
OUTPUT_DIR = Pathname.pwd + "doc"

class Sorter

def initialize(options)
@output_dir = Pathname.pwd.expand_path + options.op_dir
end

def generate(top_levels)
# Klassen und Module abgreifen (ary enthält dann die RDoc::ClassModule-Objekte)
ary = RDoc::TopLevel.all_classes + RDoc::TopLevel.all_modules

# ↓↓↓ Hier meinen Sortiercode durch euren ersetzen ↓↓↓
sorted = ary.map{|mod| mod.method_list}.flatten.sort{|m1, m2| m1.full_name.tr(":#", "ab") <=> m2.full_name.tr(":#", "ab")}

# Und hier die Ausgabe
File.open(@output_dir + "sorted_method_list.txt", "w") do |file|
sorted.each{|meth| file.puts meth.full_name}
end
end

end

if __FILE__ == $0
options = RDoc::Options.new
options.template = "" # Für den Minimalgenerator wird kein Template benötigt
options.generator = Sorter
options.files = DOC_TARGETS
options.op_dir = OUTPUT_DIR
RDoc::RDoc.new.document(options)
end

Einfach an der entsprechend markierten Stelle den Sortiercode einsetzen und bei DOC_TARGETS Verzeichnisse oder Ruby-Dateien auflisten, die RDoc parsen soll. Das Ergebnis liegt dann in doc/sorted_method_list.txt.

Valete,
Quintus

EDIT: Ich sehe gerade, die zweite Lösung sortiert nichts ganz richtig, der vergleicht Klassenmethoden direkt mit Klassennamen. Also bitte nicht als Referenz nehmen (aber die erste sollte tun).

_________________
Habe den Mut, dich deines eigenen Verstandes zu bedienen! — Immanuel Kant

Mein Blog | Auf Twitter: @qquintilianus | PGP/GPG-Schlüssel: BF3A 614B D62B A4A0 C292 141C B875 5CB1 C592 A85A

Helft beim OpenRubyRMK, einem freien Programm zum erstellen von RPGs! (→ GitHub-Projekt)


Nach oben
 Profil  
 
BeitragVerfasst: 30 Jul 2012, 19:44 
Offline
Rubyist
Benutzeravatar

Registriert: 04 Jun 2008, 22:03
Beiträge: 394
in etwa so?
ary.map{|mod| mod.each_method.sort_by{|m|m.pretty_name.tr(":#", "ab")}}.flatten


Nach oben
 Profil  
 
BeitragVerfasst: 30 Jul 2012, 19:52 
Offline
Interpreter
Benutzeravatar

Registriert: 18 Sep 2008, 22:32
Beiträge: 1412
Wohnort: NRW → UN
Das geht leider nicht :(/opt/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/rdoc/context.rb:762:in `block in each_method': no block given (yield) (LocalJumpError)


Und mit enum_for bekomme ich seltsame Ergebnisse... ...
RDoc::Markup::ToPrawn#show_pages?
RDoc::Markup::ToPrawn#start_accepting
RDoc::Markup::ToPrawn#to_prawn
RDoc::Generator::PrawnMarkup#anchor
RDoc::Generator::PrawnMarkup#current_heading_level
RDoc::Generator::PrawnMarkup#describe_in_pdf
...

Generator müsste hier zuerst kommen.

Vale,
Quintus

_________________
Habe den Mut, dich deines eigenen Verstandes zu bedienen! — Immanuel Kant

Mein Blog | Auf Twitter: @qquintilianus | PGP/GPG-Schlüssel: BF3A 614B D62B A4A0 C292 141C B875 5CB1 C592 A85A

Helft beim OpenRubyRMK, einem freien Programm zum erstellen von RPGs! (→ GitHub-Projekt)


Nach oben
 Profil  
 
BeitragVerfasst: 30 Jul 2012, 19:55 
Offline
Rubyist
Benutzeravatar

Registriert: 04 Jun 2008, 22:03
Beiträge: 394
ok aktuell sind die module nicht sortiert:
aber jetzte:
ary.sort_by(&:name).map{|mod| mod.each_method.sort_by{|m|m.pretty_name.tr(":#", "ab")}}.flatten


Nach oben
 Profil  
 
BeitragVerfasst: 30 Jul 2012, 20:05 
Offline
Interpreter
Benutzeravatar

Registriert: 18 Sep 2008, 22:32
Beiträge: 1412
Wohnort: NRW → UN
Das gibt immer noch den LocalJumpError. #each_method unterstützt so keine Enumeratoren. Mit #method_list sieht’s aber auch düster aus: ...
RDoc::Generator::Papyrus::Options#show_pages=
RDoc::Generator::Papyrus::new
RDoc::Generator::Papyrus::setup_options
RDoc::Generator::Papyrus#generate
...

RDoc::Generator::Papyrus ist aber kürzer als RDoc::Generator::Papyrus::Options und muss daher zuerst kommen. ::new ist ja keine Klasse/Modul, sondern eine Klassenmethode.

Vale,
Quintus

_________________
Habe den Mut, dich deines eigenen Verstandes zu bedienen! — Immanuel Kant

Mein Blog | Auf Twitter: @qquintilianus | PGP/GPG-Schlüssel: BF3A 614B D62B A4A0 C292 141C B875 5CB1 C592 A85A

Helft beim OpenRubyRMK, einem freien Programm zum erstellen von RPGs! (→ GitHub-Projekt)


Nach oben
 Profil  
 
BeitragVerfasst: 30 Jul 2012, 20:30 
Offline
Rubyist
Benutzeravatar

Registriert: 04 Jun 2008, 22:03
Beiträge: 394
und jetzt? wie ist das:
ary.sort_by(&:full_name).map{|mod| mod.each_for(:each_method).sort_by{|m|m.pretty_name.tr(":#", "ab")}}.flatten


Nach oben
 Profil  
 
BeitragVerfasst: 10 Aug 2012, 11:18 
Offline
Interpreter
Benutzeravatar

Registriert: 18 Sep 2008, 22:32
Beiträge: 1412
Wohnort: NRW → UN
Ah, sorry für die späte Antwort, ich war in der letzten Zeit mit einem anderen Projekt beschäftigt... Aber ja, der Code funktioniert (wenn man #each_for durch #enum_for ersetzt) ;-). Ich bau das dann mal so ein. Sieht gar nicht so unheimlich aus :-)

Vale,
Quintus

PS: Ah, ich darf das doch unter der GPLv3 benutzen?

_________________
Habe den Mut, dich deines eigenen Verstandes zu bedienen! — Immanuel Kant

Mein Blog | Auf Twitter: @qquintilianus | PGP/GPG-Schlüssel: BF3A 614B D62B A4A0 C292 141C B875 5CB1 C592 A85A

Helft beim OpenRubyRMK, einem freien Programm zum erstellen von RPGs! (→ GitHub-Projekt)


Nach oben
 Profil  
 
BeitragVerfasst: 10 Aug 2012, 13:24 
Offline
Rubyist
Benutzeravatar

Registriert: 04 Jun 2008, 22:03
Beiträge: 394
jo mach doch :P ... ps ich wundere mich warum der nicht geht ... als ich mir den code von rdoc angesehen habe müsste es funktionieren ... vllt solltest du mal rdoc updaten?


Nach oben
 Profil  
 
BeitragVerfasst: 11 Aug 2012, 16:37 
Offline
Interpreter
Benutzeravatar

Registriert: 18 Sep 2008, 22:32
Beiträge: 1412
Wohnort: NRW → UN
Hanmac hat geschrieben:
jo mach doch :P ... ps ich wundere mich warum der nicht geht ... als ich mir den code von rdoc angesehen habe müsste es funktionieren ... vllt solltest du mal rdoc updaten?

Mein RDoc sollte aktuell sein: $ rdoc --version
rdoc 3.12

Vale,
Quintus

_________________
Habe den Mut, dich deines eigenen Verstandes zu bedienen! — Immanuel Kant

Mein Blog | Auf Twitter: @qquintilianus | PGP/GPG-Schlüssel: BF3A 614B D62B A4A0 C292 141C B875 5CB1 C592 A85A

Helft beim OpenRubyRMK, einem freien Programm zum erstellen von RPGs! (→ GitHub-Projekt)


Nach oben
 Profil  
 
BeitragVerfasst: 12 Aug 2012, 13:31 
Offline
Rubyist
Benutzeravatar

Registriert: 04 Jun 2008, 22:03
Beiträge: 394
http://rdoc.rubyforge.org/RDoc/Context.html#method-i-each_method

def each_method # :yields: method
return enum_for __method__ unless block_given?

@method_list.sort.each { |m| yield m }
end

?¿

ka warums bei dir nicht is ...


Nach oben
 Profil  
 
BeitragVerfasst: 13 Aug 2012, 23:23 
Offline
Interpreter
Benutzeravatar

Registriert: 18 Sep 2008, 22:32
Beiträge: 1412
Wohnort: NRW → UN
each_for ist aber nicht each_method...

Vale,
Quintus

_________________
Habe den Mut, dich deines eigenen Verstandes zu bedienen! — Immanuel Kant

Mein Blog | Auf Twitter: @qquintilianus | PGP/GPG-Schlüssel: BF3A 614B D62B A4A0 C292 141C B875 5CB1 C592 A85A

Helft beim OpenRubyRMK, einem freien Programm zum erstellen von RPGs! (→ GitHub-Projekt)


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach: