App 2: Prompt the User (Scala 3 Video)
Introduction
Now that I’ve shown in the inside of the application — the functions that read-from and write-to the database file — I’ll switch gears and look at the outside of the function: the UI code that the user interacts with.
In this code we’ll continue to follow the rule that any function that interacts with the outside world must return Try
. With the database code it helps to think that we were working with remote servers, and the same is true here: you can imagine that we’re doing something like writing a REST API, and getting input from remote sources.
NOTE: I started to create this as a REST example, but that gets into too many things that aren’t important to our primary objectives. So I’m using the following “command-line UI” approach to keep things as simple as possible while we work with functions that return
Try
values.
Our main function
As I mentioned earlier, TDL’s main
method starts like this:
@main
def ToDoList() =
and I save that code in a file named ToDoList.scala
. After that, I add the call to my Database
class:
@main
def ToDoList() =
val db = Database("./ToDoList.dat")
Now the next thing the application needs to do is prompt the user for their input. So we’ll need a promptUser
function.
promptUser
Because promptUser
reaches out into the outside world, it needs to return a Try
. But because printing a couple of strings to STDOUT can’t really fail (unless there’s something seriously wrong with your computer), I won’t use the try
/catch
/finally
construct.
Instead I’ll use the Try
shortcut that I showed earlier, where you just pass your block of code into Try
’s constructor. Including the necessary import
statements, that code looks like this:
import scala.io.StdIn
import scala.util.{Try, Success, Failure}
def promptUser(): Try[Unit] = Try {
println("\n(Commands: a \"task\", d 1, u 1, h, q, v)")
print("Yo: ")
}
In that code:
- The
promptUser
function requires the twoimport
statements shown promptUser
doesn’t require any input parameters- Per the rule, it needs to return a
Try
- Because it can’t really fail, I declare that it returns
Unit
inside theTry
- The opening
Try {...
code tells us the code that follows is passed intoTry
’s constructor - In that code block, I prompt the user with a
println
call, followed by aprint
- I use
print
in the second line because it doesn’t put a newline character after the string; that leaves the user’s prompt on the same line as the string
Organizing the code
That’s all that’s needed to prompt a user for their input. However, knowing that I’m going to need a few other I/O-related functions, I want to get this code out of my main file. Because these functions are all related to I/O, let’s create a new file named IOHelper.scala
. Then we’ll create an IOHelper
object in it, and that object will contain my functions:
import scala.io.StdIn
import scala.util.{Try, Success, Failure}
object IOHelper:
def promptUser(): Try[Unit] = Try {
println("\n(Commands: a \"task\", d 1, u 1, h, q, v)")
print("Yo: ")
}
end IOHelper
Back to main
Now I can go back to my ToDoList.scala
file and put this code in it:
import IOHelper.*
@main def ToDoList() =
val db = Database("./ToDoList.dat")
promptUser()
At this point I’m ignoring the fact that promptUser
returns a Try
, but I’ll get back to that shortly. Before doing that, let’s write a function to read the user’s input.
Update: All of my new videos are now on
LearnScala.dev