2016-12-20 1 views
8

Dir.glob("*.txt") {|f| p f} imprime les noms de fichiers.Pourquoi Dir.glob ("*. Txt"). Sort a-t-il besoin de .each?

Dir.glob("*.txt").sort {|f| p f} échoue avec une ArgumentError.

Dir.glob("*.txt").sort.each {|f| p f} Imprime les noms de fichiers dans l'ordre alphabétique.

Pourquoi le second échoue-t-il? Mieux encore, pourquoi le premier fonctionne-t-il, avec ou sans le .each?

  • Dir.glob et Dir.glob.sort sont les deux tableaux.
  • .

(Inspirés par le Alphabetize results of Dir.glob. Pas un double de Dir.glob with sort issue parce que le « troisième » répond déjà que sa question.)

+0

Copie possible de [Dir.glob avec problème de tri] (http://stackoverflow.com/questions/29733611/dir-glob-with-sort-issue) –

Répondre

4

L'autre réponse est correcte, mais je pense qu'il ya une explication plus profonde. Lorsque vous avez un bloc après un appel de méthode, comme Dir.glob("*.txt") {|f| p f}, le bloc est un argument (facultatif) de la méthode. Dans la définition de Dir.glob, il existe une instruction yield qui exécute le bloc.

Lorsque vous enchaînez les méthodes, comme dans Dir.glob("*.txt").sort {|f| p f}, le bloc devient un argument de la méthode sort au lieu de la méthode glob. sort peut également prendre un bloc pour définir une comparaison, mais ce bloc n'a pas de sens dans ce contexte.

Chaînage each pour obtenir Dir.glob("*.txt").sort.each {|f| p f} fait bloc un argument à la méthode each, qu'il utilise comme glob ne (en cours d'exécution du bloc pour chaque argument).

+1

C'est donc une simple coïncidence que 'Dir.glob.each' et' Dir.glob' acceptent le même type de bloc. C'est "pourquoi" 'Dir.glob {}' fonctionne, avec ou sans '.each'. Merci! –

+0

@CamilleGoudeseune '.each' a une valeur de retour de l'objet passé ainsi tout ce qu'il fait retourne la réponse reçue de' glob'. La seule fois où cela n'est pas vrai, c'est si vous utilisez des méthodes de mutation dans 'each' – engineersmnky

5

Le second échoue parce que sort {|f| p f} n'a vraiment pas de sens. Le bloc que vous utilisez avec sort est supposé "return -1, 0, or +1" et prend deux arguments (les éléments à comparer) mais votre bloc prend un argument et renvoie cet argument car p str renvoie str.

Le troisième est très bien parce que le bloc comparateur par défaut de sort équivaut à dire:

sort { |a, b| a <=> b } 

si .sort.each est parfaitement logique.

Si vous utilisez le type de bloc qui sort dans le second attend par exemple:

Dir.glob("*.txt").sort {|a, b| a <=> b } 

alors les choses fonctionnent mieux. Ou vous pouvez simplement laisser le bloc si vous voulez les choses de tri par ordre croissant lexical:

Dir.glob('*.txt').sort 
+0

Est-ce que 'sort_by' fonctionne dans 1.9.3? –

+1

@ sagarpandya82 Apparemment [it] (http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-sort_by) mais je pense que c'est une distraction à moins que l'OP ne soit déroutant 'sort '(avec un bloc à deux arguments) et' sort_by' (avec un bloc à un argument). –

+0

Aha. Donc, sort {} signifie quelque chose de différent de .each's {} ou .glob's {}. Pourtant, pourquoi l'asymétrie: pourquoi pas .glob a également besoin d'un. (Est-ce même une question significative?) –