R bevragen naar informatie

In enkele gevallen wilt u misschien verdere informatie uit R ophalen, die dan in de UI van uw plugin wordt weergegeven. U wilt, bijvoorbeeld, een selectie aanbieden van de levels van een factor die de gebruiker heeft geselecteerd voor analyse. Vanaf versie 0.6.2 van RKWard is dit mogelijk. Voordat we beginnen, is het belangrijk dat u op de hoogte bent van een aantal valkuilen:

R-code, die gestart wordt vanuit de logica van een UI van een plugin, wordt verwerkt tijdens de event loop van R, wat betekent dat die kunnen lopen terwijl andere berekeningen aan de gang zijn. Dit is om er zeker van te zijn, dat de UI van uw plugin bruikbaar is, ook al is R druk bezig met andere dingen. Maar, dit maakt het werkelijk belangrijk dat uw code geen bijeffecten heeft, in het bijzonder:

  • Maak geen toewijzingen (assignments) in .GlobalEnv of welke andere niet-lokale omgeving dan ook.

  • Stuur niets naar het uitvoerbestand.

  • Plot niets op het scherm.

  • Doe, in het algemeen, niets dat zij-effecten heeft. Uw code kan informatie inlezen, maar niets "doen".

Met dit in gedachten, is hier het algemene patroon. U gebruikt dit in een sectie van ge-scripte UI-logica:

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

                                        last_command_id = doRCommand ('levels (' + variabele + ')', "commandFinished");
                                }

                                commandFinished = function (result, id) {
                                        if (id != last_command_id) return;  // een ander antwoord is op komst
                                        als (typeof (result) == "undefined") {
                                                gui.setListValue ("selector.available", Array ("ERROR"));
                                                return;
                                        }
                                        gui.setValue ("selector.enabled", 1);
                                        gui.setListValue ("selector.available", result);
                                }
                ]]></script>
        

Hierin is, variabele een eigenschap met een objectnaam (bijv. in een <varslot>). Wanneer die verandert, wilt u het tonen van levels in de <valueselector>, met de naam selector bijwerken. De sleutelfunctie hier is doRCommand(), met als eerste parameter de opdracht welke string te starten, en als tweede parameter de naam van een aan te roepen functie, na de opdracht. Let erop dat de opdracht asynchroon wordt gedaan, wat de zaak wat complexer maakt. Ten eerste moet u er voor zorgen dat uw <valueselector> uit blijft staan, zolang het geen bijgewerkte informatie bevat. En verder kan het zijn dat er mogelijk meerdere opdrachten in een wachtrij staan, voordat u de eerste resultaten krijgt. Daarom krijgt elke opdracht een "id", die we opslaan in last_command_id voor een later gebruik.

Als de opdracht klaar is, wordt de daarin opgegeven functie aangeroepen (in dit geval dus commandFinished), met twee parameters: het antwoord zelf, en de id van bijbehorende opdracht. Het type van het antwoord is vergelijkbaar met dat in R, bijv. een numerieke array, als het antwoord numeriek (een getal) is. Het kan zelfs een list() in R zijn, maar in dit geval wordt het een JS Array() zonder namen.

Let erop dat zelfs dit voorbeeld een beetje eenvoudiger is gemaakt. In werkelijkheid moet u verdere voorzorgsmaatregelen treffen, bijv. het voorkomen van een extreem aantal levels in de selector. Het goede nieuws is dat u dit waarschijnlijk niet allemaal zelf moet doen. Bovenstaand voorbeeld komt uit de rkward::level_select-plugin, bijvoorbeeld, die u eenvoudig kunt inbedden in uw eigen plugin. U kunt zelfs een andere te starten expressie opgeven in plaats van levels().