# #2 Circom: Template parameters, Variables, Loops

## **Template parameters**

Previously we looked at a circuit (<mark style="color:red;">`IsBinary`</mark>) that verified if the supplied inputs were indeed binary.

That circuit circuit was hardcoded to accept only 2 inputs.

What if we want to parametrize the number of inputs? We would modify the circuit, like so:

```rust
template IsBinary(n) {
    
    // array of n inputs
    signal input in[n];
    
    // 4 constraints each of them to be 0 or 1
    // only checks first 4 elements in array
    in[0] * (1 - in[0]) === 0;
    in[1] * (1 - in[1]) === 0;
    in[2] * (1 - in[2]) === 0;
    in[3] * (1 - in[3]) === 0;
}

// must specify value of n
component main = IsBinary(4);
```

Notice that the template declaration has changed to include <mark style="color:red;">`n`</mark> in the parenthesis

* <mark style="color:red;">`n`</mark> here is known as a template parameter
* <mark style="color:red;">`n`</mark> is used within the circuit to specify the size of the array <mark style="color:red;">`in`</mark>
* on instantiating, we must specify the value of <mark style="color:red;">`n`</mark>

Circuits and constraints in Circom must have a fixed, known structure at instantiation; meaning they can't change after compilation. While templates can use parameters, once compiled, the circuit must be static and clearly defined. There is no support for "dynamic-length" circuits or constraints —everything must be fixed and well-defined from the start.

It is not possible to support variability in circuits and constraints post-compilation, as such variability would undermine the integrity of said circuits. Hence, it is crucial to ensure the scope of proving and verification is static and well-defined. Imagine having an R1CS system of constraints whose structure was mutable based on input signal values. Neither the prover nor the verifier could operate effectively as the number of constraints are not set in stone.

Although we have parametrized the array to be based on `n` inputs, the number of constraints remain unchanged - there are 4 constraints and they only verify for the first 4 elements of the array. In the next example, we will explore how to generalize the number of constraints to match our array, using loops.

## For loop and Variables: <mark style="color:red;">`for`</mark>, <mark style="color:red;">`var`</mark>

Use a for loop to generate constraints programmatically to match the number of inputs, like so:

```rust
template IsBinary(n) {

    // array of n inputs
    signal input in[n];
		
    // n loops: n constraints
    for (var i = 0; i < n; i++) {
        in[i] * (1 - in[i]) === 0;
    }
}

// instantiated w/ 4 inputs & 4 constraints
component main = IsBinary(4);
```

* both inputs and loop iterations are defined by <mark style="color:red;">`n`</mark>
* for each input, a constraint is defined with the purpose of verifying that it is either <mark style="color:red;">`0`</mark> or <mark style="color:red;">`1`</mark>

We have introduced two new keywords into the circuit: <mark style="color:red;">`for`</mark> and <mark style="color:red;">`var`</mark>

* Usage of the <mark style="color:red;">`for`</mark> keyword should be no mystery to the reader.
* The <mark style="color:red;">`var`</mark> keyword is used to declare a **variable**; <mark style="color:red;">`i`</mark> , as seen in the loop definition.
* Variable assignment is made using the equal symbol <mark style="color:red;">`=`</mark>

Here, variable <mark style="color:red;">`i`</mark> is used to programmatically refer to different signals in the input array, while creating constraints for them.&#x20;

## Variables

Variables hold non-signal data and are mutable. Here is an example of a variable declaration outside of a loop:

```jsx
component VariableExample(n) {

	var acc = 2;
	signal s;
}
```

* Variables are **not** part of the R1CS system of constraints.
* Variables are used to compute values outside the R1CS, to help define the R1CS.
* When working with variables, Circom behaves like a normal programming language.
* Operators <mark style="color:red;">`=`</mark>, <mark style="color:red;">`==`</mark>, <mark style="color:red;">`>=`</mark>, <mark style="color:red;">`<=`</mark>, and <mark style="color:red;">`!=`</mark>, <mark style="color:red;">`++`</mark>, and <mark style="color:red;">`--`</mark> behave the way you expect them to with variables.
* However, these operators do not work with signals (Circom will not compile such code), as they would not honour quadratic expressions.

**Example**

```jsx
component VariableExample() {

	signal input s;
	var acc;

	// non-quadratic expression
	acc = (10 / 2) * 3;
}

component main = VariableExample();
```

* non-quadratic expressions are allowed with variables
* <mark style="color:red;">`acc`</mark> would be assigned the value of 15

Since we can use non-quadratic expressions with variables, they are very useful for side calculations, which can yield a value that can subsequently be used within a constraint.

```jsx
component VariableExample() {

	signal input s;
	var acc;
		
	// non-quadratic expression
	acc = (10 / 2) * 3;
	
	s === acc;
}

component main = VariableExample();
```

* input signal <mark style="color:red;">`s`</mark> is constrained to <mark style="color:red;">`acc`</mark>
* the circuit serves to verify if the input signal is indeed 15.

## Summary Example

Let’s combine all the above concepts into a less trivial example. The circuit below serves to verify if someone knows the decimal form of a binary number.

It expected both the binary and its supposed decimal equivalent to be provided for verification.

```jsx
template BinaryToDecimal(n) {

    // Binary number as array
    signal input in[n];   // n-bit binary input
    signal input res;    

    var sum = 0;

    // Loop through each bit of the binary input
    for (var i = 0; i < n; i++) {
    
        // Add the binary value * 2^i to the sum
        // 1 << i is the same as 2^i
        sum += in[i] * (1 << i); 
    }

    // constraint the computed sum to the given decimal
    res === sum;
}

// Example with a 4-bit binary number
component main = BinaryToDecimal(4); 

```

* circuit takes the binary number input as an array `in[n]` and the decimal result as `res`
* the provided binary number is converted to decimal form and assigned it to `sum`
* `res` is then constrained against `sum`
* If the computed decimal value is not equal to the provided decimal value, verification fails.

This example showcases how a circuit can be created via parameters.

In the next article we will discuss in-depth where and how parameters can be used.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnix.gitbook.io/zk-notes/circom/2-circom-template-parameters-variables-loops.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
