infinisil changed the topic of #nix-lang to: Channel for discussing Nix as a language - https://nixos.org/nix/manual/#chap-writing-nix-expressions - Logs: https://logs.nix.samueldr.com/nix-lang/
infinisil has quit [Quit: Configuring ZNC, sorry for the joins/quits!]
infinisil has joined #nix-lang
<sphalerite> why does tryEval have value if it's unsuccessful…
<sphalerite> > tryEval = x: let r = builtins.tryEval x; in if r.success then r else { success = false; }
<{^_^}> tryEval defined
<sphalerite> > tryEval 5
<{^_^}> { success = true; value = 5; }
<sphalerite> > tryEval (throw "nope")
<{^_^}> { success = <CODE>; }
<sphalerite> > (tryEval 5).value or "failed"
<{^_^}> 5
<sphalerite> > (tryEval (throw "nope")).value or "failed"
<{^_^}> "failed"
<sphalerite> it would be so much nicer to use
<MichaelRaskin> Well, tryEval is older than the «or» syntax
<sphalerite> even then
<sphalerite> why have a value when nothing meaningful was obtained?
<MichaelRaskin> builtins,tryEval (throw "nope")
<MichaelRaskin> > builtins.tryEval (throw "nope")
<{^_^}> { success = false; value = false; }
<sphalerite> seems very arbitrary to have it be false
<MichaelRaskin> Hm. I probably looked at Common Lisp ignore-errors
<MichaelRaskin> I don't remember why not null
<MichaelRaskin> Maybe you could ask if anyone objects to removal of value on failure now that «or» exists
<sphalerite> yeah I'll do that
<MichaelRaskin> Realistically I implemented this because back in the day this seemed to be the most reasonable medium-term way to implement Hydra jobset generation in release.nix (walk everything, collect things with maintainers field and platforms field, not die on the first problem)
<infinisil> sphalerite: I want tryEval to return the throw's message
<infinisil> In case of failure
<sphalerite> infinisil: I mentioned this in the issue too :)
<infinisil> Which issue?
<sphalerite> oops had't submitted the issue yet
<sphalerite> nix#241
<sphalerite> nix#2421
<{^_^}> https://github.com/NixOS/nix/pull/241 (by wizeman, 4 years ago, closed): nix-env: Minor change to '--delete-generations Nd' semantics
<{^_^}> https://github.com/NixOS/nix/issues/2421 (by lheckemann, 14 seconds ago, open): Remove value for failed tryEval?
<infinisil> Hmm.. How would a proper try/catch thing look like in nix
<infinisil> Maybe that could replace throw/tryEval
<infinisil> builtins.catch (throw "error") (e: "Got error: ${e}") => "Got error: error"
<infinisil> builtins.catch "no error" (e: "Got error: ${e}") => "no error"
<infinisil> That looks a lot better than tryEval tbh
<MichaelRaskin> I have a (possibly false) memory that returning too much details about the error was criticized for making non-specified order of dependency evaluation accessible in a succesful Nix expression evaluation
<infinisil> order of dependency evaluation? What's that exactly?
<MichaelRaskin> Well, evaluating something cn have ten simultaneous reasons to fail
<infinisil> > (throw "fun") (throw "arg")
<{^_^}> fun
<infinisil> MichaelRaskin: You mean how e.g. this throws the first error instead of the second?
<MichaelRaskin> For example
<MichaelRaskin> Or you could have a list
<MichaelRaskin> > [ (throw "fun") (throw "arg") ]
<{^_^}> [ <CODE> <CODE> ]
<infinisil> I don't think that would be a problem, it's how all languages work. And what gets evaluated first is fixed with Nix' laziness
<MichaelRaskin> > __toString [ <CODE> <CODE> ]
<{^_^}> undefined variable '__toString' at (string):194:1
<MichaelRaskin> > builtins.toString [ (throw "fun") (throw "arg") ]
<{^_^}> fun
<MichaelRaskin> Well, most languages do not try to be fully functional…
<infinisil> Even haskell works like that afaik
<MichaelRaskin> Oh! nix#1000
<{^_^}> https://github.com/NixOS/nix/pull/1000 (by shlevy, 2 years ago, closed): Allow throwing and catching arbitrary (string-coercible) values
<MichaelRaskin> I was not misremembering, this argument against catch (and extended tryEval) was indeed used on record
<infinisil> I don't get the problem tbh
<infinisil> Yes it depends on the evaluation order, but so what? How is this bad?
<infinisil> Yeah
<infinisil> In Haskell terms, I think this would just make every value be `Either String a`, while `builtins.catch :: Either String a -> (String -> Either String a) -> Either String a`
<MichaelRaskin> Well, it does create a risk of weird expressions that suddenly give a slightly different result on Nix update.
<infinisil> Oh yeah, I guess in haskell you couldn't just `+` two `Either`s
<infinisil> You'd need to use monady stuff to have them evaluate in order
<infinisil> Still, I don't think that's a big problem, it could even be put into the semantics docs: "builtins.catch catches *any* error, without a fixed order"
<infinisil> Although, regarding the monady stuff, Idris has something for that: http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#notation
<infinisil> Where `pure (!x + !y)` == `do { _x <- x; _y <- y; pure x + y }`, it does these bindings from left to right, so it doesn't rely on evaluation order. This means that the left-most error will be the one to propagate
<sphalerite> infinisil: or Control.Except? :)
<infinisil> sphalerite: Yeah
<infinisil> Let's add do notation to Nix!
<sphalerite> let's make nix into a haskell library!
<MichaelRaskin> Let's die heroically trying to clean out all the type ambiguities in Nixpkgs!
<sphalerite> The ability to have type safety isn't an obligation to have type safety :D
<infinisil> Hold on, why would evaluation order be impure
<infinisil> MichaelRaskin: There's only a single way to evaluate expressions in lazy languages
<sphalerite> infinisil: no there's not..? in (a + b) for instance, there's no reason for a to be forced before b or vice versa
<sphalerite> infinisil: they could just as well be evaluated in parallel
<infinisil> Nope
<infinisil> (a + b) = (((+) a) b)
<sphalerite> right but ((+) a) doesn't require a to be evaluated
<sphalerite> because it's lazy.
<sphalerite> :)
<infinisil> Ah
<infinisil> I guess it depends on the primops keeping the same order
<infinisil> But assuming those are fixed, the evaluation order is always the same
<sphalerite> but there's no reason for them to
<infinisil> But there's also no reason for them not to
<sphalerite> as I said, they could even be evaluated in parallel to potentially improve performance.
<sphalerite> yes there is ^
<infinisil> Oh
<infinisil> I see, alright but then the result has to wait for both results anyways, at which point the error of the left one will probably be checked first
<MichaelRaskin> infinisil: also, why the assumption that lazy = full-currying
<infinisil> Eh not sure, but Nix works that way anyways
<infinisil> I think
<infinisil> Or not, I guess not with primops lol
<infinisil> But anyways, I don't think it would be hard to guarantee a fixed evaluation order
<infinisil> ANd I don't see any problems that could arrive from such a fixed order
<infinisil> (I really thought I saw nix-instantiate --parse return something like `((__add a) b)` for `a + b`, but I guess it doesn't)