0

I have been playing with the following function:

s = function(x) {
  for(n=10,z=0;~(--n);){
    z+=pow(-1,n)/fac(2*n+1)*pow(x,2*n+1)
  }
  return z
}

fac is a factorial function, pow is a power function (for those playing at home) which I have defined outside of this function. s is meant to be a Taylor series derivation of the sine function, so s(Math.PI/4) would come back as a very close approximation of the square root of 0.5.

I'd like to make this an arrow function with z automatically returning, but have found myself failing at this point with an "Invalid left-hand side expression in prefix operation" error...

I received this error when I tried:

s=x=>~(--(n=n||10))?s((z=z||0)+=pow(-1,n)/fac(2*n+1)*pow(x,2*n+1)):z

I know I'm missing something ridiculous... but I can't put my finger on it... Can anyone lend a hand?

Thanks in advance.

Eliseo D'Annunzio
  • 592
  • 1
  • 10
  • 26
  • What did happen to the loop, do you really intend to use a *global* `n` variable?! You should not make this a function with a concise body. – Bergi Sep 29 '17 at 01:30
  • I am a bit confused by the ~. What does it do in javascript? – gautam1168 Sep 29 '17 at 01:31
  • 2
    @gautam1168 https://stackoverflow.com/questions/12299665/what-does-a-tilde-do-when-it-precedes-an-expression it's a bitwise operator – Sterling Archer Sep 29 '17 at 01:35
  • @Bergi I wanted to use a recursive function to calculate the Taylor series, so I'm trying to absorb the loop in that manner... As to the n variable, it's arbitrary (remembering I'm just playing with this function), but I need a marker so that I can calculate the powers and factorials for each progression in the series... – Eliseo D'Annunzio Sep 29 '17 at 01:35
  • @Eliseod'Annunzio To convert a loop to a recursive function, the iterator and accumulator variables need to become parameters. The problem with `n` is not the name, but rather that it is not declared in any scope [and therefore global](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html) – Bergi Sep 29 '17 at 01:38
  • @gautam1168 the ~ acts as a -(N+1) on standard numbers. I'm using this to act as a marker for n with each time it gets decreased by 1. because I need the loop to work when n = 0, I'm catching it when n becomes -1, which ~(-1) becomes 0, which closes the condition and is meant to exit the ternary. – Eliseo D'Annunzio Sep 29 '17 at 01:39
  • @Eliseod'Annunzio Btw, `while(n--)` (or `for(…;n--;)`) is the idiomatic way to do that. – Bergi Sep 29 '17 at 01:45
  • @Bergi, whilst that may have been the case, I needed the loop to work at n=0 as well before breaking out of the loop... This the use of the ~ to trick the loop to break when n=-1. – Eliseo D'Annunzio Sep 29 '17 at 07:00
  • @Eliseod'Annunzio Try it. The postfix decrement will run the loop body with `0` before breaking out. – Bergi Sep 29 '17 at 11:56

3 Answers3

3

Both the expressions --(n=n||10) and (z=z||0)+=pow(-1,n)… are syntax errors. --10 and 0+=… are clearly invalid, you cannot assign to a literal value.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I could give advise on how to fix it, but I rather won't as this would make absolutely horrible code. – Bergi Sep 29 '17 at 01:36
  • Humor me, @Bergi... as this is research for a blog post I'm writing on quirks in JavaScript and best (and worst) coding practices... I'm happy to put in the post that this is not recommended coding practice... I'm just curious as to what I'm missing... – Eliseo D'Annunzio Sep 29 '17 at 01:41
  • It needs to be `n=(--n||10)` and `z=(z||0)+…`. (Which of course still will throw a runtime exception when you don't declare the variables anywhere). – Bergi Sep 29 '17 at 01:43
1

You could but everything into 1 function (including factorial and power), but that would be more unreadable:

s=(x)=>((n,r)=>(r=(s,o=0,f=y=>!y||y*f(y-1),p=(b,w)=>eval('b*'.repeat(w)+1))=>!n--?o:o+r(s, p(-1, n)*p(x,2*n+1)/f(2*n+1)))(x))(10);

s=(x)=>((n,r)=>(r=(s,o=0,f=y=>!y||y*f(y-1),p=(b,w)=>eval('b*'.repeat(w)+1))=>!n--?o:o+r(s, p(-1, n)*p(x,2*n+1)/f(2*n+1)))(x))(10);

console.log(s(Math.PI/4));
console.log(Math.sqrt(0.5));
cyr_x
  • 13,987
  • 2
  • 32
  • 46
0

Using Bergi's suggestion and shifting n-- after the action I found the following worked:

s=(x)=>~(n||10)?(s(z=(z||0)+p(-1,n)/f(2*n+1)*p(x,2*n+1))&&(n--)):z
Eliseo D'Annunzio
  • 592
  • 1
  • 10
  • 26