Skip to content

lint seeded randomness

github-actions[bot] edited this page Jul 24, 2025 · 1 revision

This document was generated from 'src/documentation/print-linter-wiki.ts' on 2025-07-24, 05:52:54 UTC presenting an overview of flowR's linter (v2.3.0, using R v4.5.0). Please do not edit this file/wiki page directly.

Seeded Randomness [overview]

reproducibility robustness

Checks whether randomness-based function calls are preceded by a random seed generation function. For consistent reproducibility, functions that use randomness should only be called after a constant random seed is set using a function like set.seed.
This linting rule is implemented in src/linter/rules/seeded-randomness.ts.

Configuration

Linting rules can be configured by passing a configuration object to the linter query as shown in the example below. The seeded-randomness rule accepts the following configuration options:

  • randomnessConsumers
    A set of randomness consumer function names that require a seed to be set prior to invocation.
  • randomnessProducers
    A set of functions and variables whose invocation or assignment causes a random seeded to be set. Each entry has a type, which is either function or assignment, and a name, which is the name of the function or variable. The default value for this is the function set.seed and the variable .Random.seed.

Examples

runif(1)

The linting query can be used to run this rule on the above example:

[ { "type": "linter",   "rules": [ { "name": "seeded-randomness",     "config": {} } ] } ]

Results (prettified and summarized):

Query: linter (0 ms)
   ╰ Seeded Randomness (seeded-randomness):
       ╰ definitely:
           ╰ Function runif at 1.1-8
       ╰ Metadata: {"consumerCalls":1,"callsWithFunctionProducers":0,"callsWithAssignmentProducers":0,"callsWithNonConstantProducers":0,"searchTimeMs":0,"processTimeMs":0}
All queries together required ≈0 ms (1ms accuracy, total 3 ms)

Show Detailed Results as Json

The analysis required 2.8 ms (including parsing and normalization and the query) within the generation environment.

In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the Interface wiki page for more information on how to get those.

{
  "linter": {
    "results": {
      "seeded-randomness": {
        "results": [
          {
            "certainty": "definitely",
            "function": "runif",
            "range": [
              1,
              1,
              1,
              8
            ]
          }
        ],
        ".meta": {
          "consumerCalls": 1,
          "callsWithFunctionProducers": 0,
          "callsWithAssignmentProducers": 0,
          "callsWithNonConstantProducers": 0,
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      }
    },
    ".meta": {
      "timing": 0
    }
  },
  ".meta": {
    "timing": 0
  }
}

Additional Examples

These examples are synthesized from the test cases in: test/functionality/linter/lint-seeded-randomness.test.ts

Test Case: none

Given the following input:

cat("hello")

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: simple no producer

Given the following input:

runif(1)

We expect the linter to report the following:

[{ range: [1,1,1,8], function: 'runif', certainty: LintingCertainty.Definitely }]

See here for the test-case implementation.

Test Case: simple no consumer

Given the following input:

set.seed(17)

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: simple both

Given the following input:

set.seed(17)
runif(1)

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: simple after

Given the following input:

runif(1)
set.seed(17)

We expect the linter to report the following:

[{ range: [1,1,1,8], function: 'runif', certainty: LintingCertainty.Definitely }]

See here for the test-case implementation.

Test Case: loop valid

Given the following input:

for(i in 1:10) { set.seed(17); runif(1); }

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: condition

Given the following input:

if(FALSE) { set.seed(17); }
runif(1);

We expect the linter to report the following:

[{ range: [2,1,2,8], function: 'runif', certainty: LintingCertainty.Definitely }]

See here for the test-case implementation.

Test Case: condition true

Given the following input:

if(TRUE) { set.seed(17); }
runif(1);

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: non-constant seed

Given the following input:

num<-1 + 7;
set.seed(num);
runif(1);

We expect the linter to report the following:

range: [3,1,3,8], function: 'runif', certainty: LintingCertainty.Definitely

See here for the test-case implementation.

Test Case: random seed

Given the following input:

set.seed(runif(1));
runif(1);

We expect the linter to report the following:

range: [1,10,1,17], function: 'runif', certainty: LintingCertainty.Definitely },
{ range: [2,1,2,8], function: 'runif', certainty: LintingCertainty.Definitely

See here for the test-case implementation.

Test Case: multiple seeds

Given the following input:

set.seed(1);
set.seed(2);
runif(1);

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: multiple consumers

Given the following input:

set.seed(1);
set.seed(2);
runif(1);
runif(1);

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: custom set.seed

Given the following input:

set.seed <- function(x) {}
set.seed(17)
runif(1)

We expect the linter to report the following:

[{ range: [3,1,3,8], function: 'runif', certainty: LintingCertainty.Definitely }]

See here for the test-case implementation.

Test Case: set .Random.seed

Given the following input:

.Random.seed <- 17
runif(1)

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: set .Random.seed with assignment inbetween

Given the following input:

.Random.seed <- 17
x <- 7 
runif(1)

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: set .Random.seed reverse

Given the following input:

17 -> .Random.seed
runif(1)

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: set .Random.seed override <-

Given the following input:

`<-`<-function(){}
.Random.seed <- 17
runif(1)

We expect the linter to report the following:

[{ range: [3,1,3,8], function: 'runif', certainty: LintingCertainty.Definitely }]

See here for the test-case implementation.

Test Case: set in function call

Given the following input:

runif(set.seed(17))

We expect the linter to report the following:

[{ range: [1,1,1,19], function: 'runif', certainty: LintingCertainty.Definitely }]

See here for the test-case implementation.

Test Case: get in function call

Given the following input:

runif(runif(1))

We expect the linter to report the following:

range: [1,7,1,14], function: 'runif', certainty: LintingCertainty.Definitely },
{ range: [1,1,1,15], function: 'runif', certainty: LintingCertainty.Definitely

See here for the test-case implementation.

Clone this wiki locally