DEV Community

Cover image for ES6's Until Loop
jackismoe
jackismoe

Posted on

ES6's Until Loop

We all know it. Javascript is great.
Until it isn’t.
It’s super easy to use.
Until it isn’t.
And there’s a way to do just about anything you want in JS. From DOM manipulation to client server architecture. From machine learning to IoT. Truly javascript has an answer for everything, right?
As condescending of an intro as that was, I do genuinely feel that Javascript (or Typescript) is the future. That being said, the language and its frameworks aren’t without their problems. I would like to submit to you as a for instance my favorite programming meme, featuring Patrick Star and Manta Ray.

Alt Text
Plugging this into a console, we find that what is shown holds true. But I’m not here to talk bad about JS. My goal with this post is to propose that (some of) the problems we face with programming languages aren’t in fact problems with the language itself, but how we as programmers are approaching the task at hand.

Enter: Recursion.

Being a Rubyist at heart, learning Javascript had its curve. Somethings I liked better in Ruby, somethings made more sense in Javascript. One example of this was the JS for loop, and more specifically the for…of loop.
When I discovered the for…of loop, it was like the world had been hidden from me. “Surely this is the pinnacle of human innovation” I thought. Being able to iterate over an array with such little syntax was a miracle.
And of course JS, like almost all other common languages has a while loop, which does something as long as a given expression is true (or crashes your computer if you’re not careful).
So if a common for loop iterates over a collection of data x amount of times (or for as many times as is equal to the length of the collection) and the while loop goes on and on as long as something remains true… can I tell Javascript to do something UNTIL something is true?
This was a question that bothered me more and more as I continued to learn JS. I could in theory manipulate one of the aforementioned iterators to act in such a manner, but the function almost always ended up being more intricate than I felt was necessary. Then one day during a code session, I was doing some googling unrelated to the problem statement and I saw recursion being used, and it all clicked.
I’m sure that many of you reading this are familiar with the concept of recursion, but I’m going to define it anyway for my own peace of mind.

Recursion is defined as a repeated application of recursive procedures. (Long form for ‘something is being repeated’.)

“Yeah okay, that’s awesome, but how does that help me?”
Let’s look at a sandbox example.

Alt Text
This measly six lines of code will return a factorial of any number given to the function. This function is a common sandbox problem, with many different ways to solve it, however with recursion implemented, the function can be as short as possible. Let’s break it down.
As an example, say we plugged in 8 to the function. In the first line, the function checks to see if the n is less than or equal to 1. Since it is not, we continue, and return the value of whatever the product of n times n-1 is. Because of recursion, we can call this function ONCE with the desired number as n, and it will loop through, decreasing by 1 UNTIL n is equal to or less than 1. Thats a lot to take in, especially if you’re not familiar with recursion. Here is this function in action:

image
(For reference, a factorial is the product of a number times every number less than it, greater than 0.)
This function takes the number 8, multiplies it by 7, multiplies THAT product by 6, then THAT product by 5… etc. all the way down to 1, all in 6 lines of code. This would be irresponsibly complicated without recursion.
Recursion along with an if statement solves my, albeit unnecessary, desire for Javascript to have an until loop.
But honestly, that example was a bit too esoteric to really get a grasp on how awesome recursion really is. Let’s see a practical use.

reactJack

Recently, I built a black jack simulator. In the game of black jack, each player including the dealer is initially dealt two playing cards.

image
In the dealFirstTwo() function, the variable index will create a random number between 0 and (initially) 51. It will find a card inside of an array of objects I created called wholeDeck containing all 52 playing cards whose index in the array corresponds to the index variable. It will then set the dealt property of that found card object to true. The sortDeck() function sets the variable sortedDeck equal to all the objects inside the wholeDeck array whose dealt property equals false, which on the first pass is every card except the first card ‘dealt’. Then, the function will push the found card into the hand that is passed in as a parameter to the function (either playerHand or dealerHand, both just empty arrays initially). Finally, the function checks the length of the hand passed in as a parameter, and if the length is not equal to or greater than 2, it will repeat the function.

TL;DR: Give me a random number, find a card inside of a deck based on that number, tell that card its been dealt, tell the deck that card has been dealt, tell the player that the card belongs to it, and if the player doesn’t have two cards in his hand, give it another card.

Calling this function twice, with playerHand and dealerHand passed into the function as parameters respectively, we can efficiently deal two cards to a player and a dealer (and in theory, and as many players as needed).
And for one last example, another function in my blackjack simulator that handles the initial players turn uses recursion as well.

image
This function is a bit longer, but accomplishes the same idea. UNTIL a player either busts or chooses to stay, keep giving the player a card.
Here we have an if…else statement, with another if…else statement nested inside the else branch of the initial.
Line by line we have this:
If playerTotal (a variable set as the total of all values of the cards in a given hand) is greater than 21, tell the player ‘you’ve busted’, show the hidden dealer card, and then seeWhoWon(). If playerTotal is not greater than 21, send a confirmation window telling the player their total, and asking the player if they want another card (this returns a boolean value). If the player wants to hit, the dealOne() function deals one card (this function is the same as the function dealFirstTwo() above, without the recursive if statement). The playerTotal will be updated, showTertiaryPlayerCards() will show the card dealt on the screen, and after 500 milliseconds, the function will repeat. If the player does not want to hit, we pass the turn to the dealer, which is a similar function with a few more specifications for my very (very) simple ‘A.I.’.

TL;DR: Check to see if player has busted. If not, ask if they want a card. If they do, give them one, and repeat. If they don’t, its the dealers turn. If they busted, the dealer doesn’t get a turn, because the dealer wins automatically.

Hopefully this has cleared up the idea of recursion for some, and if not maybe it was able to show you the utility behind the idea.
Cheers!

Top comments (2)

Collapse
 
darrylnoakes profile image
Darryl Noakes • Edited

For "until", wouldn't while (!expression) work? Or did I miss something?

Collapse
 
jackismoe profile image
jackismoe

i had not considered using bang in a while loop when i wrote this. i will play around with it later today to see