2015-10-28 1 views
0

(Le titre est probablement tout à fait mal, mais je ne sais pas comment le décrire mieux)Paramétrage d'attributs d'un objet qui a été créé dans une fonction

J'ai un objet (riche) qui est créé par un fonction. Cet objet a plusieurs attributs. Un attribut est une fonction qui devrait (entre autres) changer la valeur d'un autre attribut.

Voici un exemple minimal de ce que je veux faire:

rich_object <- list(1,2,3) 


attr(rich_object, "subset_function") <- function(i){ 
    attr(rich_object, "value_to_change") <<- attr(rich_object, "value_to_change")[1:i] 

} 

attr(rich_object, "value_to_change") <- 1:20 


attr(rich_object, "value_to_change") 

attr(rich_object, "subset_function")(10) 

attr(rich_object, "value_to_change") 

Cela fonctionne exactement comme je veux que cela fonctionne. (sauf que je dois utiliser le mauvais <<- opérateur)

Lorsque j'utilise le même code et l'envelopper dans une fonction pour générer l'objet, il ne fonctionne plus.

create_awesome_object <- function(a,b,c){ 

    awesome_object <- list(a,b,c) 

    value_to_change <- 1:20 

    attr(awesome_object, "subset_function") <- function(i){ 
    attr(awesome_object, "value_to_change") <<- attr(awesome_object, "value_to_change")[1:i] 

    } 

    attr(awesome_object, "value_to_change") <- value_to_change 

    awesome_object 

} 



rich_object_2 <- create_awesome_object(1,2,3) 

attr(rich_object_2, "value_to_change") 
attr(rich_object_2, "subset_function")(10) 
attr(rich_object_2, "value_to_change") 

serait génial si quelqu'un pouvait me pointer vers une solution (encore mieux si cela fonctionnerait sans <<-)

EDIT: Je sais que qu'il ya de meilleures façons de faire des trucs comme ça. Mais je dois travailler avec du code préexistant et le refactoring de l'ensemble du projet n'est actuellement pas possible.

+0

Vous souhaitez probablement créer un 'class'. Voici un tutoriel: http://adv-r.had.co.nz/OO-essentials.html (le lien semble vers le bas maintenant, mais je suis sûr qu'il reviendra ... également en miroir sur archive.org) – Frank

+0

@Frank: Je sais que cela ne devrait pas être fait comme ça. Malheureusement, cela fait partie d'un paquet plus grand et en raison de la rétrocompatibilité je dois m'en tenir à ces étranges fonctions d'attributs .... –

+1

@ ja-thomas Vraiment, vous devriez arrêter de raser ce yak (fonctions d'attributs) et commencer à raser le yak refactoring. Ne devrait pas être plus long et il sera moins sujette aux erreurs. – Tensibai

Répondre

0

Donc, je viens de me faire remarquer une solution de travail (il y avait déjà quelque chose de similaire dans le projet).

L'idée est de définir l'attribut value_to_change comme une fonction qui renvoie la valeur de l'environnement parent.

Ajout de la solution pour la cohérence.

create_awesome_object <- function(a,b,c){ 

    awesome_object <- list(a,b,c) 

    value_to_change <- 1:20 

    attr(awesome_object, "subset_function") <- function(i){ 
    value_to_change <<- attr(awesome_object, "value_to_change")()[1:i] 

    } 

    attr(awesome_object, "value_to_change") <- function() value_to_change 

    awesome_object 

} 



rich_object_2 <- create_awesome_object(1,2,3) 

attr(rich_object_2, "value_to_change")() 
attr(rich_object_2, "subset_function")(10) 
attr(rich_object_2, "value_to_change")() 

Merci pour vos suggestions.

1

Je pense qu'il ya un malentendu sur ce que fait <<- (d'où toutes ses mauvaises qualités).

<<- affecte dans l'environnement parent. Cela signifie que si vous êtes dans une fonction, elle l'affecte dans l'environnement global. Mais si vous êtes dans une fonction qui est dans une fonction, elle ne déplace qu'un seul environnement, ce qui serait l'environnement de la première fonction.

En tant que tel, si vous êtes vraiment attaché à ce formulaire (personnellement j'essaierais de l'éviter), vous pouvez passer à la fonction assign. Cela vous permet de déclarer dans quel environnement vous souhaitez effectuer l'assignation. Ainsi, vous pouvez définir votre fonction à affecter à l'environnement Global (via envir = .GlobalEnv), de sorte qu'elle sera toujours affectée à l'environnement Global, quelle que soit l'imbrication de votre fonction.

+0

Cela dépend aussi de si et où l'objet est déjà assigné. –

+0

Le problème étant que cette ligne 'attr (awesome_object," value_to_change ") << -' awesome_object n'est pas une référence à "l'instance", donc assigner globalement avec assign ne va pas aider à obtenir la valeur mise à jour dans 'rich_object_2' de toute façon . – Tensibai