<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.nixos.org/w/index.php?action=history&amp;feed=atom&amp;title=Nix_Evaluation_Performance</id>
	<title>Nix Evaluation Performance - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.nixos.org/w/index.php?action=history&amp;feed=atom&amp;title=Nix_Evaluation_Performance"/>
	<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;action=history"/>
	<updated>2026-04-04T07:44:58Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.0</generator>
	<entry>
		<id>https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8969&amp;oldid=prev</id>
		<title>imported&gt;Infinisil at 15:07, 17 April 2023</title>
		<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8969&amp;oldid=prev"/>
		<updated>2023-04-17T15:07:57Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 15:07, 17 April 2023&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l140&quot;&gt;Line 140:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 140:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Using Thunks to Your Advantage ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Using Thunks to Your Advantage ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;TODO: Explain how to use thunks to avoid duplicating work. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Move &lt;/del&gt;let bindings out as far as possible. Show how attribute sets or lists can be used for memoization.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;TODO: Explain how to use thunks to avoid duplicating work. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Often it makes sense to move &lt;/ins&gt;let bindings out as far as possible&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;, but sometimes that can even cause extra thunks to be allocated&lt;/ins&gt;. Show how attribute sets or lists can be used for memoization.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mediawiki:diff:1.41:old-8968:rev-8969:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>imported&gt;Infinisil</name></author>
	</entry>
	<entry>
		<id>https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8968&amp;oldid=prev</id>
		<title>imported&gt;Infinisil: Fix numbered list</title>
		<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8968&amp;oldid=prev"/>
		<updated>2021-06-29T13:19:47Z</updated>

		<summary type="html">&lt;p&gt;Fix numbered list&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 13:19, 29 June 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l24&quot;&gt;Line 24:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 24:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that when you see e.g. &amp;lt;code&amp;gt;&amp;quot;hello&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; in Nix, you know that Nix won&amp;#039;t allocate a thunk for that. The reason for this is that there&amp;#039;s not much to evaluate there, putting it into a thunk wouldn&amp;#039;t make much sense.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that when you see e.g. &amp;lt;code&amp;gt;&amp;quot;hello&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; in Nix, you know that Nix won&amp;#039;t allocate a thunk for that. The reason for this is that there&amp;#039;s not much to evaluate there, putting it into a thunk wouldn&amp;#039;t make much sense.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: Note however that this is &amp;#039;&amp;#039;not&amp;#039;&amp;#039; the case for &amp;lt;code&amp;gt;&amp;quot;Hello ${name}&amp;quot;&amp;lt;/code&amp;gt;, because that is desugared to &amp;lt;code&amp;gt;&amp;quot;Hello &amp;quot; + name&amp;lt;/code&amp;gt; underneath, which won&amp;#039;t be a string by itself anymore&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: Note however that this is &amp;#039;&amp;#039;not&amp;#039;&amp;#039; the case for &amp;lt;code&amp;gt;&amp;quot;Hello ${name}&amp;quot;&amp;lt;/code&amp;gt;, because that is desugared to &amp;lt;code&amp;gt;&amp;quot;Hello &amp;quot; + name&amp;lt;/code&amp;gt; underneath, which won&amp;#039;t be a string by itself anymore&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# Nix won&amp;#039;t create thunks for referenced variables&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# Nix won&amp;#039;t create thunks for referenced variables&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that once you defined a variable in a &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expression, or you&amp;#039;re in a function that received some arguments at the top, Nix won&amp;#039;t create extra thunks for when you reference these variables.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that once you defined a variable in a &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expression, or you&amp;#039;re in a function that received some arguments at the top, Nix won&amp;#039;t create extra thunks for when you reference these variables.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: It makes a lot of sense for Nix to do this, because variables themselves already point to either a thunk or an evaluated value, which can be used directly and doesn&amp;#039;t need to be wrapped in another thunk that would just say &amp;quot;Evaluate this variable&amp;quot;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: It makes a lot of sense for Nix to do this, because variables themselves already point to either a thunk or an evaluated value, which can be used directly and doesn&amp;#039;t need to be wrapped in another thunk that would just say &amp;quot;Evaluate this variable&amp;quot;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# The following expressions attempt to create thunks if allowed by above two rules&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# The following expressions attempt to create thunks if allowed by above two rules&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#* &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expressions attempt to create a thunk for each variable&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#* &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expressions attempt to create a thunk for each variable&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mediawiki:diff:1.41:old-8967:rev-8968:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>imported&gt;Infinisil</name></author>
	</entry>
	<entry>
		<id>https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8967&amp;oldid=prev</id>
		<title>imported&gt;Infinisil: Correct mistaken explanation regarding referenced variables; Nix wouldn&#039;t evaluate the original expression multiple times if variables were to create new thunks</title>
		<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8967&amp;oldid=prev"/>
		<updated>2021-06-29T13:19:04Z</updated>

		<summary type="html">&lt;p&gt;Correct mistaken explanation regarding referenced variables; Nix wouldn&amp;#039;t evaluate the original expression multiple times if variables were to create new thunks&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 13:19, 29 June 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l27&quot;&gt;Line 27:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 27:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# Nix won&amp;#039;t create thunks for referenced variables&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# Nix won&amp;#039;t create thunks for referenced variables&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that once you defined a variable in a &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expression, or you&amp;#039;re in a function that received some arguments at the top, Nix won&amp;#039;t create extra thunks for when you reference these variables.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that once you defined a variable in a &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expression, or you&amp;#039;re in a function that received some arguments at the top, Nix won&amp;#039;t create extra thunks for when you reference these variables.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;This &lt;/del&gt;makes a lot of sense, because &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;if Nix &#039;&#039;would&#039;&#039; create new thunks&lt;/del&gt;, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the thunks wouldn&lt;/del&gt;&#039;t &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;share any work between each other&lt;/del&gt;. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Each use of a variable would have to reevaluate its original expression!&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;It &lt;/ins&gt;makes a lot of sense &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;for Nix to do this&lt;/ins&gt;, because &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;variables themselves already point to either a thunk or an evaluated value&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;which can be used directly and doesn&lt;/ins&gt;&#039;t &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;need to be wrapped in another thunk that would just say &quot;Evaluate this variable&quot;&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# The following expressions attempt to create thunks if allowed by above two rules&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# The following expressions attempt to create thunks if allowed by above two rules&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mediawiki:diff:1.41:old-8966:rev-8967:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>imported&gt;Infinisil</name></author>
	</entry>
	<entry>
		<id>https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8966&amp;oldid=prev</id>
		<title>imported&gt;Sternenseemann: Fix &quot;Hello ${name}&quot; desugaring</title>
		<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8966&amp;oldid=prev"/>
		<updated>2021-06-29T09:11:47Z</updated>

		<summary type="html">&lt;p&gt;Fix &amp;quot;Hello ${name}&amp;quot; desugaring&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 09:11, 29 June 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l23&quot;&gt;Line 23:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 23:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This includes &amp;lt;code&amp;gt;integers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floats&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;strings&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;paths&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;booleans&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This includes &amp;lt;code&amp;gt;integers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floats&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;strings&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;paths&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;booleans&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that when you see e.g. &amp;lt;code&amp;gt;&amp;quot;hello&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; in Nix, you know that Nix won&amp;#039;t allocate a thunk for that. The reason for this is that there&amp;#039;s not much to evaluate there, putting it into a thunk wouldn&amp;#039;t make much sense.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: This means that when you see e.g. &amp;lt;code&amp;gt;&amp;quot;hello&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; in Nix, you know that Nix won&amp;#039;t allocate a thunk for that. The reason for this is that there&amp;#039;s not much to evaluate there, putting it into a thunk wouldn&amp;#039;t make much sense.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: Note however that this is &#039;&#039;not&#039;&#039; the case for &amp;lt;code&amp;gt;&quot;Hello ${name}&quot;&amp;lt;/code&amp;gt;, because that is desugared to &amp;lt;code&amp;gt;&quot;Hello&quot; + name&amp;lt;/code&amp;gt; underneath, which won&#039;t be a string by itself anymore&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#: Note however that this is &#039;&#039;not&#039;&#039; the case for &amp;lt;code&amp;gt;&quot;Hello ${name}&quot;&amp;lt;/code&amp;gt;, because that is desugared to &amp;lt;code&amp;gt;&quot;Hello &quot; + name&amp;lt;/code&amp;gt; underneath, which won&#039;t be a string by itself anymore&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# Nix won&amp;#039;t create thunks for referenced variables&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# Nix won&amp;#039;t create thunks for referenced variables&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mediawiki:diff:1.41:old-8965:rev-8966:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>imported&gt;Sternenseemann</name></author>
	</entry>
	<entry>
		<id>https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8965&amp;oldid=prev</id>
		<title>imported&gt;Infinisil at 04:55, 29 June 2021</title>
		<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8965&amp;oldid=prev"/>
		<updated>2021-06-29T04:55:00Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 04:55, 29 June 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l140&quot;&gt;Line 140:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 140:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/syntaxHighlight&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/syntaxHighlight&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Using Thunks to Your Advantage ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;=&lt;/ins&gt;== Using Thunks to Your Advantage &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;=&lt;/ins&gt;==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;TODO: Explain how to use thunks to avoid duplicating work. Move let bindings out as far as possible. Show how attribute sets or lists can be used for memoization.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;TODO: Explain how to use thunks to avoid duplicating work. Move let bindings out as far as possible. Show how attribute sets or lists can be used for memoization.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mediawiki:diff:1.41:old-8964:rev-8965:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>imported&gt;Infinisil</name></author>
	</entry>
	<entry>
		<id>https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8964&amp;oldid=prev</id>
		<title>imported&gt;Infinisil: Adding section on thunks</title>
		<link rel="alternate" type="text/html" href="https://wiki.nixos.org/w/index.php?title=Nix_Evaluation_Performance&amp;diff=8964&amp;oldid=prev"/>
		<updated>2021-06-29T04:50:07Z</updated>

		<summary type="html">&lt;p&gt;Adding section on thunks&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;TODO: Explain that not only thunks are important for performance and memory usage, but other things as well, such as function calls, number of attributes, number of values in general (includes thunks), etc. Pretty much most of the &amp;lt;code&amp;gt;NIX_SHOW_STATS&amp;lt;/code&amp;gt; metrics.&lt;br /&gt;
&lt;br /&gt;
TODO: Explain how to profile Nix with &amp;lt;code&amp;gt;NIX_PROFILE&amp;lt;/code&amp;gt; and other ways.&lt;br /&gt;
&lt;br /&gt;
== Thunks ==&lt;br /&gt;
&lt;br /&gt;
=== What are thunks ===&lt;br /&gt;
In Nix, thunks are used to implement laziness. A thunk is a type of Nix value that is not yet evaluated. It is only evaluated once needed. It consists of:&lt;br /&gt;
* The expression that the value should be evaluated from&lt;br /&gt;
* The environment in which the expression should be evaluated, aka the variables in scope&lt;br /&gt;
&lt;br /&gt;
It is very easy to introduce a lot of thunks in Nix code, which can have negative consequences:&lt;br /&gt;
* Every new thunk requires heap memory allocation&lt;br /&gt;
* A thunk prevents the evaluation garbage collector from collecting any variables from the referenced environment, causing not only the memory of the chunk itself to be kept alive, but also all its references&lt;br /&gt;
* Too deeply nested thunk chains can lead to stack overflows when evaluated&lt;br /&gt;
&lt;br /&gt;
Of course, thunks are essential to Nix, so it&amp;#039;s not possible to avoid them. And in fact, using thunks properly can improve performance.&lt;br /&gt;
&lt;br /&gt;
=== When thunks are created ===&lt;br /&gt;
The rules of thunk creation in Nix are relatively straightforward.&lt;br /&gt;
&lt;br /&gt;
# Nix won&amp;#039;t create thunks for atomic expressions&lt;br /&gt;
#: This includes &amp;lt;code&amp;gt;integers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floats&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;strings&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;paths&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;booleans&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;&lt;br /&gt;
#: This means that when you see e.g. &amp;lt;code&amp;gt;&amp;quot;hello&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; in Nix, you know that Nix won&amp;#039;t allocate a thunk for that. The reason for this is that there&amp;#039;s not much to evaluate there, putting it into a thunk wouldn&amp;#039;t make much sense.&lt;br /&gt;
#: Note however that this is &amp;#039;&amp;#039;not&amp;#039;&amp;#039; the case for &amp;lt;code&amp;gt;&amp;quot;Hello ${name}&amp;quot;&amp;lt;/code&amp;gt;, because that is desugared to &amp;lt;code&amp;gt;&amp;quot;Hello&amp;quot; + name&amp;lt;/code&amp;gt; underneath, which won&amp;#039;t be a string by itself anymore&lt;br /&gt;
&lt;br /&gt;
# Nix won&amp;#039;t create thunks for referenced variables&lt;br /&gt;
#: This means that once you defined a variable in a &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expression, or you&amp;#039;re in a function that received some arguments at the top, Nix won&amp;#039;t create extra thunks for when you reference these variables.&lt;br /&gt;
#: This makes a lot of sense, because if Nix &amp;#039;&amp;#039;would&amp;#039;&amp;#039; create new thunks, the thunks wouldn&amp;#039;t share any work between each other. Each use of a variable would have to reevaluate its original expression!&lt;br /&gt;
&lt;br /&gt;
# The following expressions attempt to create thunks if allowed by above two rules&lt;br /&gt;
#* &amp;lt;code&amp;gt;let in&amp;lt;/code&amp;gt; expressions attempt to create a thunk for each variable&lt;br /&gt;
#* &amp;lt;code&amp;gt;{ ... }&amp;lt;/code&amp;gt; (attribute set) expressions attempt to create a thunk for each attribute&lt;br /&gt;
#* &amp;lt;code&amp;gt;[ ... ]&amp;lt;/code&amp;gt; (list) expressions attempt to create a thunk for each element&lt;br /&gt;
#* &amp;lt;code&amp;gt;f a&amp;lt;/code&amp;gt; (function application) expressions attempt to create a thunk for the argument&lt;br /&gt;
#* &amp;lt;code&amp;gt;{ attr ? def }: ...&amp;lt;/code&amp;gt;: For every function evaluation where the function takes an attribute set where an attribute has a default value which &amp;#039;&amp;#039;doesn&amp;#039;t&amp;#039;&amp;#039; exist in the passed argument, a thunk for the default value is attempted to be created&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
The following shows an illustrative example of when and how many thunks are allocated. The comments give the thunk counts and explanation in the format&lt;br /&gt;
&amp;lt;syntaxHighlight lang=nix&amp;gt;&lt;br /&gt;
# total (+difference) Explanation&lt;br /&gt;
&amp;lt;/syntaxHighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxHighlight lang=nix&amp;gt;&lt;br /&gt;
# let in expressions can allocate thunks&lt;br /&gt;
let&lt;br /&gt;
&lt;br /&gt;
  # 0 (+0) No thunk allocated because strings are atomic value expressions&lt;br /&gt;
  name = &amp;quot;Paul&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  # 1 (+1) Thunk is allocated, because the + operator is neither an atomic&lt;br /&gt;
  # value nor a direct variable&lt;br /&gt;
  greeting = &amp;quot;Hello, &amp;quot; + name;&lt;br /&gt;
&lt;br /&gt;
  # 1 (+0) No thunk is allocated because greeting is a direct variable&lt;br /&gt;
  result1 = greeting;&lt;br /&gt;
&lt;br /&gt;
  # 2 (+1) This let in variable creates a new thunk, but the attribute itself&lt;br /&gt;
  # isn&amp;#039;t evaluated, meaning it also won&amp;#039;t create any thunks for its values&lt;br /&gt;
  deadAttrs = {&lt;br /&gt;
    deadName = &amp;quot;dead &amp;quot; + &amp;quot;value&amp;quot;;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  # 4 (+2) One for the variable, but also one for the value inside, because the&lt;br /&gt;
  # attribute itself is evaluated&lt;br /&gt;
  attrs = {&lt;br /&gt;
    name = &amp;quot;alive &amp;quot; + &amp;quot;value&amp;quot;;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  # 5 (+1) Intermediate result, forcing evaluation of the attrs, one thunk for&lt;br /&gt;
  # the variable declaration. Note that this is a function call, but because&lt;br /&gt;
  # both arguments are variables, no extra thunks are allocated&lt;br /&gt;
  result2 = builtins.seq attrs null;&lt;br /&gt;
&lt;br /&gt;
  # 7 (+2) Same with a list which is evaluated&lt;br /&gt;
  list = [&lt;br /&gt;
    (&amp;quot;alive &amp;quot; + &amp;quot;value&amp;quot;)&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
  # 8 (+1) And again, another intemediate result&lt;br /&gt;
  result3 = builtins.seq list result2;&lt;br /&gt;
&lt;br /&gt;
  # 10 (+2) Just two variables, a normal function doesn&amp;#039;t allocate a thunk on&lt;br /&gt;
  # its own&lt;br /&gt;
  fun = a: a;&lt;br /&gt;
  result4 = builtins.seq fun result3;&lt;br /&gt;
&lt;br /&gt;
  # 13 (+3) However if the function is applied to a non-atom, non-variable&lt;br /&gt;
  # value, a thunk for the argument is created&lt;br /&gt;
  app = fun (1 + 1);&lt;br /&gt;
  result5 = builtins.seq app result4;&lt;br /&gt;
&lt;br /&gt;
  # 16 (+3) A function with a default attribute argument can allocate a thunk&lt;br /&gt;
  # for the default argument if it isn&amp;#039;t passed&lt;br /&gt;
  attrApp = ({ notPassed ? 1 + 1, ... }: null) attrs;&lt;br /&gt;
  result6 = builtins.seq attrApp result5;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  # Let bindings can allocate thunks even if their variables are unused&lt;br /&gt;
  #  -&amp;gt; Push let bindings outside as much as possible!&lt;br /&gt;
  # 16 (+2) Outer let bindings&lt;br /&gt;
  # 19 (+3) inner let bindings, one for every iteration&lt;br /&gt;
  # 23 (+2) for the two non-atomic/non-variable function argument&lt;br /&gt;
  # 23 (+0) Atomic value list elements&lt;br /&gt;
  lets = map (x:&lt;br /&gt;
    let y = 1 + 1;&lt;br /&gt;
    in x&lt;br /&gt;
  ) [ 1 2 3 ];&lt;br /&gt;
  result7 = builtins.deepSeq lets result6;&lt;br /&gt;
&lt;br /&gt;
  # 24 (+1) One variable&lt;br /&gt;
  values = [ 1 2 3 ];&lt;br /&gt;
&lt;br /&gt;
  # 27 (+3) Three variables next&lt;br /&gt;
  # 27 (+0) Function receives variable as argument -&amp;gt; no extra thunk&lt;br /&gt;
  elAt = builtins.elemAt values;&lt;br /&gt;
  # 27 (+0) Function called three times, but all arguments don&amp;#039;t need thunks&lt;br /&gt;
  elAtApp = elAt 0 + elAt 1 + elAt 2;&lt;br /&gt;
  result8 = builtins.seq elAtApp result7;&lt;br /&gt;
&lt;br /&gt;
  # 29 (+2) Two variables next&lt;br /&gt;
  # 29 (+0) Function (and nested function) called three times,&lt;br /&gt;
  # but all arguments don&amp;#039;t need thunks&lt;br /&gt;
  elemAtApp = builtins.elemAt values 0&lt;br /&gt;
    + builtins.elemAt values 1&lt;br /&gt;
    + builtins.elemAt values 2;&lt;br /&gt;
  result9 = builtins.seq elemAtApp result8;&lt;br /&gt;
&lt;br /&gt;
in result9&lt;br /&gt;
&amp;lt;/syntaxHighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can verify the final thunk count by using the &amp;lt;code&amp;gt;NIX_SHOW_STATS&amp;lt;/code&amp;gt; environment variable. The above file is assumed to be in &amp;lt;code&amp;gt;thunks.nix&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxHighlight lang=bash&amp;gt;&lt;br /&gt;
$ NIX_SHOW_STATS=1 NIX_SHOW_STATS_PATH=stats.json \&lt;br /&gt;
  nix-instantiate --eval thunks.nix&lt;br /&gt;
null&lt;br /&gt;
$ jq .nrThunks stats.json&lt;br /&gt;
29&lt;br /&gt;
&amp;lt;/syntaxHighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using Thunks to Your Advantage ==&lt;br /&gt;
&lt;br /&gt;
TODO: Explain how to use thunks to avoid duplicating work. Move let bindings out as far as possible. Show how attribute sets or lists can be used for memoization.&lt;/div&gt;</summary>
		<author><name>imported&gt;Infinisil</name></author>
	</entry>
</feed>