// t: current time, b: begInnIng value, c: change In value, d: duration
def: 'easeOutQuad',
swing: function (x, t, b, c, d) {
//alert(jQuery.easing.default);
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
},
easeInQuad: function (x, t, b, c, d) {
return c*(t/=d)*t + b;
},
easeOutQuad: function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
},
I am trying to convert Robert Penner's Easing Functions into python and getting stuck! Any help or any one else done this before?
https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
There are mainly three kinds of distinguishable errors in Python: syntax errors, exceptions and logical errors.
Syntax errors are produced by Python when it is translating the source code into byte code. They usually indicate that there is something wrong with the syntax of the program. Example: Omitting the colon at the end of a def statement yields the somewhat redundant message SyntaxError: invalid syntax.
Python - Error Types. The most common reason of an error in a Python program is when a certain statement is not in accordance with the prescribed usage. Such an error is called a syntax error. The Python interpreter immediately reports it, usually along with the reason.
In both JavaScript and Python, /=
is an "augmented assignment" operator, with pretty much the same meaning.
In JS:
var i = 10;
i /= 2;
… is equivalent to:
var i = 10;
i = i / 2;
And, in Python:
i = 10
i /= 2
… is likewise equivalent (not quite exactly the same, but close enough for numbers) to:
i = 10
i = i / 2
However, there is one very big difference.
In JavaScript, assignment is an expression—it has a value, and that value is the value being assigned to the variable. So:
var i = 10;
var j = i /= 2;
… is roughly equivalent to:
var i = 10;
i /= 2;
var j = i;
In Python, assignment is a statement. It has no value, and cannot be used in an expression. So:
i = 10
j = i /= 2
… raises a SyntaxError
.
Porting code that uses assignment (augmented or otherwise) in the middle of an expression generally requires breaking that expression up into multiple lines and/or finding a way to rewrite the expression to not require any assignments. (But often, that's not a bad thing, because the original expressions weren't very readable anyway…)
For example, assuming JS evaluates operands from left to right (which I'm not sure is guaranteed?):
def easeInQuad(x, t, b, c, d):
t /= d
return c*t*t+b
More generally, you do this:
old_t = t
t /= d
And then you replace any instances of t
before that t/=d
with old_t
, and leave all instances from t/=d
and later alone. Fortunately, in this case, there are no previous instances, so we don't need that old_t
stuff.
And if you think about it, you can easily get the same effect without ever changing t
, in one line, much more readably, in any of the following ways:
return c * (t/d) * (t/d) + b
return c * (t/d)**2 + b
return c * t*t / d*d + b
Someone who thinks in C will immediately complain that these are all "too slow". After all, the first does an extra division, the second does an exponentiation instead of a multiplication, and the third does two multiplications instead of one. Horrors!
Of course you can always use a temporary variable:
t_over_d = t/d
return c * t_over_d * t_over_d + b
… but again, to a C programmer, that implies that you're using up a valuable register. Sure, every compiler written after, say, 1985 will detect that t
is dead as soon as t_over_d
appears and reuse the same register, but why not force it to reuse the register if we can, especially if it saves a few keystrokes too?
In JS or Python, the cost of a multiplication is such a tiny fraction of the cost of calling a function, and interpreting the bytecode, and so on that you'd never even notice it. Meanwhile, the cost of rebinding a local variable (especially in a V8-style or PyPy-style JIT interpreter) might be much, much higher than the cost of passing around an unnamed temporary result.
So, this is a paradigm case of misguided "optimization" making code much harder to understand, while probably slowing it down instead of speeding it up, and in an area that cannot possibly be a bottleneck worth optimizing anyway.
Since gnibbler brought up the question of whether JavaScript actually does guarantee this evaluation order…
First, JavaScript is defined as, effectively, "what Firefox does" (and "what Spidermonkey does", but that ought to be the same thing—and, if it isn't, then JavaScript does 2 things, so that's twice as good, right?). But ECMAScript is defined by standards, and it's those standards that every JS implementation (despite the name) pays lip service to, and we can pretend that ECMAScript 5.1 is the standard that all implementations conform to (which is true so long as "all implementations" means "Opera"). You can find it here.
So, in ES 5.1: 11.5 Multiplicative Operators guarantees that the result of (t/=d)
will be evaluated before t
, and 11.13.2 Compound Assignment guarantees that evaluating t/=d
will set the value of t
before it finishes. (You have to read up on what "evaluate" means and what GetValue
an SetValue
mean, but I'm pretty sure this really is guaranteed.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With