2012-06-26 15 views
5

Utilizzo il manubrio nell'applicazione mobile jQuery di Rails 3.2.Intervallo all'interno dell'istruzione switch case in Coffeescript

Sto cercando di scrivere una dichiarazione caso interruttore all'interno di un metodo CoffeeScript come

Handlebars.registerHelper 'status', (blog) -> 
    switch(parseInt(blog.status)) 
    when [0..20] 
     status = "active" 
    when [20..40] 
     status = "Moderately Active" 
    when [40..60] 
     status = "Very Active" 
    when [60..100] 
     status = "Hyper Active" 
    return status 

Non ricevo alcun risultato. Come usare range in quando. Si prega di suggerire

+2

Perché questo dovrebbe funzionare? Questo [problema github] (https://github.com/jashkenas/coffee-script/issues/1383) sembra dire che questa sintassi non è stata accettata. –

risposta

16

Il switch non funziona come note Cygal nei commenti (ad esempio vedere issue 1383). Un switch è solo un glorificato if(a == b) costrutto ed è necessario essere in grado di dire le cose come:

a = [1,2,3] 
switch a 
... 

e farlo funzionare quando si switch su un array. I progettisti di CoffeeScript ritenevano che l'aggiunta di un (fragile) caso speciale per gestire gli array (che è tutto lo [a..b]) non fosse valsa la pena.

È possibile farlo con un if:

Handlebars.registerHelper 'status', (blog) -> 
    status = parseInt(blog.status, 10) 
    if 0 <= status <= 20 
    'Active' 
    else if 20 < status <= 40 
    'Moderately Active' 
    else if 40 < status <= 60 
    'Very Active' 
    else if 60 < status <= 100 
    'Hyper Active' 
    else 
    # You need to figure out what to say here 

O con corto circuito return s in questo modo:

Handlebars.registerHelper 'status', (blog) -> 
    status = parseInt(blog.status, 10) 
    return 'Something...'  if status <= 0 
    return 'Active'   if status <= 20 
    return 'Moderately Active' if status <= 40 
    return 'Very Active'  if status <= 60 
    return 'Hyper Active'  if status <= 100 
    return 'Something else' # This return isn't necessary but I like the symmetry 

Nota che ci sono tre casi speciali che è necessario aggiungere le stringhe di:

  1. status < 0.
  2. status > 100.
  3. status è NaN. Questo caso di solito ricade sotto il ramo "non è inferiore o uguale a 100" dal NaN => n e NaN <= n sono entrambi falsi per tutti n.

Sì, sei assolutamente certo che lo stato rientrerà sempre nell'intervallo presunto. D'altra parte, l'impossibile accade per tutto il tempo software (da cui la mailing list comp.risks) e non ci sono buoni motivi per lasciare buchi che sono così facilmente riempiti.

Si noti inoltre l'aggiunta dell'argomento Radix alla chiamata parseInt, non si vorrebbe uno zero iniziale per fare un casino di cose. Sì, l'argomento Radix è facoltativo ma in realtà non dovrebbe essere e le tue dita dovrebbero aggiungere automaticamente lo , 10 a ogni chiamata effettuata da parseInt.

+1

Una buona risposta: D. Mi piace la concisione della seconda soluzione, ma anche il "tutto-è-un-espressionabilità" del primo. Posso proporre di unirmi a entrambi [usando un'espressione 'swtich ] (http://goo.gl/QKKAq)? = D (non voglio rubare nessun punto pubblicandolo come una nuova risposta) – epidemian

+0

@epidemian: sembra una buona alternativa a me, ho molti punti e non mi dispiace condividere quindi dovresti metterlo giù come una domanda. Probabilmente userò il secondo, mi piace l'effetto "è un tavolo di ricerca in linea". –

+0

OK, ho aggiunto una risposta come una tua appendice. – epidemian

8

L'aggiunta di un po 'piccolo per mu is too short's answer, è possibile trasformare il suo secondo frammento di codice in un'espressione switch:

Handlebars.registerHelper 'status', (blog) -> 
    status = parseInt(blog.status, 10) 
    switch 
    when status <= 0 then 'Something...'  
    when status <= 20 then 'Active' 
    when status <= 40 then 'Moderately Active' 
    when status <= 60 then 'Very Active' 
    when status <= 100 then 'Hyper Active' 
    else 'Something else' 

questo è fondamentalmente equivale a fare un switch (true) in JavaScript (anche se il compilatore CS genererà un switch (false) statement with the negated conditions a garantire risultati booleani dalle espressioni ... penso).


E la ragione per cui il switch over range non funziona è che spazia letterali in CS rappresentano i vecchi sistemi JS semplici (anche se il compilatore fare alcuni trucchi di ottimizzazione quando si fa qualcosa di simile for i in [1..something]), in modo da quando sono trovato all'interno di un switch vengono trattati solo like normal array values:

// Generated JS for question's CS code: 
switch (parseInt(blog.status)) { 
    case [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]: 
    status = "active"; 
    break; 
    case [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]: 
    status = "Moderately Active"; 
    break; 
    case [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]: 
    status = "Very Active"; 
    break; 
    case (function() { 
     _results = []; 
     for (_i = 60; _i <= 100; _i++){ _results.push(_i); } 
     return _results; 
    }).apply(this): 
    status = "Hyper Active"; 
} 

il valore all'interno dell'istruzione switch è fondamentalmente confrontato con ciascun valore case utilizzando ===, che funziona solo per primitive, non per array (e anche se ha funzionato per gli array, testerebbe l'uguaglianza dell'array, non se il valore di switch è contenuto negli array di case ed).

+1

Vedi, vale la pena farlo. Non avrei pensato a quella forma di "switch", ma la prossima volta lo farò. Penso che tu abbia ragione, ma il contesto booleano e l'uso di 'switch (false)' invece di 'switch (true)'. –

Problemi correlati