4
\$\begingroup\$

I tested this program on Smooth-CoffeeScript

I just wanted to have as many eyes on this as I could to learn about coffeescript;

Is there anything I should do to improve it?

Am I using the tools available to me adeptly? (i.e. good variable naming, layout, commenting, etc.)

userQuestion   = '¿ what is 2 + 2 ?'
correctLength = 1
correctAnswer = '4'
correctAnswerMsg = "That's correct!"
closeMsg = "Almost there!"
digitsOnlyMsg = "Digits only!"
singleDigitMsg = "Single digit!"
tryAgainMessage = "Try again!"

prompt userQuestion, '', (answer) ->  # the answer can not be set as a variable here
                                      # (answer) grabs the answer from the console
  userEntry = answer                  # -> casts that answer down to the rest of the indent to be used plainly
                                      # at least that's how I think it works :/                  

  show userEntry  # the user's answer always shows on the first line

  if userEntry.length isnt correctLength  # .length only works when comparing the length of a string to an integer
    show singleDigitMsg

  userEntry = (Number) userEntry
  correctAnswer = (Number) correctAnswer  # now we convert our user entry and our correct answer into integers so the math functions work

  if userEntry is correctAnswer
    show correctAnswerMsg
    exit program

  else if userEntry is correctAnswer - 1 or userEntry is correctAnswer + 1
    show closeMsg

  else if isNaN(userEntry)
    show digitsOnlyMsg

  else  # this only shows when the user types in 1, 2, or 6-9. Or multiple characters with a digit, like '-4' 
    show tryAgainMessage
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

This is a a very, um, thorough way of doing things. Not necessarily a bad thing, and it does help learn some CoffeeScript, so yay for that, but still it's a little much. I'll roll with it though.

Before talking about the code proper, though, I have to point out that prompt, show and exit program aren't part of CoffeeScript or JavaScript. That would appear to be something wholly custom to that smooth-coffeescript site you mention. In other words, those only work on that site, so don't think it's something you can use anywhere else. In the code below I'll use alert instead of show (since works in browsers), and I'll get to the exit program thing in a second.

prompt is another matter, since that does exist in browsers, but it works differently. Instead of taking a callback function, it simply returns a string (or null). So this is actually pretty bad of the smooth-coffeescript author(s), since it doesn't merely add custom functionality, but takes an existing, well-documented feature of browser-based JavaScript and makes it behave differently, confusing everyone.

So just know that the stuff you write on that site, while it might teach you CoffeeScript, it can also mislead you.

Now, some notes on the code:

  • Put the strings and other variables inside the prompt function; don't pollute the global namespace. The only one you have to keep outside is the question itself, as that's used when calling prompt to begin with.

  • userEntry = answer does nothing useful. It just gives you two variables both containing what the user entered. Nothing gained.

  • This part has some weirdness:

    if userEntry is correctAnswer
      show correctAnswerMsg
      exit program
    

    As mentioned exit program is not standard. In Node.js you might use process.exit to explicitly quit/stop the entire script and runtime, but that the nearest thing that's actually common to see. However, you don't need to exit the script/program. Since you're inside a function (the callback for prompt), you can just say return when you want to stop. Since there's no other code after the call to prompt, the script will exit on its own.

    However, you don't even need to return. You've written an if.. else if.. else structure, so if the user's answer is correct, none of the other else/else if branches will be run. So there's nothing to stop or return from.

  • Checking for both length and the number itself is a hassle. Both because if the number's wrong, who cares if the length was right? Secondly, it requires you to specify both length and value of the correct answer, meaning you have two things to change if you want to make the question what is 3 + 11? instead. And you'd have to change the singleDigitMsg text too - and the name of the singleDigitMsg variable itself - since neither of those make sense anymore.

    I'd instead check "did the user enter only digits?" and "did they enter the correct number?". Checking "did the user enter something that's the same length as the string representation of the correct number?" is somehow both too precise and too vague to be useful.

  • For checking if the user's just-1-off from the correct answer, don't check if it's correct-1 or correct+1; check if the difference is 1.

Here's what I'd write (run the snippet, and open the developer console to see the output)

# a less confusing wrapper for the browser-native `prompt` function
promptWithCallback = (message, callback) ->
  response = prompt message
  callback response unless response is null

# the actual thing
promptWithCallback "What's 2 + 2?", (answer) ->
  correctAnswer = 4

  # complain if answer contains non-digit character
  if /\D/.test answer
    alert "Only digits, please"
    return # stop here

  # instead of casting to a Number, use parseInt with a radix/base argument
  # this avoids the string "08" being converted to NaN because JS thinks it's
  # an octal (base 8) number (due to the leading zero) that's invalid (due to
  # it containing an 8). Doesn't happen in most runtimes, but still
  number = parseInt answer, 10

  if number is correctAnswer
    alert "Yup, correct!"

  else if Math.abs(number - correctAnswer) is 1
    alert "Nope - but you were really close though. Try again"

  else
    alert "Nope. Try again"

If you want to try it in your browser (couldn't make it work with stack snippets due to a http/https conflict), go to coffeescript.org, click the "Try CoffeeScript" button at the top, paste in the code, and click "run".

You'll note that I didn't add variables for all the different strings. Frankly, I just didn't want to bother with that, since it's all pretty simple. It's not necessarily a bad thing to do (it puts all the text in one place, making it easier to change), but it's not a huge piece of code, so I just wrote it in place.

\$\endgroup\$
2
  • \$\begingroup\$ Why does it give an alert for if it was wrong or close, but it only logs to the console when you don't enter a digit. \$\endgroup\$
    – Shui
    Commented May 10, 2017 at 15:49
  • \$\begingroup\$ @Shui Ah, whoops. I think I started using alert for simplicity's sake, but forgot to fix the existing code. My bad, will edit \$\endgroup\$
    – Flambino
    Commented May 10, 2017 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.