2011-12-30 3 views
3

Il est facile d'avoir une condition à la tête d'une chaîne et partager le reste:État au milieu ou à la queue d'une chaîne

if condition 
    get_this 
else 
    get_that 
end 
.foo.bar.baz 

Mais souvent, je veux une condition au milieu ou à la queue d'une chaîne. Le mieux que je peux penser est d'utiliser instance_eval:

foo.bar 
.instance_eval{ 
    if condition 
     get_this 
    else 
     get_that 
    end 
} 
.baz 

Mais je me inquiète que l'appel instance_eval est lourd, donc je finis réellement ne pas le faire. Cela vaut-il la peine de le faire? Y at-il une meilleure façon, ou devrais-je écrire tout simplement:

if condition 
    foo.bar.get_this 
else 
    foo.bar.get_that 
end 
.baz 
+0

+1 pour la syntaxe dans le premier extrait. –

+0

@AndrewGrimm Merci pour le commentaire, mais qu'entendez-vous par "premier extrait"? – sawa

+0

Un extrait est un petit morceau de code. Je fais référence à la condition 'if condition ... .foo.bar.baz'. Snippet un diminutif de "snip", selon [wiktionary] (http://en.wiktionary.org/wiki/snippet). "Snip" lui-même est probablement une onomatopée, qui en japonais est apparemment チ ョ キ チ ョ キ. –

Répondre

3

Pourquoi ne pas fournir une méthode sur bar qui accepte une valeur booléenne et e en actes en conséquence? Cela encapsule la logique et peut même protéger une logique complexe ou des conditions multiples, sans devenir trop salissant.

class Bar 
    def get_what(condition) 
    case condition 
     when qux; get_this(param1) 
     when quux; get_that(param1, param2) 
     else get_other(param1) 
    end 
    end 
end 

# assuming `bar` is an instance of `Bar` 
foo.bar.get_what(cond).baz 

PS: En fonction du cas d'utilisation, j'essaie souvent d'éviter des choses comme des chaînes de messages trop longs (car selon le Law of Demeter (Wikipedia) cela pourrait être considéré comme une mauvaise pratique :)), mais lorsque vous travaillez avec hash et des tableaux en rubis C'est plutôt utile. Donc, je suppose que vous avez un cas d'utilisation valide pour utiliser une longue chaîne de messages.

3

Comment l'utilisation Object#send appeler conditionnellement une méthode:

foo.bar.send(condition? ? :get_this : :get_that).baz 

Dans un cas plus complexe, avec de multiples/différents paramètres, on pourrait utiliser le splat operator pour déballer un tableau dans les paramètres:

foo.bar.send(
    * case conditional 
    when qux 
     [:get_this, param1] 
    when quux 
     [:get_that, param1, param2] 
    else 
     [:get_other, param1, param2] 
    end 
).baz 
+0

Je vois. Cela résout partiellement le problème, c'est-à-dire, lorsque 'get_this' et' get_that' sont des méthodes simplistes (éventuellement avec des arguments). Pouvez-vous également penser à un moyen quand ils sont plus compliqués? Votre réponse est une bonne idée, cependant. – sawa

+0

Voir les réponses montées – clyfe

+0

Ouais. C'est ce que j'ai mentionné comme méthode simpliste (unique). Mais parfois, il y a des séquences de choses à faire séparément dans des conditions différentes. Mais, ta réponse est belle. – sawa

2

Parfois, une solution low-tech est le meilleur:

my_bar = foo.bar 
if condition 
    my_thing = my_bar.get_this 
else 
    my_thing = my_bar.get_that 
end 
my_thing.baz 

Sérieusement, je considère beaucoup plus important que le sens du code source est 100% clair pour tout le monde (y compris vous un peu de temps à l'avenir) qu'il est raccourci par une ligne ou deux.

+1

c'est ok, mais je pense que c'est plus idiomatique 'my_thing = if condition ...' – tokland

+0

Peut-être 'my_thing = (condition? ...: ...)'. Personnellement, il n'y a aucun moyen que j'utilise jamais la valeur d'un «si», même si techniquement c'est une expression. – Lindydancer

+0

Dans certains cas, je pense que je dois le faire. – sawa

Questions connexes