Forum Programmation.ruby Accéder à une variable par son nom

Posté par (page perso) .
Tags : aucun
0
10
juil.
2008
Je n'arrive plus à retrouver comment on utilise une chaîne de caractère pour l'utiliser comme nom de variable. J'explique avec un morceau de code:


var1 = 123
var2 = "abc"
var3 = nil
%w{ var1 var2 var3 }.each { |nom| puts nom.type }

Ca me donne trois fois "string", ce qui est logique dans le cas présent. Ce que je souhaite avoir c'est "fixnum, string, nil". Mais je ne retrouve pas comment transformer une chaîne en "nom de variable".
  • # une solution

    Posté par (page perso) . Évalué à 2.

    Bonjour,
    Je ne sais pas si ça repond vraiment au probleme, mais voici quand meme :

    class Test
    attr_accessor :var1, :var2, :var3
    def initialize
    @var1 = 32
    @var2 = "hello"
    @var3 = nil
    end
    end

    object = Test.new

    %w{ @var1 @var2 @var3 }.each do |name|
    puts object.instance_variable_get(name).class
    end

    $ ruby test.rb
    Fixnum
    String
    NilClass

    • [^] # Re: une solution

      Posté par (page perso) . Évalué à 2.

      Merci pour l'info, mais ça ne résouds effectivement pas mon problème. Mon but n'est bien entendu pas d'afficher le type de données, mais de faire des traitements. Bref, d'utiliser "en vrai" les variables en question.
  • # avec eval ... comme en php

    Posté par . Évalué à 1.

    var1 = 123
    var2 = "abc"
    var3 = nil
    %w{ var1 var2 var3 }.each { |nom| eval("puts #{nom}.class") }

    ou
    %w{ var1 var2 var3 }.each { |nom| eval("puts #{nom}.type") }
  • # Plus de précisions

    Posté par (page perso) . Évalué à 2.

    Je donne un autre exemple.


    var1 = 123
    var2 = 456
    var3 = 789
    i=0
    %w{ var1 var2 var3 }.each { |nom| i=i+nom }
    puts i


    La méthode avec i = i + eval("puts #{nom}.class") fonctionne. Je recherche cependant quelque chose de plus propre :-) La documentation Ruby étant... étant ce qu'elle est, je n'arrive pas à retrouver l'opérateur ou la classe qui permet d'obtenir la meme chose, mais plus dans les standards Ruby.
  • # intern

    Posté par (page perso) . Évalué à 1.

    Ca y est, j'ai retrouvé ce que je cherchais: c'est String#intern :-)

    Malheureusement, ça ne fonctionne pas. Je me trompe probablement quelque part. Quelqu'un sait où est mon erreur ?


    var1 = "abc"
    puts "var1".intern.class
    puts "var1".intern

    Ca affiche "Symbol" puis "var1" alors que je pensais que ça afficherait "Symbol" puis "abc".
    • [^] # Re: intern

      Posté par . Évalué à 3.

      Intern permet de convertir une chaîne en symbole. C'est instance_variable_get(String) qui répond à ta demande. Cependant cette méthode ne peut récupérer que les variables d'instances.
      • [^] # Re: intern

        Posté par (page perso) . Évalué à 2.

        J'avais bien compris cela. Mais je n'ai alors donc pas compris ce qu'est un symbole. Je pensais que var1 par exemple est un symbole. Donc "var1".intern serait la même chose. J'ai tout faux.
        Je vais me rabattre sur eval. C'est moche mais ça fonctionne.
  • # Et pourquoi pas...

    Posté par . Évalué à 2.

    En profitant du fait que tout soit object en ruby et en utilisant des variables d'instances:


    @a, @b, @c = 42, '42', [42]
    => [42,'42',[42]]

    %w/a b c/.map {|var| instance_variable_get("@"+var).class }
    => [Fixnum, String, Array]


    Mais je ne sais pas si c'est bien conseillé.
    • [^] # Re: Et pourquoi pas...

      Posté par . Évalué à 2.

      Donc tout est objet, mais il y a des variables d'instances et d'autres pas d'instances ? D'ailleurs à quel objet sont elles (chacune des 2) rattachées (vu leur contexte globale) ?
      • [^] # Re: Et pourquoi pas...

        Posté par . Évalué à 1.

        En ruby, il existe 4 types de variables:
        - variable local (var)
        - variable global ($var)
        - variable d'instance (@var)
        - variable de classe (@@var)

        Dans l'exemple au-dessus, j'utilise des variables d'instance qui sont rattachées à l'objet spécial "main" qui correspond au contexte d'exécution du programme. Ça revient au même que l'exemple de castorpilot mais dans son cas, le contexte est explicite (la classe Test).

        J'avoue que ma méthode n'est pas très propre. ^^

        Sinon, la différence entre variable d'instance et variable local, c'est leur portée.
        Un exemple:


        self #=> 'main'
        @a = 'foo' # variable d'instance de l'objet spécial 'main'
        a = 'bar' # variable local

        def foo
        puts @a
        puts a rescue "variable non défini"
        end

        foo

        #=> foo
        #=> variable non défini


        PS: Je ne suis pas programmeur, je fais du ruby par 'plaisir'. Donc il se peut que ces informations soit imprécises voir carrément fausses. Toutes mes excuses si c'est le cas et toutes corrections et/ou informations supplémentaires sont les bienvenus.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.