Konventioner, principer och bakgrund

Det finns många sätt att skriva R-kod för en viss uppgift, och det finns ännu fler sätt att generera R-koden från JS. Exakt hur du gör det, bestämmer du själv. Det finns ändå ett antal hänsynstaganden som du bör följa, och bakgrundsinformation som du bör förstå.

Förstå omgivningen local()

Vanligtvis måste man skapa en eller flera tillfälliga R-objekt i koden som genereras av insticksprogrammet. Normalt vill man inte att de ska placeras i användarens arbetsrymd, och potentiellt till och med skriva över användarvariabler. Därför görs all kod genererad av insticksprogram i en lokal omgivning, local() (se hjälpsidan i R om funktionen local()). Det betyder att alla variabler som skapas är tillfälliga och sparas inte permanent.

Om användaren explicit ber om att en variabel ska sparas, måste tilldelningar till objektet göras genom att använda .GlobalEnv$objectname <- value. I allmänhet ska inte operatorn <<- användas. Den tilldelar inte nödvändigtvis i .GlobalEnv.

En viktig fallgrop är användning av eval(). Här måste man observera att eval normalt använder den aktuella omgivningen för utvärdering, dvs. den lokala. Det fungerar oftast bra, men inte alltid. Om du sålunda behöver använda eval(), bör du ange parametern envir: eval(..., envir=globalenv()).

Kodformatering

Det viktigaste är att den genererade R-koden fungerar, men den bör också vara lättläst. Håll därför också ett öga på formateringen. Några överväganden:

Normala toppnivå R-satser ska vara vänsterjusterade.

Satser i ett lägre block ska indenteras med en flik (se exemplet nedan).

Om du utför mycket komplexa beräkningar, lägg till en kommentar här och där, i synnerhet för att markera logiska avsnitt. Observera att det finns en särskild funktion, comment(), för att infoga översättningsbara kommentarer i genererad kod.

Generad kod kan exempelvis se ut så här. Samma kod utan indentering eller kommentarer skulle vara ganska svårläst, trots dess blygsamma svårighetsgrad:

# bestäm först svaj och rotation
my.wobble <- wobble (x, y)
my.rotation <- wobble.rotation (my.wobble, z)

# vacklingsmetod måste väljas enligt rotation
if (my.rotation > wobble.rotation.limit (x)) {
        method <- "foo"
        result <- boggle.foo (my.wobble, my.rotation)
} else {
        method <- "bar"
        result <- boggle.bar (my.wobble, my.rotation)
}
                

Hantera komplexa alternativ

Många insticksprogram kan göra mer än en sak. Exempelvis kan insticksprogrammet Beskrivande statistik beräkna medelvärde, intervall, summa, produkt, median, längd, etc. Dock väljer användaren typiskt att bara utföra vissa av beräkningarna. Försök hålla den genererade koden så enkel som möjligt i sådana fall. Den ska bara innehålla delarna som är relevanta för alternativen som faktiskt har valts. För att åstadkomma det är här ett exempel på ett vanligt konstruktionsmönster som det skulle användas (i JS skulle elementen "domean", "domedian" och "dosd" här vara kryssrutor, <checkbox>):

function calculate () {
        echo ('x <- <' + getString ("x") + ')\n');
        echo ('results <- list ()\n');

        if (getBoolean ("domean.state")) echo ("results$" + i18n ("Mean value") + " <- mean (x)\n");
        if (getBoolean ("domedian.state")) echo ("results$" + i18n ("Median") + " <- median (x)\n");
        if (getBoolean ("dosd.state")) echo ("results$" + i18n ("Standard deviation") + " <- sd (x)\n");
        //...
}