Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

while loop #2189

Open
william-silversmith opened this issue May 31, 2016 · 3 comments
Open

while loop #2189

william-silversmith opened this issue May 31, 2016 · 3 comments

Comments

@william-silversmith
Copy link

william-silversmith commented May 31, 2016

Feature Request

I was attempting to write some numerical code, and looping until a condition is met is a typical thing to do for that sort of thing. I can accomplish the same thing with recursion, but the number of parameters I have to pass back and forth is icky.

I guess having a while loop means that stylus won't necessarily ever halt, which might not be so good for people that aren't developers, but you can still do that with recursion (though it halts by blowing up the stack ;) ).

@Panya
Copy link
Member

Panya commented May 31, 2016

Could you show a use case? I guess a JS plugin would be better suited for this task.

@william-silversmith
Copy link
Author

william-silversmith commented May 31, 2016

I will admit I'm pushing CSS to the limits here, but I'm attempting to make it easier for designers to use e.g. spring animations in CSS using keyframe animations. I've written up the math and a JS version here: https://medium.com/analytic-animations/the-spring-factory-4c3d988e7129#.d3xdphwx0

I'm not confident that stylus needs a while loop as I'm a bit of an edge case, but I figured I'd show you guys a use case that maybe you hadn't seen. In Listing 1 below, I use an anonymous function, bisection, that passes a reference to itself to simulate a while loop. In my JS version, I made my solution more general by finding the upper and lower bounds before performing a binary search because in part because the code complexity was a little easier to handle with the while loop. In this version, I just chose an unrealistically large range to bisect.

I could go and rewrite that part again, it's only laziness that's holding me back, but a while loop in this case helps prevent laziness from winning. ;)

In Listing 2, you can see a prototype (it's not fully designed yet) of how someone might use the output of my spring function. Listing 3 shows sample output. There might be a few bugs still in the code, but I think it should be illustrative.

Thank you for your consideration. :)

// LISTING 1: Performing a while loop for numerical computation
// Resolve recursive definition of omega and B using bisection method
numericallySolveOmegaAndB(zeta, k, y0 = 1, v0 = 0) {

  // See https://en.wikipedia.org/wiki/Damping#Under-damping_.280_.E2.89.A4_.CE.B6_.3C_1.29
  // B and omega are recursively defined in solution. Know omega in terms of B, will numerically
  // solve for B.

  errorfn = @(B, omega) {
    omega_d = omega * sqrt(1 - zeta * zeta)
    return B - ((zeta * omega * y0) + v0) / omega_d
  }

  A = y0
  B = zeta // initial guess, no good theoretical reason why

  omega = computeOmega(A, B, k, zeta)
  error = errorfn(B, omega)

  lower = -10000
  upper = 10000

  bisection = @(self_fn, ct, error, lower, upper, B, omega) {
    if (abs(error) <= 0.000001) {
      return {
        B: B,
        omega: omega,
      }
    }

    ct = ct + 1

    if (ct > 1000) {
      return {
        B: B,
        omega: omega,
      }
    }

    B = (upper + lower) / 2

    omega = computeOmega(A, B, k, zeta)
    error = errorfn(B, omega)
    direction = -1 * sign(error)

    if (direction > 0) {
      lower = B
    } 
    else {
      upper = B
    }

    return self_fn(self_fn, ct, error, lower, upper, B, omega)
  }

  return bisection(bisection, 0, error, lower, upper, B, omega)
}
// LISTING 2: Creating a spring animation
vals = springFactoryVals(damping: 0.15, halfcycles: 5, precision: 5, y0: 1, v0: 10)
ct = 0

@keyframes spring
  for val in vals
    pct = ct / (length(vals) - 1) * 100
    ct = ct + 1

    {unit(pct, '%')}
      left unit(val * 100, 'px')
// LISTING 3: Sample output
// Note: -moz, -o, -webkit output truncated for clarity
@keyframes spring {
  0% {
    left: 100px;
  }
  20% {
    left: -50.18610410443193px;
  }
  40% {
    left: 23.595075650464086px;
  }
  60% {
    left: -9.853507250727997px;
  }
  80% {
    left: 3.083943137298255px;
  }
  100% {
    left: 4.613368e-9px;
  }
}

Here's a gist of the full thing: https://gist.github.com/william-silversmith/8e9b89a0eaad9d168bb9343b1f13df19

@bhutiyakishan1
Copy link

so its been two years and this issue is still open? WOW!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants