# tasks.ref()

`tasks.ref(...)` allows users to reference and access other tasks' outputs and/or [targets](https://docs.runprism.com/v0.2.8/fundamentals/targets). This is the most important function in Prism. It is impossible to build even moderately complex workflows without it.

`tasks.ref(...)` takes two arguments:

* `task: str`: the name of the task whose output you'd like to retrieve. This name should be in the form `<module_name>`, or `<module_name>.<task_name>`, where `<task_name>` is the name of the Prism task class / function.
* `local: bool`:  whether `task` lives in the same module. The default is `False`.&#x20;

Let's look at some examples.

## Ref-ing tasks in different modules

### One task in ref'd module

In most Prism projects, each module in `tasks/` will contain a single task. Let's see how we'd use `tasks.ref()` in this situation.

{% tabs %}
{% tab title="Class-based tasks" %}
{% code lineNumbers="true" %}

```python
# tasks/hello_world.py

import prism.task
import prism.target

class HelloWorld(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
        test_str = "Hello, world!"
        return test_str
```

{% endcode %}

<pre class="language-python" data-line-numbers><code class="lang-python"># tasks/second_task.py

import prism.task
import prism.target

class SecondTask(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
<strong>        hello_world_str = tasks.ref("hello_world")
</strong>        additional_details = "\n" + "This is a Prism project"!
        return hello_world_str + additional_details
</code></pre>

{% endtab %}

{% tab title="Function-based tasks" %}
{% code lineNumbers="true" %}

```python
# tasks/hello_world.py

from prism.decorators import task

@task()
def hello_world(tasks, hooks):
    test_str = "Hello, world!"
    return test_str
```

{% endcode %}

{% code lineNumbers="true" %}

```python
# tasks/second_task.py

import prism.decorators import task

@task()
def second_task(tasks, hooks):
    hello_world_str = tasks.ref("hello_world")
    additional_details = "\n" + "This is a Prism project"!
    return hello_world_str + additional_details
```

{% endcode %}
{% endtab %}
{% endtabs %}

Our `tasks.ref()` is located in the second task. We simply use the name of the module containing the task whose output we want to retrieve. Note that we **exclude** the `.py` suffix from the module name.

{% hint style="info" %}
**Important**: you could specify the task name using `<module_name>.<task_name>`, i.e., `hello_world.HelloWorld`. But this isn't necessary, since `hello_world.py` only contains a single task.
{% endhint %}

### Multiple tasks in ref'd module

Now, let's look at a situation where the ref'd module has multiple tasks and you want to retrieve the output of a *specific* task.

The basic usage is still the same. However, since the ref'd module has multiple tasks, you need to specify your task like `<module_name>.<task_name>`. Here, `task_name` refers to name of the Prism task class or function.

{% tabs %}
{% tab title="Class-based task" %}

```python
# tasks/hello_world.py

import prism.task
import prism.target

class HelloWorld(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
        test_str = "Hello, world!"
        return test_str
        
class FooBar(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
        return "foo, bar"
```

<pre class="language-python"><code class="lang-python"># tasks/second_task.py

import prism.task
import prism.target

class SecondTask(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
        # Get the output of HelloWorld task
<strong>        hello_world_str = tasks.ref("hello_world.HelloWorld")
</strong><strong>        
</strong><strong>        # Get the output of FooBar task
</strong><strong>        foo_bar_str = tasks.ref("hello_world.FooBar")
</strong><strong>        
</strong>        return hello_world_str + foo_bar_str
</code></pre>

{% endtab %}

{% tab title="Function-based task" %}

```python
# tasks/hello_world.py

from prism.decorators import task

@task()
def hello_world(tasks, hooks):
    test_str = "Hello, world!"
    return test_str


@task()
def foo_bar(tasks, hooks):
    return "foo, bar"
```

```python
# tasks/second_task.py

import prism.decorators import task

@task()
def second_task(tasks, hooks):
    # Get the output of HelloWorld task
    hello_world_str = tasks.ref("hello_world.hello_world")
        
    # Get the output of FooBar task
    foo_bar_str = tasks.ref("hello_world.foo_bar")
    
    return hello_world_str + foo_bar_str
```

{% endtab %}
{% endtabs %}

## Ref-ing tasks in the same module

Now, let's look at an example where we want to retrieve the output of a task in the same module. This is where the `local` argument becomes important.

To ref a task in the same module, simply use the `task_name` (i.e., either the class name or function name), and set `local = True`. Here's what that looks like:

{% tabs %}
{% tab title="Class-based tasks" %}

```python
# tasks/hello_world.py

import prism.task
import prism.target

class HelloWorld(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
        test_str = "Hello, world!"
        return test_str


class FooBar(prism.task.PrismTask):
    
    def run(self, tasks, hooks):
        hello_world_str = tasks.ref("HelloWorld", local=True)
        return hello_world_str + "\n" + "foo, bar"
```

{% endtab %}

{% tab title="Function-based tasks" %}

```python
# tasks/hello_world.py

from prism.decorators import task

@task()
def hello_world(tasks, hooks):
    test_str = "Hello, world!"
    return test_str


@task()
def foo_bar(tasks, hooks):
    hello_world_str = tasks.ref("hello_world", local=True)
    return hello_world_str + "\n" + "foo, bar"
```

{% endtab %}
{% endtabs %}

And that's it!

Don't worry if you don't remember all of these details — Prism will give you ample warnings and direction so that you ref your tasks perfectly.
