= ``zexp``s, store paths, and context
:page-pagination:

In Nix, strings carry around a "context", corresponding to a list of
dependencies that string has. For example, the `outPath` of a derivation in Nix
has a context that contains its derivation, plus the output name. When strings
are concatenated, their contexts are merged together.

In Zilch, a similar concept exists; encapsulated in so-called "zexpressions".
A `zexpr` is a lazily evaluated thunk that, when evaluated, has access to other
``zexpr``s and closely related objects. When a `zexpr` is unwrapped, it returns
the resulting value, plus a list of derivations and outputs that are depended
on.

[source,scheme]
----
(define example (zexp foo))
;; #<zexp val: foo>

(zexp-unwrap example)
;; #<zexp-evaluation val: foo; drvs: (); srcs: ()>
----

The primary way a zexp that contains context is made, is by using
xref:generated:zilch.magic.adoc#store-path-for-drv[`store-path-for-drv`] and xref:generated:zilch.magic.adoc#store-path-for-ca-drv[`store-path-for-ca-drv`]. This returns a
`<store-path>`, which can be unwrapped like a `zexp`.

[source,scheme]
----
(define drv
 (store-path-for-drv
  "hello" "x86_64-linux"
  '("/bin/sh" "-c" "echo hi > $out") '()
  '("out"))

;; (("out"
;;   . #<store path /nix/store/mjs27ix6ig2bkbi3s3sm470vrv4lf7ic-hello
;;       (/nix/store/76w21n1f03fs5kw8fnffphx7qrqffw6r-hello.drv!out)>))

(zexp-unwrap (cdar drv))
;; #<zexp-evaluation
;;   val: "/nix/store/mjs27ix6ig2bkbi3s3sm470vrv4lf7ic-hello";
;;   drvs: ((#<derivation …> "out"));
;;   srcs: ()>
----

A `zexp` behaves similarly to the `quasiquote` macro, in that it is possible to
use `unquote` (or its reader syntax) to unquote values. Unquoting a `zexp`,
however, requires a special mechanism, and is executed before `unquote`. This
allows for full expressiveness when generating, for example, arguments or
environments for derivations.

[source,scheme]
----
(define complex
 (zexp
  (unquote
   (string-append
    "The path for the derivation's output is "
    (zexp-unquote (cdar #3)))))

(zexp-unwrap complex)
;; #<zexp-evaluation
;;   val: "The path for the derivation's output is /nix/store/mjs27ix6ig2bkbi3s3sm470vrv4lf7ic-hello";
;;   drvs: ((#<derivation …> "out"));
;;   srcs: ()>
----

A store path, after being created by `store-path-for-(ca-)drv`, is not
guaranteed to exist in the store. To ensure it exists, xref:generated:zilch.magic.adoc#store-path-materialize[`store-path-materialize`]
is used; this is transparently done when a `store-path` is unwrapped inside a
`zexp`.

== Reader syntax
For convenience, `+#~foo+` is used as reader syntax for `(zexp foo)`, while
`+#$foo+` and `+#$@foo+` are syntax for `(zexp-unwrap foo)` and `(zexp-unquote-splicing foo)`
respectively.

