PageSourceSearch

https://noir-lang.org/docs/assets/js/2e2ec308.81761ddf.js

js noir-lang.org collected 2026-10-03 22:54:53 UTC 18,449 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[3893],{43899(e,n,a){a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"language/data_types/arrays","title":"Arrays","description":"Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code.","source":"@site/versioned_docs/version-v1.0.0-rc.0/language/data_types/arrays.md","sourceDirName":"language/data_types","slug":"/language/data_types/arrays","permalink":"/docs/v1.0.0-rc.0/language/data_types/arrays","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.0/language/data_types/arrays.md","tags":[],"version":"v1.0.0-rc.0","frontMatter":{"title":"Arrays","description":"Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code.","keywords":["noir","array type","methods","examples","indexing"]},"sidebar":"sidebar","previous":{"title":"Strings","permalink":"/docs/v1.0.0-rc.0/language/data_types/strings"},"next":{"title":"Vectors","permalink":"/docs/v1.0.0-rc.0/language/data_types/vectors"}}');var s=a(74848),i=a(28453);const t={title:"Arrays",description:"Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code.",keywords:["noir","array type","methods","examples","indexing"]},l=void 0,c={},d=[{value:"Dynamic Indexing",id:"dynamic-indexing",level:2},{value:"Indexing with Field Elements",id:"indexing-with-field-elements",level:2},{value:"Types",id:"types",level:2},{value:"Methods",id:"methods",level:2},{value:"len",id:"len",level:3},{value:"sort",id:"sort",level:3},{value:"sort_via",id:"sort_via",level:3},{value:"map",id:"map",level:3},{value:"mapi",id:"mapi",level:3},{value:"for_each",id:"for_each",level:3},{value:"for_eachi",id:"for_eachi",level:3},{value:"fold",id:"fold",level:3},{value:"reduce",id:"reduce",level:3},{value:"all",id:"all",level:3},{value:"any",id:"any",level:3},{value:"concat",id:"concat",level:3},{value:"as_str_unchecked",id:"as_str_unchecked",level:3}];function o(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["An array is one way of grouping together values into one compound type. Array types can be inferred\nor explicitly specified via the syntax ",(0,s.jsx)(n.code,{children:"[<Type>; <Size>]"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main(x : u64, y : u64) {\n    let my_arr = [x, y];\n    let your_arr: [u64; 2] = [x, y];\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Here, both ",(0,s.jsx)(n.code,{children:"my_arr"})," and ",(0,s.jsx)(n.code,{children:"your_arr"})," are instantiated as an array containing two ",(0,s.jsx)(n.code,{children:"u64"})," elements."]}),"\n",(0,s.jsx)(n.p,{children:"Array elements can be accessed using indexing:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let a = [1, 2, 3, 4, 5];\n\n    let first = a[0];\n    let second = a[1];\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group\na ",(0,s.jsx)(n.code,{children:"Field"})," value and a ",(0,s.jsx)(n.code,{children:"u8"})," value together for example."]}),"\n",(0,s.jsx)(n.p,{children:"You can write mutable arrays, like:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let mut arr = [1, 2, 3, 4, 5];\n    assert(arr[0] == 1);\n\n    arr[0] = 42;\n    assert(arr[0] == 42);\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let array: [Field; 32] = [0; 32];\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a ",(0,s.jsx)(n.a,{href:"/docs/v1.0.0-rc.0/language/data_types/vectors",children:"vector"}),", you can just call ",(0,s.jsx)(n.code,{children:"as_vector"})," on your array:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let array: [Field; 32] = [0; 32];\nlet sl = array.as_vector()\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can also create vectors directly using the ",(0,s.jsx)(n.code,{children:"@[...]"})," literal syntax. See ",(0,s.jsx)(n.a,{href:"/docs/v1.0.0-rc.0/language/data_types/vectors",children:"Vectors"})," for details."]}),"\n",(0,s.jsx)(n.p,{children:"You can define multidimensional arrays:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let array : [[Field; 2]; 2];\nlet element = array[0][0];\n"})}),"\n",(0,s.jsx)(n.p,{children:"However, multidimensional vectors are not supported. For example, the following code will error at compile time:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let vector : [[Field]] = @[];\n"})}),"\n",(0,s.jsx)(n.h2,{id:"dynamic-indexing",children:"Dynamic Indexing"}),"\n",(0,s.jsx)(n.p,{children:'Using constant indices of arrays will often be more efficient at runtime in constrained code.\nIndexing an array with 
1non-constant indices (indices derived from the inputs to the program, or returned from unconstrained functions) is also\ncalled "dynamic indexing" and incurs a slight runtime cost:'}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main(x: u32) {\n    let array = [1, 2, 3, 4];\n\n    // This is a constant index, after inlining the compiler sees that this\n    // will always be `array[2]`\n    let _a = array[double(1)];\n\n    // This is a non-constant index, there is no way to know which u32 value\n    // will be used as an index here\n    let _b = array[double(x)];\n}\n\nfn double(y: u32) -> u32 {\n    y * 2\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"There is another restriction with dynamic indices: they cannot be used on arrays with\nelements which contain a reference type:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main(x: u32) {\n    let array = [&mut 1, &mut 2, &mut 3, &mut 4];\n\n    // error! Only constant indices may be used here since `array` contains references internally!\n    let _c = array[x];\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"indexing-with-field-elements",children:"Indexing with Field Elements"}),"\n",(0,s.jsxs)(n.p,{children:["Working with the native Field type can help producing more optimized programs (if you know what you are doing!), by avoiding overflow checks in general and in particular for array index, u32 arithmetic.\nHowever Noir type system will require your array index to be ",(0,s.jsx)(n.code,{children:"u32"}),", so if you computed an array index using the Field type, you will have to convert it into a ",(0,s.jsx)(n.code,{children:"u32"}),". This operation is usually costly because the 'unbounded' Field element needs to be reduced modulo ",(0,s.jsx)(n.code,{children:"2^32"}),". However we can benefit from the array out-of-bound checks in order to avoid this costly operation.\nOne way to do it is the following:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["use ",(0,s.jsx)(n.code,{children:"assert_max_bit_size::<32>();"})," and ",(0,s.jsx)(n.code,{children:"as u32"})," in order to convert a Field into a u32 using only one range-check, if you know that the Field is indeed 32 bits (or less)."]}),"\n",(0,s.jsxs)(n.li,{children:["Index the array with the resulting u32: ",(0,s.jsx)(n.code,{children:"array[x as u32]"}),". This will remove the range-check from the previous step."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn foo(x: Field, array: [Field; 10]) -> Field {\n    // x is used to index `array`, so it must fit into 32 bits\n    x.assert_max_bit_size::<32>();\n    // assert_max_bit_size::<32>() makes the u32 conversion: `x as u32`, free.\n    // Accessing the array also implies an out-of-bound check, so it makes the range-check `x.assert_max_bit_size::<32>();`\n    // redundant. It will be removed in a later stage.\n    array[x as u32]\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"types",children:"Types"}),"\n",(0,s.jsx)(n.p,{children:"You can create arrays of primitive types, structs, nested arrays, and arrays of structs that\ncontain arrays. See the multidimensional array example above."}),"\n",(0,s.jsx)(n.h2,{id:"methods",children:"Methods"}),"\n",(0,s.jsxs)(n.p,{children:["For convenience, the STD provides some ready-to-use, common methods for arrays.\nEach of these functions are located within the generic impl ",(0,s.jsx)(n.code,{children:"impl<T, N> [T; N] {"}),".\nSo anywhere ",(0,s.jsx)(n.code,{children:"self"})," appears, it refers to the variable ",(0,s.jsx)(n.code,{children:"self: [T; N]"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"len",children:"len"}),"\n",(0,s.jsx)(n.p,{children:"Returns the length of an array"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn len(self) -> Field\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let array = [42, 42];\n    assert(array.len() == 2);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"sort",children:"sort"}),"\n",(0,s.jsxs)(n.p,{children:["Returns a new sorted array. The original array remains untouched. Notice that this function will\nonly work for arrays of fields or integers, not for any arbitrary type. This is because the sorting\nlogic it uses internally is optimized specifically for these values. If you need a sort function to\nsort any type, you should use the function ",(0,s.jsx)(n.code,{children:"sort_via"})," described below."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn sort(self) -> [T; N]\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let arr = [42, 32];\n    let sorted = arr.sort();\n    assert(sorted == [32, 42]);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"sort_via",children:"sort_via"}),"\n",(0,s.jsx)(n.p,{children:"Sorts the array with a custom comparison function. The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument."}),"\n",(0,s.jsxs)(n.p,{children:["Using this method with an operator like ",(0,s.jsx)(n.code,{children:"<"})," that does not return ",(0,s.jsx)(n.code,{children:"true"})," for equal values will result in an assertion failure for arrays with equal elements."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N]\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let arr = [42, 32]\n    let sorted_ascending = arr.sort_via(|a, b| a <= b);\n    assert(sorted_ascending == [32, 42]); // verifies\n\n    let sorted_descending = arr.sort_via(|a, b| a >= b);\n    assert(sorted_descending == [32, 42]); // does not verify\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"map",children:"map"}),"\n",(0,s.jsx)(n.p,{children:"Applies a function to each element of the array, returning a new array containing the mapped elements."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn map<U>(self, f: fn(T) -> U) -> [U; N]\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let a = [1, 2, 3];\nlet b = a.map(|a| a * 2); // b is now [2, 4, 6]\n"})}),"\n",(0,s.jsx)(n.h3,{id:"mapi",children:"mapi"}),"\n",(0,s.jsx)(n.p,{children:"Applies a function to each element of the array, along with its index in the\narray, returning a new array containing the mapped elements."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> [U; N]\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let a = [1, 2, 3];\nlet b = a.mapi(|i, a| i + a * 2); // b is now [2, 5, 8]\n"})}),"\n",(0,s.jsx)(n.h3,{id:"for_each",children:"for_each"}),"\n",(0,s.jsx)(n.p,{children:"Applies a function to each element of the array."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn for_each<Env>(self, f: fn[Env](T) -> ())\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:'let a = [1, 2, 3];\na.for_each(|x| {\n    println(f"{x}");\n});\n// prints:\n// 1\n// 2\n// 3\n'})}),"\n",(0,s.jsx)(n.h3,{id:"for_eachi",children:"for_eachi"}),"\n",(0,s.jsx)(n.p,{children:"Applies a function to each element of the array, along with its index in the\narray."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ())\n"})}),"\n",(0,s.jsx)(n.p,{children:"example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:'let a = [1, 2, 3];\na.for_eachi(|i, x| {\n    println(f"{i}, {x}");\n});\n// prints:\n// 0, 1\n// 1, 2\n// 2, 3\n'})}),"\n",(0,s.jsx)(n.h3,{id:"fold",children:"fold"}),"\n",(0,s.jsx)(n.p,{children:"Applies a function to each element of the array, returning the final accumulated value. The first\nparameter is the initial value."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn fold<U>(self, mut accumulator: U, f: fn(U, T) -> U) -> U\n"})}),"\n",(0,s.jsx)(n.p,{children:"This is a left fold, so the given function will be applied to the accumulator and first element of\nthe array, then the second, and so on. For a given call the expected result would be equivalent to:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"let a1 = [1];\nlet a2 = [1, 2];\nlet a3 = [1, 2, 3];\n\nlet f = |a, b| a - b;\na1.fold(10, f)  //=> f(10, 1)\na2.fold(10, f)  //=> f(f(10, 1), 2)\na3.fold(10, f)  //=> f(f(f(10, 1), 2), 3)\n"})}),"\n",(0,s.jsx)(n.p,{children:"example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"\nfn main() {\n    let arr = [2, 2, 2, 2, 2];\n    let folded = arr.fold(0, |a, b| a + b);\n    assert(folded == 10);\n}\n\n"})}),"\n",(0,s.jsx)(n.h3,{id:"reduce",children:"reduce"}),"\n",(0,s.jsx)(n.p,{children:"Same as fold, but uses the first element as the starting element."}),"\n",(0,s.jsxs)(n.p,{children:["Requires ",(0,s.jsx)(n.code,{children:"self"})," to be non-empty."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn reduce(self, f: fn(T, T) -> T) -> T\n"})}),"\n",(0,s.jsx)(n.p,{children:"example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let arr = [2, 2, 2, 2, 2];\n    let reduced = arr.reduce(|a, b| a + b);\n    assert(reduced == 10);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"all",children:"all"}),"\n",(0,s.jsx)(n.p,{children:"Returns true if all the elements satisfy the given predicate"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn all(self, predicate: fn(T) -> bool) -> bool\n"})}),"\n",(0,s.jsx)(n.p,{children:"example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let arr = [2, 2, 2, 2, 2];\n    let all = arr.all(|a| a == 2);\n    assert(all);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"any",children:"any"}),"\n",(0,s.jsx)(n.p,{children:"Returns true if any of the elements satisfy the given predicate"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn any(self, predicate: fn(T) -> bool) -> bool\n"})}),"\n",(0,s.jsx)(n.p,{children:"example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let arr = [2, 2, 2, 2, 5];\n    let any = arr.any(|a| a == 5);\n    assert(any);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"concat",children:"concat"}),"\n",(0,s.jsx)(n.p,{children:"Concatenates this array with another array."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn concat<let M: u32>(self, array2: [T; M]) -> [T; N + M]\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let arr1 = [1, 2, 3, 4];\n    let arr2 = [6, 7, 8, 9, 10, 11];
1\n    let concatenated_arr = arr1.concat(arr2);\n    assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"as_str_unchecked",children:"as_str_unchecked"}),"\n",(0,s.jsxs)(n.p,{children:["Converts a byte array of type ",(0,s.jsx)(n.code,{children:"[u8; N]"})," to a string. Note that this performs no UTF-8 validation -\nthe given array is interpreted as-is as a string."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"impl<let N: u32> [u8; N] {\n    pub fn as_str_unchecked(self) -> str<N>\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:'fn main() {\n    let hi = [104, 105].as_str_unchecked();\n    assert_eq(hi, "hi");\n}\n'})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(o,{...e})}):o(e)}},28453(e,n,a){a.d(n,{R:()=>t,x:()=>l});var r=a(96540);const s={},i=r.createContext(s);function t(e){const n=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.