Consultando o R para obter informações

Em alguns casos, você pode querer obter mais informações do R para serem apresentadas na interface do usuário do seu plugin. Por exemplo, você pode querer oferecer uma seleção dos níveis de um fator que o usuário selecionou para análise. Desde a versão 0.6.2 do RKWard, isso é possível. Antes de começarmos, é importante que você esteja ciente de algumas ressalvas:

O código R executado dentro da lógica da interface do usuário do plugin é avaliado no loop de eventos do R, o que significa que ele pode ser executado enquanto outros cálculos estão em andamento. Isso garante que a interface do usuário do seu plugin seja utilizável, mesmo enquanto o R estiver ocupado realizando outras tarefas. No entanto, isso torna muito importante que seu código não tenha efeitos colaterais. Em particular:

  • Não faça nenhuma atribuição em .GlobalEnv ou qualquer outro ambiente não local.

  • Não imprima nada no arquivo de saída.

  • Não plote nada na tela.

  • Em geral, não faça nada que tenha efeitos colaterais. Seu código pode ler informações, mas não "fazer" nada.

Com isso em mente, aqui está o padrão geral. Você usará isso dentro de uma seção de lógica de interface do usuário com o script scripted UI logic:

<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;  // comando foi cancelado, pois um novo está prestes a chegar ->benigno
                                                // possivelmente outros erros de tratamento, msg carrega os avisos e mensagens de erro produzidos,
                                                // se o comando falhou porexemplo:
                                                gui.setListValue ("selector.available", Array ("ERROR:", msg));
                                        });
                                });
                ]]></script>
        

Aqui, variable é uma propriedade que contém o nome de um objeto (por exemplo, dentro de um <varslot>). Sempre que isso mudar, você precisará atualizar a exibição dos níveis dentro do <valueselector>, chamado selector. A função chave aqui é a instrução construtora new RCommand(), que recebe como primeiro parâmetro a string de comando a ser executada. Observe que o comando é executado de forma assíncrona, o que torna as coisas um pouco mais complexas. Por um lado, você precisa garantir que seu <valueselector> permaneça desabilitado enquanto não contiver informações atualizadas. Em segundo lugar, como o usuário pode fazer alterações rapidamente, mais de um comando pode ter sido gerado antes de recebermos qualquer resultado. Portanto, você precisará garantir que execute apenas o comando mais recente.

Para lidar com a assincronia, o que é retornado aqui é um objeto Promise. Mais informações sobre esse poderoso recurso do JavaScript podem ser encontradas na internet. O importante a saber aqui é que adicionar uma instrução .then() permite especificar o que acontecerá quando o comando for concluído, e uma instrução .catch() pode ser usada para lidar com quaisquer erros. Novamente, lembre-se de que o bloco .then() não é executado imediatamente. Para entender as implicações disso, pode ser útil, durante o desenvolvimento, inserir um Sys.sleep(1); em seu comando R, para ver o que acontece, quando um comando não é concluído imediatamente.

Finalmente, para lidar com a geração de múltiplos comandos, você pode especificar um segundo argumento para new RCommand(), ("myid", neste exemplo). Quaisquer comandos com o mesmo identificador (escolhido livremente) serão entendidos como pertencentes à mesma fila. O RKWard garantirá então que apenas o comando mais recente acione o bloco .then() enquanto quaisquer comandos obsoletos chegarão no bloco .catch(). Aqui, os comandos obsoletos podem ser identificados, pois a string "outdated" é passada como seu valor, enquanto para quaisquer outros erros possíveis, os avisos e mensagens de erro são repassados.

Note que este exemplo é um tanto simplificado. Na realidade, você deve tomar precauções adicionais, por exemplo, para evitar colocar uma quantidade excessiva de níveis no seletor. A boa notícia é que provavelmente você não precisa fazer tudo isso sozinho. O exemplo acima foi retirado do plugin rkward::level_select, por exemplo, que você pode simplesmente incorporar em seu próprio plugin. Isso permite até mesmo que você especifique uma expressão diferente para executar no lugar de levels().

Nota

Em versões anteriores do RKWard, os comandos R eram executados usando uma função um pouco mais complexa: doRCommand(). Você ainda pode encontrar isso em alguns plugins, mas não é recomendável usá-la em novos códigos.