Escrevendo código R robusto: namespaces, mascarando e usando o operador `::`

Versão curta

Para aqueles que não querem ler o meu "caso", esta é a essência:

Qual é a maneira recomendada de minimizar as chances de novos pacotes quebrarem o código existente, ou seja, de fazer o código que você escrevetão robusto quanto possível?

Qual é a maneira recomendada de fazer o melhor uso domecanismo de namespace quando

a) apenasusando pacotes contribuídos (digamos em apenas alguns R Analysis Project)?

b) com respeito aem desenvolvimento pacotes próprios?

Qual a melhor maneira de evitar conflitos com relação aaulas formais (na maioria das vezesClasses de Referência no meu caso) como não há sequer um mecanismo de namespace comparável ao:: para as aulas (AFAIU)?

A maneira como o universo R funciona

Isso é algo que está incomodando minha mente há cerca de dois anos, mas não sinto como se tivesse chegado a uma solução satisfatória. Além disso, sinto que está piorando.

Nós vemos um número cada vez maior de pacotes emCRAN, github, R-Forge e afins, o que é simplesmente fantástico.

Em um ambiente tão descentralizado, é natural que a base de código que compõe R (digamos quebase R econtribuiu R, por simplicidade) irá desviar de um estado ideal em relação à robustez: as pessoas seguem diferentes convenções, há S3, S4, S4 Classes de Referência, etc. As coisas não podem ser tão "alinhadas" como seriam se houvesse um "instância central de compensação"que as convenções aplicadas. Tudo bem.

O problema

Diante do exposto, pode ser muito difícil usar R para escrever código robusto. Nem tudo que você precisa estará na base R. Para determinados projetos, você acabará carregando alguns pacotes contribuídos.

IMHO, o maior problema a esse respeito é a maneira como o conceito de namespace é colocado em uso em R: R permite simplesmente escrever o nome de uma certa função / método sem exigir explicitamente seu namespace (ou seja,foo vs.namespace::foo).

Então, por uma questão de simplicidade, é o que todo mundo está fazendo. Mas dessa forma, confrontos de nomes, código quebrado e a necessidade de reescrever / refatorar seu código são apenas uma questão de tempo (ou do número de pacotes diferentes carregados).

Na melhor das hipóteses, vocêconhecer sobre quais funções existentes são mascaradas / sobrecarregadas por um pacote recém-adicionado. Na pior das hipóteses, você não terá nenhuma pista até o seu código quebrar.

Alguns exemplos:

tente carregarRMySQL eRSQLite ao mesmo tempo, eles não se dão muito bemAlém dissoRMongo sobrescreverá certas funções deRMySQLprevisão mascara muita coisa com respeito a funções relacionadas a ARIMAR.utils até mascara obase::parse rotina

(Não me lembro quais funções em particular estavam causando os problemas, mas estou disposta a procurar novamente se houver interesse)

Surpreendentemente, isso não parece incomodar muitos programadores por aí. Eu tentei aumentar o interesse algumas vezes emr-devel, sem nenhum benefício significativo.

Desvantagens de usar o:: operadorUsando o:: operador pode prejudicar significativamente a eficiência em determinados contextos como Dominick Samperiapontou.Quandoem desenvolvimento seu próprio pacote, você não pode usar o:: operador em todo o seu próprio código, pois o seu código ainda não é um pacote real e, portanto, também não há namespace. Então eu teria que inicialmente ficar com ofoo maneira, construir, testar e depois voltar a mudar tudo paranamespace::foo. Na verdade não.Possíveis soluções para evitar esses problemasReatribuir cada função de cada pacote para uma variável que segue certas convenções de nomenclatura, por exemplonamespace..foo a fim de evitar as ineficiências associadas ànamespace::foo (Eu delineei uma vezAqui). Prós: funciona. Contras: é desajeitado e você duplica a memória usada.Simular um namespace ao desenvolver seu pacote. AFAIU, isso não é realmente possível, pelo menos eu estavadisse então naquela época.Façaobrigatório usarnamespace::foo. IMHO, isso seria a melhor coisa a fazer. Claro, perderíamos alguma extensão de simplicidade, mas, novamente, o universo R não é mais simples (pelo menos não é tão simples quanto no início dos anos 00).E as aulas (formais)?

Além dos aspectos descritos acima,:: maneira funciona muito bem para funções / métodos. Mas e as definições de classe?

Tomar pacotetimeDate com sua classetimeDate. Diga outro pacote vem junto que também tem uma classetimeDate. Eu não vejo como eu poderia declarar explicitamente que eu gostaria de uma nova instância de classetimeDate de qualquer um dos dois pacotes.

Algo assim não vai funcionar:

new(timeDate::timeDate)
new("timeDate::timeDate")
new("timeDate", ns="timeDate")

Isso pode ser um grande problema à medida que mais e mais pessoas mudam para um estilo OOP para seus pacotes R, levando a muitas definições de classe. Se láé uma maneira de abordar explicitamente o namespace de uma definição de classe, eu apreciaria muito um ponteiro!

Conclusão

Mesmo que isso tenha sido um pouco demorado, espero poder apontar o problema / questão central e que posso aumentar a conscientização aqui.

eu acho quedevtools emvbutils tem algumas abordagens que podem valer a pena se espalhar, mas tenho certeza que há mais a dizer.

questionAnswers(2)

yourAnswerToTheQuestion