DRY Principle in statically typed Nextflow: reusing output path definitions in `output:` and `script:` sections

Hi all!

I’ve been really enjoying using Nextflow recently for setting up ML pipelines. I previously used Snakemake, but found that the path-based logic became too complex as the pipeline grew in complexity.

There is one quirk that irritates me slightly though. This is strongly related to a previous post, which asked the same question but for legacy, untyped synax: DRY Principle in Nextflow: Reusing Output Path Definitions in `output:` and `script:` sections

According to Processes (typed) | Seqera Docs, I can define a process like

process myProcess {
    input:
    message: String

    output:
    out_file: Path = file("${message}.txt")

    script:
    """
    echo "${message}" > "${message}.txt"
    """
}

but this forces me to repeat the same output path logic twice. I would like to just use ${out_file} in the script block, like this:

process myProcess {
    input:
    message: String

    output:
    out_file: Path = file("${message}.txt")

    script:
    """
    echo "${message}" > "${out_file}"
    """
}

but if I try this then I get the error

`out_file` is not defined

Is there any chance of this getting added in the future? I really like the new typed syntax and would like to use it to the greatest extent possible.

BR, Valter

Rob’s answer in the other thread also applies here – you can assign the file pattern to a variable in the script block and use it in the output block. Using out_file in the script block wouldn’t make sense because out_file is being defined in the output block, which is evaluated after the script block

Thanks! This seems to work:

process myProcess {
    input:
    message: String

    output:
    out_file: Path = file(out_file)

    script:
    out_file = "${message}.txt"
    """
    echo "${message}" > "${out_file}"
    """
}

I still think that the desired behavior I posted looks slightly more succinct, but if the output block cannot be evaluated earlier then this is a fair tradeoff.

Some people even prefer to define the output block after the script block to better reflect the evaluation order:

process myProcess {
    input:
    message: String

    script:
    out_file = "${message}.txt"
    """
    echo "${message}" > "${out_file}"
    """

    output:
    out_file: Path = file(out_file)
}