nextflow-io / nextflow

A DSL for data-driven computational pipelines
http://nextflow.io
Apache License 2.0
2.69k stars 621 forks source link

variable isolation issue #4872

Open eldadkd opened 5 months ago

eldadkd commented 5 months ago

Bug report

Expected behavior and actual behavior

Expected behavior: println("calculateCPUs overrideValue = $overrideValue") should print: alculateCPUs overrideValue = null

Actual behavior: what prints out is: calculateCPUs overrideValue = 1 GB

Steps to reproduce the problem

running this nf script:

include {calculateMem; calculateCPUs} from "./func.nf"

workflow {
    p1()
}

process p1 {
    debug true
    memory {calculateMem(overrideValue: "1 GB", task:task)}
    cpus {calculateCPUs(task: task)}

    exec:
    println("Hi")

}

and this script:

def calculateMem(Map args) {
    overrideValue = args.get('overrideValue', null)
    task = args.get('task')
    return 1.GB
}

def calculateCPUs(Map args) {
    overrideValue = args.get('overrideValue')
    task = args.get('task')

    taskMemory = task.memory.toGiga()
    println("taskMemory from inside the calculateCPUs: $taskMemory")
    println("calculateCPUs args['overrideValue']: ${args.get('overrideValue')}")
    println("calculateCPUs overrideValue = $overrideValue")
    return 1
}

after calling this line taskMemory = task.memory.toGiga() on calculateCPUs method overrideValue value is changed from null to the value given to calculateMem

Program output

Launching `/Users/eldadkd/Library/Application Support/JetBrains/IdeaIC2023.3/scratches/scratch_4.txt` [high_poisson] DSL2 - revision: 47ee90e704
executor >  local (1)
[77/7b381c] process > p1 [100%] 1 of 1 ✔
taskMemory from inside the calculateCPUs: 1
calculateCPUs args['overrideValue']: null
calculateCPUs overrideValue = 1 GB
Hi

Environment

bentsherman commented 5 months ago

this is an unfortunate quick of the Nextflow compiler. when you declare a variable with def, it gets defined as a global variable

likely needs to be addressed by #4613 or a subsequent iteration

eldadkd commented 5 months ago

I forgot to mention that if I remove those lines:

taskMemory = task.memory.toGiga()
println("taskMemory from inside the calculateCPUs: $taskMemory")

overrideValue is null as expected

bentsherman commented 5 months ago

I would say just always declare local variables with def unless you actually want it to be global