Environnements #1

Un bon artisan range son établi et n’y laisse jamais — Ô grand jamais — trainer ses outils. C’est à ça que servent les tiroirs en dessous : à ranger des outils et même, éventuellement, un peu de matière première.

R fonctionne comme ça.

La surface de votre établi s’appelle .GlobalEnv ou, plus communément, espace de travail.

Pour inspecter la surface de .GlobalEnv et lister les objets qui se trouvent dessus (outils ou autres) vous utilisez la fonction ls sans argument ce qui revient, par défaut, à établir une liste des objets présents dans l’environnement dans lequel vous travaillez ; en l’occurrence, la surface de votre établi.

Lorsque vous démarrer une nouvelle cession — et à supposer que vous n’avez pas sauvegardé la cession précédents (ce qui signifie que vous avez sciemment laissé des trucs trainer sur votre établi depuis) — vous devriez obtenir :

> ls()
character(0)

Ce qui revient à dire :

> ls(.GlobalEnv)
character(0)

Bref, la surface de votre établi est absolument vide.

Commençons par y déposer un peu de matière première ; en l'espèce x et y, deux vecteurs numérique de longueur 1.

> y <- x <- 1
> x
[1] 1
> y
[1] 1

De telle sorte que :

> ls()
[1] "x" "y"

Sur ces deux objets, nous allons appeler la fonction c qui est notre tube de colle universelle :

> c(x, y)
[1] 1 1

À ce stade, vous pourriez vous demander d’où sort c puisque que ls ne l’a pas listée parmi les objets présents à la surface de notre établi. C’est une excellente question que vous auriez d’ailleurs pu vous poser pour ls aussi.

La réponse est très simple : vous avez trouvé ces deux outils dans un des tiroirs de votre établi. En l’occurrence l’avant dernier, celui sur lequel il est écrit : .BaseNamespaceEnv.

Voilà comment ça fonctionne : à chaque fois que vous avez besoin de votre tube de colle (la fonction c), vous commencez par chercher quelque chose qui porte l’étiquette c (et qui soit un outil, on y reviendra) à la surface de votre établi (.GlobalEnv). Si vous trouvez un outil étiqueté c sur .GlobalEnv, vous utilisez celui-là mais dans le cas contraire, vous cherchez dans le premier de vos tiroirs puis, dans le second, le troisième… jusqu’à ce que vous trouviez un outil (un objet de classe function) étiqueté c.

Normalement, la fonction c se trouve dans l’avant dernier tiroir — celui où il est écrit .BaseNamespaceEnv et qui contient tous vos outils de base — sachant que le dernier tiroir et toujours vide.

Illustrons ça avec un exemple :

Soit une nouvelle fonction c définie comme :

c <- function(...) {
      a <- list(...)
      sum(unlist(a) * 10^((length(a)-1):0))
}

Cette fonction est définie sur .GlobalEnv de telle sorte que quand vous appellerez c, c'est elle que vous utiliserez par défaut :

> c(1, 1)
[1] 11

Mais si vous souhaitez ponctuellement utiliser la fonction c qui se trouve dans .BaseNamespaceEnv (l'avant-dernier tiroir), vous pouvez le faire en écrivant :

> base::c(1, 1)
[1] 1 1

Dans R, la surface de votre établi et chacun de ses tiroirs est un objet de classe environment :

> class(.GlobalEnv)
[1] "environment"
> class(.BaseNamespaceEnv)
[1] "environment"

Si vous souhaitez lister les objets présents dans .BaseNamespaceEnv (toutes les fonctions du package base de R) :

ls(.BaseNamespaceEnv)

Ou :

ls(baseenv())

(C'est un gros tiroir...)

Si vous souhaitez savoir dans quel ordre R cherche dans ses tiroirs :

> search()
 [1] ".GlobalEnv"        "package:rgl"       "package:stats"    
 [4] "package:graphics"  "package:grDevices" "package:utils"    
 [7] "package:datasets"  "package:methods"   "Autoloads"        
[10] "package:base"

Comme spécifié ci-dessus, R va d'abord chercher c dans .GlobalEnv, puis dans package:rgl, puis dans package:stats ... jusqu'à package:base mais pas dans le dernier tiroir (emptyenv()) puisqu'il est toujours vide. En l'occurrence, comme vous avez créé une fonction c dans .GlobalEnv, il utilise celle-là.

Mais si vous la détruisez :

> rm(list = "c")
> c(1, 1)
[1] 1 1

C'est la fonction c de package:base qui reprend le dessus.

Lorsque vous exécutez :

> diff
function (x, ...) 
UseMethod("diff")
<bytecode: 0x07279760>
<environment: namespace:base>

La ligne <environment: namespace:base> vous signale que diff se trouve dans l'environnement de base (a.k.a. avant-dernier tiroir).

Deux petites précisions à ce stade :

Primo, R gère séparément les fonctions et les autres objets de telle sorte que vous pouvez, par exemple, appeler la fonction diff (base::diff) sur un objet diff créé dans votre espace de travail :

> diff <- seq(0, 10, 2)
> diff(diff)
[1] 2 2 2 2 2

Deuxio, ls() ne liste pas vraiment tous les objets en mémoire :

> rm(list=ls())
> x <- 1
> .coucou <- 2
> ls()
[1] "x"
> rm(list = ls())
> .coucou
[1] 2

Dans ce cas, utilisez plutôt :

> ls(all = TRUE)
[1] ".coucou"      ".Random.seed"

(Un petit >?.Random.seed répondra à vos questions.)

Bien. Maintenant que vous savez que votre espace de travail est un environnement, qu'il y a des tiroirs en dessous, que ces tiroirs s'appellent sont aussi des environnements et que R cherche les objets que vous utilisez dans vos tiroirs en suivant un ordre prédéfinis, nous allons créer des boîtes au-dessus de .GlobalEnv ; boîtes qui seront aussi des environnements ; suivez le guide...

Aucun commentaire:

Enregistrer un commentaire