mirror of
https://github.com/NixOS/nix.git
synced 2024-11-22 06:42:28 +00:00
Value: use std::span, change use of const
**`Value` and `const`** These two deserve some explanation. We'll get to lists later. Values can normally be thought of as immutable, except they are are also the vehicle for call by need, which must be implemented using mutation. This circumstance makes a `const Value` a rather useless thing: - If it's a thunk, you can't evaluate it, except by copying, but that would not be call by need. - If it's not a thunk, you know the type, so the method that acquired it for you should have returned something more specific, such as a `const Bindings &` (which actually does make sense because that's an immutable span of pointers to mutable `Value`s. - If you don't care about the type yet, you might establish the convention that `const Value` means `deepSeq`-ed data, but this is hardly useful and not actually as safe as you would supposedly want to trust it to be - just convention. **Lists** `std::span` is a tuple of pointer and size - just what we need. We don't return them as `const Value`, because considering the first bullet point we discussed before, we'd have to force all the list values, which isn't what we want. So what we end up with is a nice representation of a list in weak head normal form: the spine is immutable, but the items may need some evaluation later.
This commit is contained in:
parent
7055c65285
commit
260c614762
@ -3,6 +3,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <span>
|
||||
|
||||
#include "symbol-table.hh"
|
||||
#include "value/context.hh"
|
||||
@ -395,7 +396,13 @@ public:
|
||||
return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
|
||||
}
|
||||
|
||||
const Value * const * listElems() const
|
||||
std::span<Value * const> listItems() const
|
||||
{
|
||||
assert(isList());
|
||||
return std::span<Value * const>(listElems(), listSize());
|
||||
}
|
||||
|
||||
Value * const * listElems() const
|
||||
{
|
||||
return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
|
||||
}
|
||||
@ -414,34 +421,6 @@ public:
|
||||
*/
|
||||
bool isTrivial() const;
|
||||
|
||||
auto listItems()
|
||||
{
|
||||
struct ListIterable
|
||||
{
|
||||
typedef Value * const * iterator;
|
||||
iterator _begin, _end;
|
||||
iterator begin() const { return _begin; }
|
||||
iterator end() const { return _end; }
|
||||
};
|
||||
assert(isList());
|
||||
auto begin = listElems();
|
||||
return ListIterable { begin, begin + listSize() };
|
||||
}
|
||||
|
||||
auto listItems() const
|
||||
{
|
||||
struct ConstListIterable
|
||||
{
|
||||
typedef const Value * const * iterator;
|
||||
iterator _begin, _end;
|
||||
iterator begin() const { return _begin; }
|
||||
iterator end() const { return _end; }
|
||||
};
|
||||
assert(isList());
|
||||
auto begin = listElems();
|
||||
return ConstListIterable { begin, begin + listSize() };
|
||||
}
|
||||
|
||||
SourcePath path() const
|
||||
{
|
||||
assert(internalType == tPath);
|
||||
|
Loading…
Reference in New Issue
Block a user