Ich versuche herauszufinden, wie Ruby Verkettungs-Enumeratoren behandelt, die mehrere Argumente liefern. Schauen Sie sich dieses Snippet an:
%Vor% Warum liefert select
die Argumente als Array, während map
sie als zwei separate Argumente liefert?
Aus dem bisherigen Diskurs folgt, dass wir den Quellcode analysieren können, aber wir kennen das Warum nicht. Ruby-Core-Team ist relativ sehr reaktionsschnell. Ich empfehle Ihnen, sich unter Ссылка anzumelden und dort einen Fehlerbericht zu posten. Sie werden sich dieses Problem höchstwahrscheinlich innerhalb weniger Wochen ansehen, und Sie können wahrscheinlich erwarten, dass es in der nächsten Nebenversion von Ruby korrigiert wird. (Das heißt, es sei denn, es gibt eine Entwurfslogik, die uns unbekannt ist, um die Dinge so zu halten, wie sie sind.)
Versuchen Sie:
%Vor% map
dekonstruiert automatisch die an ihn übergebenen Werte. Die nächste Frage ist warum diese Dekonstruktion durchführt und select
nicht?
Wenn Sie sich die Quelle auf der Rdoc-Seite von Array ansehen , Re praktisch identisch, select
unterscheidet sich nur dadurch, dass es einen Test auf den erzielten Wert durchführt. Irgendwo muss etwas passieren.
Wenn wir uns die Rubinius-Quelle ansehen (hauptsächlich weil ich bin besser mit Ruby als C;) für map
(aliased von collect
) zeigt es uns:
Damit werden die Argumente auf dem Weg durchgespielt, während ausgewählt wird > (Alias von find_all
) nicht:
Noch einmal, die Designentscheidung bezüglich warum liegt jenseits meiner. Sie müssen herausfinden, wer es geschrieben hat, vielleicht fragen Sie Matz:)
Ich sollte hinzufügen, schauen Sie sich die Rubinius Quelle wieder an, map
actual splats auf each
und auf yield
, ich verstehe nicht, warum Sie beides tun würden, wenn nur die yield splat wird benötigt:
wobei select
nicht.
Laut der MRI-Quelle scheint es, als ob der Iterator in select
splats verwendet wurde seine Argumente kommen herein, aber map
nicht und übergibt sie unverpackt; Der Block im letzten Fall ignoriert die anderen Argumente stillschweigend.
Der in select
verwendete Iterator:
Der in map
verwendete Iterator:
Ich bin ziemlich sicher, dass das Makro ENUM_WANT_SVALUE()
verwendet wird, um den in den Block übergebenen Wert in einen Splat-Array-Wert umzuwandeln (im Gegensatz zu einem Tupel mit den letzteren Argumenten, die stillschweigend ignoriert werden). Das heißt, ich weiß nicht, warum es so entworfen wurde.
Sehen wir uns die MRT-Quelle in enum.c an. Wie @PlatinumAzure sagte, passiert die Magie in ENUM_WANT_SVALUE()
:
Und wir können dieses Makro tatsächlich finden: do {i = rb_enum_values_pack(argc, argv);}while(0)
.
Also gehen wir weiter in rb_enum_values_pack
function:
Siehe? Die Argumente werden von rb_ary_new4
gepackt, das in array.c .
Tags und Links ruby block enumerators