PageSourceSearch

https://noir-lang.org/docs/assets/js/ee04318f.c542d9c2.js

js noir-lang.org collected 2026-10-03 22:53:37 UTC 6,209 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[2919],{76109(e,n,t){t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"language/mutability","title":"Mutability","description":"Learn about mutable variables in Noir. Discover how to declare, modify, and use them in your programs.","source":"@site/versioned_docs/version-v1.0.0-beta.26/language/mutability.md","sourceDirName":"language","slug":"/language/mutability","permalink":"/docs/v1.0.0-beta.26/language/mutability","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-beta.26/language/mutability.md","tags":[],"version":"v1.0.0-beta.26","frontMatter":{"title":"Mutability","description":"Learn about mutable variables in Noir. Discover how to declare, modify, and use them in your programs.","keywords":["noir programming language","mutability in noir","mutable variables"]},"sidebar":"sidebar","previous":{"title":"Global Variables","permalink":"/docs/v1.0.0-beta.26/language/globals"},"next":{"title":"Lambdas","permalink":"/docs/v1.0.0-beta.26/language/lambdas"}}');var r=t(74848),i=t(28453);const s={title:"Mutability",description:"Learn about mutable variables in Noir. Discover how to declare, modify, and use them in your programs.",keywords:["noir programming language","mutability in noir","mutable variables"]},l=void 0,o={},c=[{value:"Non-local mutability",id:"non-local-mutability",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Variables in noir can be declared mutable via the ",(0,r.jsx)(n.code,{children:"mut"})," keyword. Mutable variables can be reassigned\nto via an assignment expression."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"let x = 2;\nx = 3; // error: x must be mutable to be assigned to\n\nlet mut y = 3;\nlet y = 4; // OK\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"mut"})," modifier can also apply to patterns:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"let (a, mut b) = (1, 2);\na = 11; // error: a must be mutable to be assigned to\nb = 12; // OK\n\nlet mut (c, d) = (3, 4);\nc = 13; // OK\nd = 14; // OK\n\n// etc.\nlet MyStruct { x: mut y } = MyStruct { x: a };\n// y is now in scope\n"})}),"\n",(0,r.jsx)(n.p,{children:"Note that mutability in noir is local and everything is passed by value, so if a called function\nmutates its parameters then the parent function will keep the old value of the parameters."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"fn main() -> pub Field {\n    let x = 3;\n    helper(x);\n    x // x is still 3\n}\n\nfn helper(mut x: i32) {\n    x = 4;\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"non-local-mutability",children:"Non-local mutability"}),"\n",(0,r.jsxs)(n.p,{children:["Non-local mutability can be achieved through the ",(0,r.jsxs)(n.a,{href:"/docs/v1.0.0-beta.26/language/data_types/references",children:["mutable reference type ",(0,r.jsx)(n.code,{children:"&mut T"})]}),". Noir also supports immutable references (",(0,r.jsx)(n.code,{children:"&T"}),") for read-only access \u2014 see ",(0,r.jsx)(n.a,{href:"/docs/v1.0.0-beta.26/language/data_types/references",children:"References"})," for details on both reference types."]}),"\n",(0,r.jsxs)(n.p,{children:["Mutable references are created with ",(0,r.jsx)(n.code,{children:"&mut"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"fn set_to_zero(x: &mut Field) {\n    *x = 0;\n}\n\nfn main() {\n    let mut y = 42;\n    set_to_zero(&mut y);\n    assert(*y == 0);\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["When creating a mutable reference, the original variable being referred to (",(0,r.jsx)(n.code,{children:"y"})," in this\nexample) must also be mutable. Since mutable references are a reference type, they must\nbe explicitly dereferenced via ",(0,r.jsx)(n.code,{children:"*"})," to retrieve the underlying value. Note that this yields\na copy of the value, so mutating this copy will not change the original value behind the\nreference:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"fn main() {\n    let mut x = 1;\n    let x_ref = &mut x;\n\n    let mut y = *x_ref;\n    let y_ref = &mut y;\n\n    x = 2;\n    *x_ref = 3;\n\n    y = 4;\n    *y_ref = 5;\n\n    assert(x == 3);\n    assert(*x_ref == 3);\n    assert(y == 5);\n    assert(*y_ref == 5);\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"Note that types in Noir are actually deeply immutable so the copy that occurs when\ndereferencing is only a conceptual copy - no additional constraints will occur."}),"\n",(0,r.jsx)(n.p,{children:"Mutable references can also be stored within structs. Note that there is also\nno lifetime parameter on these unlike rust. This is because the allocated memory\nalways lasts the entire program - as if it were an array of one element."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"struct Foo {\n    x: &mut Field\n}\n\nimpl Foo {\n    fn incr(mut self) {\n        *self.x += 1;\n    }\n}\n\nfn main() {\n    let foo = Foo { x: &mut 0 };\n    foo.incr();\n    assert(*foo.x == 1);\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"In general, you should avoid non-local & shared mutability unless it is needed. Sticking\nto only local mutability will improve readability and potentially improve c
1ompiler optimizations as well."})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},28453(e,n,t){t.d(n,{R:()=>s,x:()=>l});var a=t(96540);const r={},i=a.createContext(r);function s(e){const n=a.useContext(i);return a.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(r):e.components||r:s(e.components),a.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.