You mean you don’t want to use the new math.sign() function to rewrite it like this?
local function moveTowards(current, target, maxDelta)
return current + math.sign(target-current) * math.min(maxDelta, math.abs(target-current))
end
You mean you don’t want to use the new math.sign() function to rewrite it like this?
local function moveTowards(current, target, maxDelta)
return current + math.sign(target-current) * math.min(maxDelta, math.abs(target-current))
end
New clamp is actually twice as fast as ternary in unprivileged code.
The speed gain is less significant in plugins–blame the mysterious dispatch overhead.
not entirely sure why you would use ternary for clamp. Is it faster than
math.min (max, math.max (x, min))
According to this glorious thread, ternary is faster than min-max.
“Which clamp is faster” is almost never a question that you need to ask, though.
Ayoooo that was my solutionnnn
Awesome. But as always, I’m bad at being grateful for what we have and always want more (what a materialistic world we live in). So I’d really like us to have a math.round
function too
Interesting.
Looks good to me. Math.Round would also be very useful.
I think native bit-wise operators could be handy. Particularly for things like custom simplex noise functions.
The C-style ternary is how I expected both to work - why is Lua’s “A and B or C” pattern not functionally equivalent to the ternary operator in C?
Because it’s not a ternary operator. It just happens to somewhat emulate it.
and
and or
are operations on their own. and
comes before or
, so a and b or c
is the same as (a and b) or c
, which might be easier to understand.
Because it’s a pattern people use a lot, since it works most of the time and has the arguments in the same visual order as a C-style ternary, but it’s not the correct logic expression for a 2-to-1 Multiplexer. The more correct logic expression is (A and B) or ((not A) and C) which requires the condition ‘A’ to be written out twice, thus breaking the nice visual similarity with the ? ternary. Also, even this expression won’t let you assign nil, because logic won’t evaluate to nil, only false.
Append “or nil” to turn false into nil.
And the expression gets even longer if you want to be able to conditionally return either false or nil. You have to use true for false, negate it all, and… please no one do this.
That expression works fine:
A,B,C = false,1,false
print((A and B) or ((not A) and C)) --> false
A,B,C = false,1,nil
print((A and B) or ((not A) and C)) --> true
-- or "short" notation: A and B or not A and C
Because and
just returns the second parameter if the first is truthy and the first paremeter otherwise:
false and 1 --> false
nil and 1 --> nil
true and false --> false
true and nil --> nil
The case for which it does not work is:
A,B,C = true, nil, false --> evaluates to false, desired result is nil
and if you exchange the arguments to the or, making it: ((not A) and C) or (A and B), then it fails
A,B,C = false, false, nil --> evaluates to false, desired result is nil
Want one logic expression that is nil compatible? Maybe try this one:
not ((A and B or not A and C)==nil or (not A and C or A and B)==nil) and (A and B or not A and C) or (((A and B or not A and C)==nil or (not A and C or A and B)==nil) and nil)
If you can come up with a significantly shorter one, I’ll be suitably impressed!
If I’m not limited to and/or/not operators:
({B,C})[A and 1 or 2]
but that’s slower than a (not too long) ternary chain.
Otherwise this, that I somehow got:
A and B or not A and C or ((A and B==nil or not A and C==nil) and nil)
Tests: (first column is just whether it’s correct)
true | true 1 2 => 1
true | true 1 nil => 1
true | true 1 false => 1
true | true nil 2 => nil
true | true nil nil => nil
true | true nil false => nil
true | true false 2 => false
true | true false nil => false
true | true false false => false
true | false 1 2 => 2
true | false 1 nil => nil
true | false 1 false => false
true | false nil 2 => 2
true | false nil nil => nil
true | false nil false => false
true | false false 2 => 2
true | false false nil => nil
true | false false false => false
Alternatively, if you know B can be false/nil you can just invert it:
not A and C or B
That would work if you also knew C isn’t false/nil (or if C is false/nil, C == B)