1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    août 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : août 2013
    Messages : 7
    Points : 10
    Points
    10

    Par défaut Variables locales aux fonctions

    Bonjour,

    Étant donné que, dans R, il n'y a pas de déclaration de variable, est-il possible d'avoir une variable locale à une fonction ayant le même nom qu'une variable globale? J'imagine que non, à moins que les variables globales ne soient pas visibles depuis les fonctions (mais ça limite l'intérêt des variables globales).

    a <- 32

    integer toto <- function (integer ref x, integer val y, integer z)
    a <- x+y // a est nécessairement la variable globale a
    return z
    endFunction



    Ça me semble être très problématique: lorsqu'on définit une fonction on ne connais pas les variable globales existantes lors de l'appel à cette fonction. Du coup les variables locales peuvent entrer en conflit avec les globales.

    Comment ce problème est-il géré en R?
    Comment veut-on le gérer en R++?
    P.

  2. #2
    Membre éclairé

    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    septembre 2007
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Santé

    Informations forums :
    Inscription : septembre 2007
    Messages : 200
    Points : 714
    Points
    714

    Par défaut

    Dans R, tu peux avoir des variables globales. Elles sont accessibles depuis les fonctions.

    Par contre, si tu déclares localement une variable qui existe globalement, alors tu n'as plus accès à la variable globale, tu as juste (localement) accès à la locale. Je crois qu'il existe une manière particulièrement crade d'avoir malgré tout accès à la variable globale, mais je ne suis pas sûr.

    Si je m'écoutais, dans R++, j'interdirais l'accès aux variables globales... Ca ne pose pas vraiment de problème puisqu'on a le droit de passer des variables par référence. Donc, tout ce dont une fonction a besoin, on lui donne comme argument. Non ?

  3. #3
    Membre à l'essai
    Homme Profil pro
    IE collecte et analyse de données
    Inscrit en
    septembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : IE collecte et analyse de données

    Informations forums :
    Inscription : septembre 2013
    Messages : 6
    Points : 14
    Points
    14

    Par défaut

    R définit la portée des variables selon le principe du lexical scoping. Concrètement, cela signifie que si une fonction f() appelle une fonction g(), les variables déclarées dans f() seront accessibles en lecture (mais pas en écriture) depuis g(). Par contre, l'inverse n'est pas vrai (ce qui est possible dans certains langage dont S je crois - à vérifier).
    Cela vaut aussi lorsque f() est l'environnement global (.GlobalEnv).

    En cela, R suit le paradigme fonctionnel. Les fonctions sont des closures et les symboles peuvent être "liés" (-ie: associés à une valeur dans le contexte de la fonction) ou "libres". Pour ces dernières, les valeurs vont être recherchées dans la copie de l'environnement de la fonction appellante.

    Les variables définies dans f() peuvent être accessibles en écriture via un environnement.

    Par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    ##
    rho <- new.env()
    ##
    x <- 1
    ##
    f <- function(rho){
      ##
      rho$x <- x+1
      ##
      print(rho$x)
      ##
      x <- 0
      ##
      cat( "Valeur de x dans f():", x , "\n")
      ##
      x
    }
    ## retourne 2 : x a été modifiée dans f()...
    f(rho)
    ##...mais pas dans .GlobalEnv
    x
    ## Par contre, la variable x de rho a bien été mise à jour
    rho$x
    
    ##
    ## Même chose mais en utilisant l'environnement global
    ##
    
    ##
    rho <- environment()
    ## retourne toujours 0 mais...
    f(rho)
    ## ...cette fois, x a été directement mise à jour dans .GlobalEnv
    x
    Thomas

  4. #4
    Membre à l'essai
    Homme Profil pro
    IE collecte et analyse de données
    Inscrit en
    septembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : IE collecte et analyse de données

    Informations forums :
    Inscription : septembre 2013
    Messages : 6
    Points : 14
    Points
    14

    Par défaut

    Citation Envoyé par Christophe Genolini Voir le message
    Si je m'écoutais, dans R++, j'interdirais l'accès aux variables globales... Ca ne pose pas vraiment de problème puisqu'on a le droit de passer des variables par référence. Donc, tout ce dont une fonction a besoin, on lui donne comme argument. Non ?
    On peut de plus penser les classes constistuent une sorte d'environnement acessible en lecture-écriture et peuvent s'y substituer, au moins partiellement.

    L'avantage de ce genre de méchanisme est cependant de ne pas avoir à multiplier les arguments (il ne faut pas oublier qu'un environnement est constitué de beaucoup plus de chose que les seuls symboles déclarés par l'utilisateur dans le cadre de sa session). Beaucoup d'informations sont transmises via ce biais.

    Mais je suis d'accord. La façon dont cela fonctionne sous R me semble problèmatique (l'accès à des variables non-locales m'a fait perdre plusieurs heures de ma vie en débœugage).

    Plutôt que d'interdire, pourquoi ne pas plutôt donner le choix ? On pourrait par exemple reprendre la syntaxe de R mais en inversant les choses. Par défaut, les variables n'auraient qu'une portée locale SAUF si l'utilisateur le requière explicitement. Et à l'exception de certaines variables d'environnement.

    Par exemple, toutes les fonctions pourraient avoir un argument réservé "rho" (ou "env" ou autre) qui permettrait de paramètrer l'environnement de la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ## Crée une copie de l'environnement courant en lecture seule
    rho <- new("env", include = "all")
    ##
    f(<fun-args>, rho = rho)
    
    ## Crée un environnement vide
    rho <- new("env")  ## -ie: exclude = "all"
    ## Peuplement
    rho@a <- ...
    
    ## Copie partielle de l'environnement courant en autorisant l'accès en écriture pour tous les symboles
    rho <- new("env", include = c(...), mutable = TRUE )
    ## Copie partielle de l'environnement courant en autorisant l'accès en écriture pour certains symboles
    rho <- new("env", include = c(...), mutable = c(TRUE, TRUE, FALSE...) )
    Pour ce qui est du passage de références ou de valeurs, plusieurs cas de figure pourraient être envisageables.

    Par exemple, si l'environnement est en lecture seule, pas besoin de copier. Mais passer une référence n'est pas suffisant. La fonction peut être appelée plusieurs fois avec le même environnement et l'environnement pourrait être modifié par la fonction appellante entre-temps ou modifiée par d'autres fonctions appellée par celle-ci. Ce qui, en fonction des situations, peut être souhaitable ou doit être proscrit.

    Le problème se pose de façon accrue dans le cas d'une application parallélisée.

    Comme je l'ai déjà noté précédemment, des méchanismes de copie en écriture pourraient constituer une solution au moins partielle. L'utilisateur (ou l'application, le package...) pourrait décider si l'environnement copié est mutable. Si oui, les variables pourraient être partagées entre plusieurs threads, ce qui leurs permettrait de communiquer. Dans le cas contraire, l'application opèrerait une copie locale de ce qui a été modifié par un autre thread et leurs espaces mémoires seraient étanches.

    Thomas

Discussions similaires

  1. [OpenMP] variable locales et fonctions récursives
    Par Babcool dans le forum Programmation parallèle, calcul scientifique et de haute performance (HPC)
    Réponses: 0
    Dernier message: 14/09/2010, 15h58
  2. Réutilisation de variable Locale dans fonction differente
    Par Luke spywoker dans le forum Général Python
    Réponses: 4
    Dernier message: 09/07/2010, 10h13
  3. Variable locale à une fonction.
    Par MoiRemi dans le forum PL/SQL
    Réponses: 7
    Dernier message: 04/02/2009, 18h05
  4. [NASM] Variables locales à une fonction
    Par Rémiz dans le forum x86 16-bits
    Réponses: 2
    Dernier message: 13/11/2008, 11h33
  5. Réponses: 5
    Dernier message: 19/09/2005, 21h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo