Interrogazione delle informazioni di R

In alcuni casi, si potrebbe voler recuperare ulteriori informazioni da R, da presentare nell'interfaccia utente dell'estensione. Ad esempio, si potrebbe voler offrire una selezione dei livelli di un fattore che l'utente ha selezionato per l'analisi. Dalla versione 0.6.2 di RKWard è possibile farlo. Prima di iniziare, è importante essere a conoscenza di alcuni avvertimenti:

Il codice R eseguito dall'interno della logica dell'interfaccia utente dell'estensione viene valutato nel ciclo di eventi di R, il che significa che può essere eseguito mentre sono in esecuzione altri calcoli. Questo serve a garantire che l'interfaccia utente dell'estensione sia utilizzabile anche mentre R è impegnato in altre attività. Tuttavia, è fondamentale che il codice non abbia effetti collaterali. In particolare:

  • Non fare alcuna assegnazione .GlobalEnv o in qualsiasi altro ambiente non locale.

  • Non stampare nulla sul file di uscita.

  • Non tracciare nulla sullo schermo.

  • In generale, non fare qualcosa che abbia effetti collaterali. Il proprio codice può leggere informazioni, non «fare» qualsiasi cosa.

Con questo in mente, ecco lo schema generale. Lo si utilizzerà all'interno di una sezione logica dell'interfaccia utente programmabile:

<script><![CDATA[
                                let update = gui.addChangeCommand ("variable", function () {
                                        gui.setValue ("selector.enabled", 0);
                                        variable = gui.getValue ("variable");
                                        if (variable == "") return;

                                        new RCommand('levels (' + variable + ')', "myid").then(result =
> {
                                                gui.setValue ("selector.enabled", 1);
                                                gui.setListValue ("selector.available", result);
                                        }).catch(msg =
> {
                                                if (msg === "outdated") return;  // il comando è stato annullato, perché ne sta per arrivare uno nuovo -> benign
                                                // possibilmente altra gestione degli errori, msg contiene gli avvisi e i messaggi di errore generati,
                                                // se il comando non è andato a buon fine ad es.:
                                                gui.setListValue ("selector.available", Array ("ERROR:", msg));
                                        });
                                });
                ]]></script>
        

Qui, variable è una proprietà che contiene un nome di oggetto (ad es. all'interno di un <varslot>). Ogni volta che ciò cambia, vorrete aggiornare la visualizzazione dei livelli all'interno del <valueselector>, chiamato selector. La funzione chiave qui è l'istruzione del costruttore new RCommand(), che prende come primo parametro la stringa di comando da eseguire. Tenere presente che il comando viene eseguito in modo asincrono e questo rende le cose un po' più complesse. Per prima cosa assicurarsi che il <valueselector> rimanga disabilitato, mentre non contiene informazioni aggiornate. In secondo luogo, poiché l'utente può apportare modifiche rapidamente, è possibile che venga generato più di un comando prima di ricevere qualsiasi risultato. Pertanto, dovrete assicurarvi di agire solo sul comando più recente.

Per gestire l'asincronia, ciò che viene restituito, qui, è un oggetto Promise. Maggiori informazioni su questa potente funzionalità JavaScript possono essere trovate su Internet. La cosa importante da sapere, qui, è che l'aggiunta di un'istruzione .then() consente di specificare cosa accadrà al termine del comando e che un'istruzione .catch() può essere utilizzata per gestire eventuali errori. Ancora una volta, tenere presente che il blocco .then() non viene eseguito immediatamente. Per comprenderne le implicazioni, potrebbe essere utile, durante lo sviluppo, inserire un Sys.sleep(1); nel comando R, per vedere cosa succede, quando un comando non viene completato, immediatamente.

Infine, per gestire la generazione di più comandi, è possibile specificare un secondo argomento per new RCommand(), ("myid", in questo esempio). Tutti i comandi con lo stesso identificatore (scelto liberamente) saranno considerati appartenenti alla stessa coda. RKWard si assicurerà quindi che solo il comando più recente attiverà effettivamente il blocco .then(), mentre eventuali comandi obsoleti arriveranno nel blocco .catch(). Qui è possibile identificare i comandi obsoleti, poiché come valore viene passata la stringa "obsoleto", mentre per eventuali altri possibili errori vengono passati gli avvisi e i messaggi di errore.

Notare che questo esempio è in qualche modo semplificato. In realtà dovreste prendere ulteriori precauzioni, ad es. per evitare di inserire un numero eccessivo di livelli nel selettore. La buona notizia è che probabilmente non dovete fare tutto questo da soli. L'esempio sopra è preso dall'estensione rkward::level_select, ad esempio, che potete semplicemente incorporare nella vostra estensione. Ciò vi consente anche di specificare un'espressione diversa da eseguire al posto di levels().

Nota

Nelle versioni precedenti di RKWard, i comandi R venivano eseguiti utilizzando una funzione doRCommand() leggermente più complessa. Questa funzione potrebbe essere ancora presente in alcune estensioni, ma non è consigliabile utilizzarla nel nuovo codice.