<sterni>
ints are always parsed as positive integers
<Profpatsch>
why are ints not bigints in the first place
<Profpatsch>
I mean we don’t have that many
<Profpatsch>
So why arbitrary restrictions, apart from “it was easier to implement at the time”
<ekleog>
“doing otherwise would break backwards-compatibility”?
<ekleog>
(though interestingly enough… I'd bet any breakage that would happen would only currently be relying on nix code being UB because signed int addition is UB in c++?)
<ekleog>
(haven't checked the code that said)
<niksnut>
Profpatsch: is there a better reason than "it was easier to implement that way"?
<niksnut>
bigint support would require pulling in another library
<V>
I mean, if it is indeed implemented directly using C++ primitives, Nix-lang can now directly invoke UB
<V>
who knows which optimisations the GCC maintainers are going to implement in the future
<ekleog>
TBF signed int overflow being UB is probably actually ID by GCC to mean wrapping on amd64; anything else would most likely break so much real-world software
<V>
indeed. if you actually took advantage of that, increment w/out bounds check could cause portions of code to be completely eliminated
<niksnut>
well, there have been some security bugs because the compiler removed code under the assumption that integers don't wrap around
<V>
but I'm also not relying on them deciding to enable this for -std=c++<future year>, with the argument that this wouldn't apply to "existing software", etc
<niksnut>
but I don't think it's an issue, we just inherit the int64_t behaviour
<siraben>
how do you exponentiate a number in nix?
<niksnut>
you don't :-)
<niksnut>
nix arithmetic is really only good for enumerating/counting (e.g. lib.range)
<siraben>
aw
<niksnut>
nickel only has 64-bit floating-point numbers, which is probably a good idea since they're more standard
<siraben>
what's the status of the nickel language?
<siraben>
V: you are crazy!
<siraben>
nix-repl> pow 2 3
<siraben>
[1 built, 0.0 MiB DL] 8
<V>
siraben: I don't deny that
<edef>
wait, why involve readFile?
<V>
wait, does fromJSON work on files directly?
<edef>
`pow = x: y: builtins.fromJSON "${builtins.toString x} ** ${builtins.toString y}"` should do
evanjs has quit [Ping timeout: 240 seconds]
<V>
ooooh
<edef>
fromJSON just takes a string
<V>
no, this is using bash?
<edef>
oh
<edef>
i see
<edef>
ah, i missed the $(( among all the token soup
<V>
easy mistake
<edef>
i was already fairly confused about how this parsed as valid JSON tbf :p
evanjs has joined #nix-lang
<sterni>
> exp = base: pow: if pow > 0 then base * (exp base (pow - 1)) else if pow < 0 then 1.0 / exp base (abs pow) else 1;
<{^_^}>
error: syntax error, unexpected ';', at (string):154:116
<sterni>
> exp = base: pow: if pow > 0 then base * (exp base (pow - 1)) else if pow < 0 then 1.0 / exp base (abs pow) else 1
<{^_^}>
error: undefined variable 'abs' at (string):154:100
<edef>
damnit, you're beating me to it
<sterni>
> abs = i: if i < 0 then -i else i
<{^_^}>
abs defined
<sterni>
> exp = base: pow: if pow > 0 then base * (exp base (pow - 1)) else if pow < 0 then 1.0 / exp base (abs pow) else 1;
<{^_^}>
error: syntax error, unexpected ';', at (string):155:116
<sterni>
> exp = base: pow: if pow > 0 then base * (exp base (pow - 1)) else if pow < 0 then 1.0 / exp base (abs pow) else 1
<{^_^}>
exp defined
<sterni>
> exp 2 16
<{^_^}>
65536
<V>
I love it
<sterni>
siraben: ^
<edef>
i was going to do full exponentiation-by-squaring
<edef>
but this is clever, i like it
<sterni>
well it's extremely slow probably
<sterni>
because function calls are really expensive
<sterni>
I wonder if genList and foldl' are faster in such cases because primops
<sterni>
but you still have to evaluate the lambda every time
<siraben>
sterni: nice
<edef>
clearly we need to have {^_^} report runtime in ms
<edef>
and/or have a benchmark mode
<sterni>
the worst thing I had so far was my naive ord implementation
<sterni>
it took like 3s to convert a list of 255 characters into a byte each
<sterni>
because a lot of recursive function calls and string/list indexing originally
<edef>
> isOdd = x: (builtins.bitAnd x 1) == 1
<edef>
> fastExp = base: exp: if exp < 0 then fastExp (1 / x) -exp else if exp == 1 then 1 else if isOdd exp then base * fastExp (exp - 1) else fastExp (x * x) (x / 2)
<{^_^}>
isOdd defined
<{^_^}>
fastExp defined
<edef>
> fastExp 2 16
<{^_^}>
value is a string while an integer was expected, at (string):55:100
<edef>
wait, what the hell
<edef>
i had a variety of expectations but this was definitely not among them
<edef>
oh, i somehow used `x` in half the places for base >_<
<edef>
> fastExp = x: exp: if exp < 0 then fastExp (1 / x) -exp else if exp == 1 then 1 else if isOdd exp then x * (fastExp x (exp - 1)) else fastExp (x * x) (x / 2)
<{^_^}>
fastExp defined
<edef>
> fastExp 2 16
<{^_^}>
1
* V
tilts head
<edef>
i'm definitely somewhat out of it, but also, i just realised everyone's impl for negative exponents is wrong
<edef>
since / does integer division
<__monty__>
> fastExp 15 1
<{^_^}>
1
<edef>
> fastExp = x: exp: if exp < 0 then fastExp (1 / x) -exp else if exp == 1 then x else if isOdd exp then x * (fastExp x (exp - 1)) else fastExp (x * x) (x / 2)
<{^_^}>
fastExp defined
<V>
mine just flat out breaks b/c bash doesn't allow for negative exponents. would be trivial to fix though
<edef>
> fastExp 2 16
<{^_^}>
4
<V>
hey, it's closer to the correct answer
<edef>
okay, wow, i really messed up but i'm not actually spotting the mistake yet
<V>
well done
<sterni>
edef: nope 1.0 / int is okay
<sterni>
> 1.0 / 5
<{^_^}>
0.2
<edef>
ah
<sterni>
you need to make sure you have a float somewhere though
<sterni>
nix floats are really bad btw
<edef>
> fastExp = x: exp: if exp < 0 then fastExp (1.0 / x) -exp else if exp == 1 then x else if isOdd exp then x * (fastExp x (exp - 1)) else fastExp (x * x) (x / 2)
<{^_^}>
fastExp defined
<sterni>
> lol = 0.00000000000001
<{^_^}>
lol defined
<edef>
ah, hold on. i don't have a 0 case
<sterni>
lol
<sterni>
> lol
<{^_^}>
1e-14
<edef>
> fastExp = x: exp: if exp < 0 then fastExp (1.0 / x) -exp else if exp == 0 then 1 else if isOdd exp then x * (fastExp x (exp - 1)) else fastExp (x * x) (x / 2)
<{^_^}>
fastExp defined
<edef>
> fastExp 2 16
<{^_^}>
4
<edef>
>_<
<sterni>
> builtins.toString lol
<{^_^}>
"0.000000"
<V>
I hate it
<sterni>
> builtins.toJson lol
<edef>
oh
<{^_^}>
attribute 'toJson' missing, at (string):484:1
<edef>
> fastExp = x: exp: if exp < 0 then fastExp (1.0 / x) -exp else if exp == 0 then 1 else if isOdd exp then x * (fastExp x (exp - 1)) else fastExp (x * x) (exp / 2)
<{^_^}>
value is a float while an integer was expected, at (string):222:14
<V>
> sqrtRuby = lib.flip expRuby 0.5
<{^_^}>
sqrtRuby defined
<V>
> sqrtRuby 4
<{^_^}>
cannot read '/nix/store/aqsdpp1wqxqjldw2pmdh4x51yph8i1aw-unknown', since path '/nix/store/g4cmabksbbsnzxpv0bk1qq2a9ckwyikv-unknown.drv' is not valid, at (string):157:37
<edef>
D:
<V>
rude
<V>
IFD-protection cramping my style
<sterni>
V: it doesn't let you build stuff :(
<V>
brb switching to guix
<sterni>
if I was using guix I wouldn't have an endless supply of cursed facts about my package manager's expression language
<V>
if I was using guix I'd not have a cursed package manager
<siraben>
Nix is cursed? :(
<V>
I mean
<V>
did you not see the conversation about float handling up there
<siraben>
(the language obviously cursed)
<sterni>
nix the package manager also
<sterni>
as in the implementation
<V>
aye
<siraben>
sterni: ooh tell me more
<siraben>
like, the C++ codebase?
<sterni>
yeah, I'm not that familiar with it actually
<sterni>
but a lot of weird stuff in nix the language is a result of implementation stuff I'd say
<siraben>
interesting, that doesn't compute in my WHNF mental model
<siraben>
should be true
<sterni>
siraben: indeed nix is being to strict in that case because the string constructor should come first
<sterni>
one thing I found really strange when I last had a look in the code is that in the implementation builtins and functions are different things and behave differently, but they have the same type (lambda) in the language
<sterni>
which has the consequence for example that builtins.functionArgs throws an exception on nix stable
<niksnut>
there is no "string constructor"
<sterni>
because it was forgotten to implement that primop for primpos as well
<niksnut>
there are values of type string, but you don't know that the argument to builtins.isString is a string value until you've evaluated it, hence the exception
<niksnut>
in the absence of a static type system, you can't really conclude whether the argument to builtins.isString will be a string without evaluating its argument
<siraben>
sterni: nice
<simpson>
Nix doesn't evaluate strictly enough for that problem to be fixed by simply putting a static type on every value. Same issue as Haskell, where the computational category isn't the one used for intuitive reasoning: https://wiki.haskell.org/Hask
<__monty__>
niksnut: But can anything that parses as a string literal ever turn out not to be a string?
<niksnut>
no, but the argument to builtins.isString is not an AST but a value/thunk
<niksnut>
so it can't really make any clever optimizations about the expected result type
<niksnut>
and if it did, it would lead to really weird semantics
<niksnut>
where builtins.isString might *sometimes* avoid an exception
<niksnut>
e.g. in builtins.isString (if expr then "foo" else throw "bar")
<niksnut>
a sufficiently smart interpreter might conclude that expr is always true