| 15 Nov 2023 |
Ilan Joselevich (Kranzes) | (Dave showed me at oceansprint how he made mkDerivation use evalModules in nixpkgs, it's sick 🔥) | 16:59:28 |
DavHau | It trades significantly better UX vs twice the eval time. Maybe it could be released as an overlay for people who don't care much about eval time. direnv recently got a feature where it caches evaluation indefinitely until 'nix-direnv-reload' is executed manually. The way slow eval times are a lot less annoying than before. | 17:23:27 |
DavHau | * It trades significantly better UX vs twice the eval time. Maybe it could be released as an overlay for people who don't care much about eval time. direnv recently got a feature where it caches evaluation indefinitely until 'nix-direnv-reload' is executed manually. That way slow eval times are a lot less annoying than before. | 17:23:53 |
| Alyssa Ross | 17:40:09 |
| NixOS Moderation Botchanged room power levels. | 18:12:25 |
| NixOS Moderation Botchanged room power levels. | 18:12:25 |
| @eisfunke:eisfunke.com changed their profile picture. | 22:42:08 |
| 18 Nov 2023 |
infinisil | Highlighting @abathur's issue: https://github.com/nixpkgs-architecture/issues/issues/23 | 04:07:31 |
| 19 Nov 2023 |
| pbsds changed their display name from pbsds to pbsds (federation borken, may not see reply). | 03:36:21 |
| ZXGU joined the room. | 11:02:45 |
| pbsds changed their display name from pbsds (federation borken, may not see reply) to pbsds. | 20:39:20 |
| 20 Nov 2023 |
@johannes.kirschbauer:scs.ems.host | In reply to @piegames:matrix.org Are there any specific proposals for how a Nix module builtin might look like? Playing mindgames:
If types are values. We could extend the language by type-values. e.g.
Primitives:
Number, ... Composed:
Set, List, ...
{
/* A type contract, foo must be a number*/
foo = Number;
} &
{
/* foo is '1' */
foo = 1;
}
{}
| 10:03:41 |
@johannes.kirschbauer:scs.ems.host | In reply to @piegames:matrix.org Are there any specific proposals for how a Nix module builtin might look like? * Playing mindgames:
If types are values. We could extend the language by type-values. e.g.
Primitives:
Number, ... Composed:
Set, List, ...
{
/* A type contract, foo must be a number*/
foo = Number;
} &
{
/* foo is '1' */
foo = 1;
}
Introducing new keywords for types ^^
| 10:04:04 |
@johannes.kirschbauer:scs.ems.host | * Playing mindgames:
If types are values. We could extend the language by type-values. e.g.
Primitives:
Number, ... Composed:
Set, List, ...
{
/* A type contract, foo must be a number*/
foo = Number;
} &
{
/* foo is '1' */
foo = 1;
}
Introducing new keywords for types ^^ and the merge operator &
| 10:04:22 |
@piegames:matrix.org | So basically copying over Nickel :) | 10:04:51 |
@johannes.kirschbauer:scs.ems.host | Yes, why not. | 10:06:00 |
@johannes.kirschbauer:scs.ems.host | It resolves the need for our overly complex module system. With a ton of different merge operations | 10:06:59 |
@piegames:matrix.org | I don't disagree | 10:07:19 |
@johannes.kirschbauer:scs.ems.host | let
partialFoo = {
nested = {
foo = Number:
};
}
in
partialFoo & {
nested.foo = 1;
}
You can even use that value as type contract in any other place. e.g. if you want to say that bar is also of type foo.
{
bar = partialFoo & {
nested.foo = 2;
}
}
I kind of like the simplicity.
| 10:14:15 |
@johannes.kirschbauer:scs.ems.host | * let
partialFoo = {
nested = {
foo = Number:
};
}
in
partialFoo & {
nested.foo = 1;
}
You can even use that value as type contract in any other place. e.g. if you want to say that bar is also of type foo.
{
bar = partialFoo & {
nested.foo = 2;
}
}
I kind of like the simplicity.
| 10:14:51 |
@johannes.kirschbauer:scs.ems.host | * let
partialFoo = {
nested = {
foo = Number:
};
};
in
partialFoo & {
nested.foo = 1;
}
You can even use that value as type contract in any other place. e.g. if you want to say that bar is also of type foo.
{
bar = partialFoo & {
nested.foo = 2;
}
}
I kind of like the simplicity.
| 10:15:03 |
@johannes.kirschbauer:scs.ems.host | Hm nickel is still different i think. | 10:21:05 |
| 21 Nov 2023 |
| Eelco changed their display name from niksnut to Eelco. | 16:36:55 |
| 24 Nov 2023 |
@yannham:matrix.org | FWIW, In Nickel, currently you can't merge a contract and a number directlylike Number & 1 (maybe it would make sense to do that, but at least for now, we don't). However, because record contracts are no different from normal records (they are just more likely to have mostly annotations and yet-to-be-defined values), there is in theory two ways to "apply" a record contract. One is by setting the contract using =, as in Johannes Kirschbauer @hsjobeki 's example above:
let Contract = { foo | Number } in
{
inner = Contract
} & {
inner.foo = 1
}
Merge will be applied recursively and combine {bar = 1} with {bar | Number} and end up checking that 1 is a Number. However, usually what you want is to use an annotation/metadata (|) instead:
{
inner | Contract
} & {
inner.foo = 1
}
The difference is that the second form is more restrictive: it says "attach a contract Contract to inner". Attaching a contract propagates through merging, even if you override. That is, it means inner can never be changed or updated by merging to something that doesn't respect the initial contract. In particular, the contract is closed by default, meaning you can't add new values (for that, you have to add an ..), while solely merging records propagate the subcontracts but you can always merge with new stuff. Attaching a contract is thus more similar to the CUE model, it "refines" a value with a constraint, and merging just refines more and more.
For example:
nickel> { inner = Contract } & { inner.foo = 1} & {inner.bar = "hello"}
{ inner = { bar = "hello", foo | Number = 1, }, }
# turning the `=` into `|` makes it stricter
nickel> { inner | Contract } & { inner.foo = 1} & {inner.bar = "hello"}
error: contract broken by the value of `inner`: extra field `bar`
[...]
# With `=`, we can override the whole contract
nickel> { inner = Contract } & { inner | force = "something totally different"}
{ inner | force = "something totally different", }
# `|` doesn't let you do that
nickel> {inner | Contract} & { inner | force = "something totally different"}
error: contract broken by the value of `inner`
[...]
| 09:27:24 |
@yannham:matrix.org | * FWIW, In Nickel, currently you can't merge a contract and a number directlylike Number & 1 (maybe it would make sense to do that, but at least for now, we don't). However, because record contracts are no different from normal records (they are just more likely to have mostly annotations and yet-to-be-defined values), there is in theory two ways to "apply" a record contract. One is by setting the contract using =, as in Johannes Kirschbauer @hsjobeki 's example above:
let Contract = { foo | Number } in
{
inner = Contract
} & {
inner.foo = 1
}
Merge will be applied recursively and combine {foo = 1} with {foo | Number} and end up checking that 1 is a Number. However, usually what you want is to use an annotation/metadata (|) instead:
{
inner | Contract
} & {
inner.foo = 1
}
The difference is that the second form is more restrictive: it says "attach a contract Contract to inner". Attaching a contract propagates through merging, even if you override. That is, it means inner can never be changed or updated by merging to something that doesn't respect the initial contract. In particular, the contract is closed by default, meaning you can't add new values (for that, you have to add an ..), while solely merging records propagate the subcontracts but you can always merge with new stuff. Attaching a contract is thus more similar to the CUE model, it "refines" a value with a constraint, and merging just refines more and more.
For example:
nickel> { inner = Contract } & { inner.foo = 1} & {inner.bar = "hello"}
{ inner = { bar = "hello", foo | Number = 1, }, }
# turning the `=` into `|` makes it stricter
nickel> { inner | Contract } & { inner.foo = 1} & {inner.bar = "hello"}
error: contract broken by the value of `inner`: extra field `bar`
[...]
# With `=`, we can override the whole contract
nickel> { inner = Contract } & { inner | force = "something totally different"}
{ inner | force = "something totally different", }
# `|` doesn't let you do that
nickel> {inner | Contract} & { inner | force = "something totally different"}
error: contract broken by the value of `inner`
[...]
| 09:30:53 |
@yannham:matrix.org | The contracts-as-normal-values is also nice to build up new contracts using usual operations, including merging itself. For example, you can write let Combined = Derivation & OtherSpecificContract & {has_some_other_specific_field | String}. It gives you a simple form of "inheritance" (the proper term would be mixins, I think) | 09:39:38 |
@yannham:matrix.org | * FWIW, In Nickel, currently you can't merge a contract and a number directlylike Number & 1 (maybe it would make sense to do that, but at least for now, we don't). However, because record contracts are no different from normal records (they are just more likely to have mostly annotations and yet-to-be-defined values), there are in theory two ways to "apply" a record contract. One is by setting the contract using =, as in Johannes Kirschbauer @hsjobeki 's example above:
let Contract = { foo | Number } in
{
inner = Contract
} & {
inner.foo = 1
}
Merge will be applied recursively and combine {foo = 1} with {foo | Number} and end up checking that 1 is a Number. However, usually what you want is to use an annotation/metadata (|) instead:
{
inner | Contract
} & {
inner.foo = 1
}
The difference is that the second form is more restrictive: it says "attach a contract Contract to inner". Attaching a contract propagates through merging, even if you override. That is, it means inner can never be changed or updated by merging to something that doesn't respect the initial contract. In particular, the contract is closed by default, meaning you can't add new values (for that, you have to add an ..), while solely merging records propagate the subcontracts but you can always merge with new stuff. Attaching a contract is thus more similar to the CUE model, it "refines" a value with a constraint, and merging just refines more and more.
For example:
nickel> { inner = Contract } & { inner.foo = 1} & {inner.bar = "hello"}
{ inner = { bar = "hello", foo | Number = 1, }, }
# turning the `=` into `|` makes it stricter
nickel> { inner | Contract } & { inner.foo = 1} & {inner.bar = "hello"}
error: contract broken by the value of `inner`: extra field `bar`
[...]
# With `=`, we can override the whole contract
nickel> { inner = Contract } & { inner | force = "something totally different"}
{ inner | force = "something totally different", }
# `|` doesn't let you do that
nickel> {inner | Contract} & { inner | force = "something totally different"}
error: contract broken by the value of `inner`
[...]
| 09:52:04 |
| 28 Nov 2023 |
infinisil | @room: The next ~monthly meeting will take place in 1 hour! There's not a lot to discuss from my side, please don't hesitate to add topics you'd like to talk about to the meeting notes agenda. Meeting link | 13:04:15 |
nbp | Here is the reason why I think a module system (not only "the" module system) is not suited for the top-level for Nixpkgs, as opposed to using it for the configuration of packages.
A module system is about squashing additional non-conflicting changes and makes an exception for ordering with mkOrder, where as the override logic is all about ordering when changes are applied, when packages / package-set are copied under a different name and mutated separately it in a different way and replace the logic that previously existed.
To make it work, one would have to add extra semantic, such as the order of modules, to inject a default ordering / priorities into a module system used in the context of Nixpkgs. Thus, the modules would no longer be position independent.
| 13:32:42 |
profpatsch | they are? | 13:51:30 |