PriyoScriptPriyoScript
Basics

Functions

Define reusable logic with parameters, return values, recursion, and closures.

Theory

Functions are reusable blocks of logic that improve readability, reduce duplication, and make code easier to test. In PriyoScript, functions are declared with lisaaTask and optionally return values using priyoGiveBack. A function can accept parameters, perform calculations, call other functions, and return output to the caller. Functions are essential for structuring medium and large programs.

Why functions matter

If a logic block is repeated, move it into a function once and call it where needed.

Function Types Table

Function typeSyntax patternDescription
Basic function (no params)lisaaTask name() { ... }Runs reusable logic without input parameters.
Function with parameterslisaaTask name(a, b) { ... }Accepts input values from caller.
Function returning valuepriyoGiveBack valueSends computed result back to caller.
Void-style functionno priyoGiveBackPerforms side effects (for example output/logging).
Recursive functionname(...) inside same functionCalls itself until base condition is met.
Closure functionreturns inner functionInner function remembers outer variables.
Async function (stage-1)prakritiWait lisaaTask ...Enables prakritiPause inside the function body.
Generator-yield (stage-1)prakritiGiveSome valueProduces step values consumable via next().
Structured concurrencyprakritiConcurrency.group(...)Runs async tasks with group wait/cancel semantics.
Bounded concurrency queueprakritiConcurrency.queue(...)Limits how many async tasks run at the same time.

Syntax Quick Reference

monalisa {
  lisaaTask add(a, b) {
    priyoGiveBack a + b
  }

  priyoTell(add(2, 3))
}

Async Functions and Await (Stage-1)

prakritiWait marks a function as async-capable. prakritiPause waits for an expression to resolve.

Example 1

monalisa {
  prakritiWait lisaaTask addAsync(a, b) {
    priyoGiveBack prakritiPause (a + b)
  }

  priyoTell(prakritiPause addAsync(20, 22))
}

Output:

42

Example 2

monalisa {
  prakritiWait lisaaTask greetLater(name) {
    priyoGiveBack "Hi " + prakritiPause name
  }

  priyoTell(prakritiPause greetLater("mona"))
}

Output:

Hi mona

Prakriti Concurrency

PriyoScript concurrency uses prakriti names for async work, lightweight task spawning, channels, grouped task ownership, queues, cancellation, deadlines, combinators, and delayed task scheduling.

Use prakritiGo when you want to start one cooperative task and keep its task handle. Use prakritiChannel when tasks need to exchange values. Use prakritiConcurrency.group(...) or .queue(...) when a parent scope should own, cancel, or inspect a set of tasks together.

Example 1: Spawn a task and receive from a channel

monalisa {
  prakritiWait lisaaTask prepare(outbox, name) {
    prakritiPause prakritiConcurrency.after(5, priyoEmpty)
    prakritiPause outbox.send(name + " ready")
    priyoGiveBack name
  }

  priyoKeep outbox = prakritiChannel()
  priyoKeep task = prakritiGo prepare(outbox, "mona")

  priyoTell(prakritiPause outbox.receive())
  priyoTell(prakritiPause task.join())
}

Output:

mona ready
mona

Example 2: Run tasks in a group

monalisa {
  prakritiWait lisaaTask fetchName(name) {
    prakritiPause prakritiConcurrency.after(5, priyoEmpty)
    priyoGiveBack name + " done"
  }

  priyoKeep group = prakritiConcurrency.group("names")
  priyoKeep first = group.run(fetchName, "mona")
  priyoKeep second = group.run(fetchName, "lisaa")

  priyoTell(priyoArray.length(prakritiPause group.all()))
  priyoTell(prakritiPause first.join())
}

Output:

2
mona done

Example 3: Cooperative cancellation

monalisa {
  prakritiWait lisaaTask worker(name, token) {
    prakritiPause prakritiConcurrency.after(5, priyoEmpty)
    token.throwIfCancelled()
    priyoGiveBack name + " finished"
  }

  priyoKeep group = prakritiConcurrency.group("cancel")
  priyoKeep token = group.token()
  priyoKeep task = group.run(worker, "mona", token)
  group.cancel("stop now")

  prakritiTry {
    priyoTell(prakritiPause task.join())
  } prakritiCatch (err) {
    priyoTell(err.code)
  }
}

Output:

PRUN-112

Example 4: Delayed scheduling

monalisa {
  prakritiWait lisaaTask greet(name) {
    priyoGiveBack "Hello " + name
  }

  priyoKeep group = prakritiConcurrency.group("scheduled")
  priyoKeep task = group.schedule(5, greet, "lisaa")

  priyoTell(task.status())
  priyoTell(prakritiPause task.join())
  priyoTell(task.status())
}

Output:

scheduled
Hello lisaa
fulfilled

Example 5: Deadline-driven cancellation

monalisa {
  prakritiWait lisaaTask worker(token) {
    prakritiPause prakritiConcurrency.after(20, priyoEmpty)
    token.throwIfCancelled()
    priyoGiveBack "done"
  }

  priyoKeep group = prakritiConcurrency.group("deadline")
  priyoKeep token = group.token()
  group.deadline(5, "deadline reached")
  priyoKeep task = group.run(worker, token)

  prakritiTry {
    priyoTell(prakritiPause task.join())
  } prakritiCatch (err) {
    priyoTell(err.code)
  }
}

Output:

PRUN-112

Example 6: Race, any, and allSettled

monalisa {
  prakritiWait lisaaTask delayedValue(name, delay) {
    prakritiPause prakritiConcurrency.after(delay, priyoEmpty)
    priyoGiveBack name
  }

  prakritiWait lisaaTask delayedBoom(delay) {
    prakritiPause prakritiConcurrency.after(delay, priyoEmpty)
    prakritiThrow "boom"
  }

  priyoKeep raceGroup = prakritiConcurrency.group("race")
  raceGroup.run(delayedValue, "slow", 10)
  raceGroup.run(delayedValue, "fast", 1)
  priyoTell(prakritiPause raceGroup.race())

  priyoKeep anyGroup = prakritiConcurrency.group("any")
  anyGroup.run(delayedBoom, 1)
  anyGroup.run(delayedValue, "winner", 5)
  priyoTell(prakritiPause anyGroup.any())
}

Output:

fast
winner

Example 7: Bounded task queues

monalisa {
  prakritiWait lisaaTask worker(name, delay) {
    prakritiPause prakritiConcurrency.after(delay, priyoEmpty)
    priyoGiveBack name
  }

  priyoKeep queue = prakritiConcurrency.queue(1, "serial")
  queue.run(worker, "first", 5)
  queue.run(worker, "second", 5)

  priyoTell(queue.limit())
  priyoTell(queue.active())
  priyoTell(queue.queued())
  priyoTell(prakritiPause queue.all())
}

Output:

1
1
1
[first, second]

Concurrency API quick reference

APIPurpose
prakritiGo task(args...)Start a cooperative task and return a handle.
prakritiChannel(capacity?, label?)Create a task communication channel.
channel.send(value) / channel.receive()Send and receive channel values asynchronously.
prakritiConcurrency.group(label?)Create a task group.
prakritiConcurrency.queue(limit, label?)Create a bounded task queue.
prakritiConcurrency.after(ms, value?)Resolve a value after a delay.
group.run(...) / queue.run(...)Start a task now.
group.schedule(...) / queue.schedule(...)Start or enqueue a task after a delay.
group.all() / queue.all()Wait for all started tasks.
group.allSettled() / queue.allSettled()Collect task outcomes without failing fast.
group.race() / queue.race()Settle on the first completed task.
group.any() / queue.any()Resolve with the first fulfilled task.
group.deadline(ms, reason?) / queue.deadline(ms, reason?)Auto-cancel after a timeout.
group.pending() / queue.pending()Count active pending tasks.
queue.active() / queue.queued() / queue.limit()Inspect queue capacity and backlog.
task.join() / task.status() / task.error()Inspect and await a specific task handle.
token.cancel() / token.throwIfCancelled()Cancel and cooperatively observe cancellation.

1. Function Without Return Value

Runs logic without explicit returned result.

Example 1

monalisa {
  lisaaTask greet() {
    priyoTell("Hello from function")
  }

  greet()
}

Output:

Hello from function

Example 2

monalisa {
  lisaaTask banner() {
    priyoTell("==== PriyoScript ====")
  }

  banner()
}

Output:

==== PriyoScript ====

2. Function With Return Value

Returns data so caller can reuse the computed value.

Example 1

monalisa {
  lisaaTask add(a, b) {
    priyoGiveBack a + b
  }

  priyoTell(add(10, 5))
}

Output:

15

Example 2

monalisa {
  lisaaTask isAdult(age) {
    priyoGiveBack age >= 18
  }

  priyoTell(isAdult(21))
}

Output:

priyoTrue

3. Recursive Function

A function that calls itself with a smaller problem until base condition.

Example 1

monalisa {
  lisaaTask factorial(n) {
    prakritiIf (n <= 1) {
      priyoGiveBack 1
    }
    priyoGiveBack n * factorial(n - 1)
  }

  priyoTell(factorial(5))
}

Output:

120

Example 2

monalisa {
  lisaaTask countdown(n) {
    prakritiIf (n == 0) {
      priyoGiveBack "done"
    }
    priyoTell(n)
    priyoGiveBack countdown(n - 1)
  }

  priyoTell(countdown(3))
}

Output:

3
2
1
done

4. Closure Function

Function returns another function that keeps access to outer variables.

Example 1

monalisa {
  lisaaTask makeCounter() {
    priyoChange count = 0
    lisaaTask next() {
      count = count + 1
      priyoGiveBack count
    }
    priyoGiveBack next
  }

  priyoKeep c = makeCounter()
  priyoTell(c())
  priyoTell(c())
}

Output:

1
2

Example 2

monalisa {
  lisaaTask makeGreeter(prefix) {
    lisaaTask greet(name) {
      priyoGiveBack prefix + " " + name
    }
    priyoGiveBack greet
  }

  priyoKeep welcome = makeGreeter("Welcome")
  priyoTell(welcome("mona"))
}

Output:

Welcome mona

5. Generator Yield (Stage-1)

prakritiGiveSome emits sequence values from a function. A yield function returns a generator-like object with next(), hasNext(), and reset().

Example 1

monalisa {
  lisaaTask series() {
    prakritiGiveSome 1
    prakritiGiveSome 2
  }

  priyoKeep g = series()
  priyoTell(g.next().value)
  priyoTell(g.next().value)
  priyoTell(g.next().done)
}

Output:

1
2
priyoTrue

Example 2

monalisa {
  lisaaTask names() {
    prakritiGiveSome "mona"
    prakritiGiveSome "lisaa"
  }

  priyoKeep g = names()
  priyoTell(g.hasNext())
  priyoTell(g.next().value)
  g.reset()
  priyoTell(g.next().value)
}

Output:

priyoTrue
mona
mona

Practice Questions

Concept Check

  1. When should you return a value instead of printing inside the function? 2. Why is a base condition mandatory in recursive functions? 3. What value does a closure preserve after the outer function finishes?

Last updated on

On this page