In Elm strings are represented with double quotes:
Characters are represented with single quotes:
Character literals must contain exactly one character. Therefore, these expressions are illegal in Elm:
''. Strings can have as many characters as we want in them.
Multi-line strings are created using
""". That’s triple quotes. Here’s how we can insert a multi-line string in repl:
We don’t need to add
\ to the end of each line when we create a multi-line string in a file though. Define a constant called
revelation right above
Now pass the
revelation constant to
Refresh the page at
http://localhost:8000/elm-examples/Playground.elm. You should see the profound revelation George Costanza had when he was looking at the ocean on a dreary day.
We can use both single and double quotes inside a multi-line string. Using a single quote inside a single-line string is fine, but we need to escape the double quotes with
\ tells Elm that the double quotes immediately after it aren’t there to end the string. Similarly, a single quote must be escaped inside a character literal.
How do we escape the backslash itself? With another backslash.
To calculate a string’s length, we can use the
length function from String module.
Up until now, we have been creating only custom functions by explicitly defining them. Going forward we will make heavy use of built-in functions like
String.length which is a part of Elm’s standard library.
- Standard Library
- Most programming languages come with a standard library - a collection of functions and values most likely written in the same language. Elm follows that trend by providing a standard library of its own. All functions and values in Elm’s standard library are grouped into modules based on what type of data they operate on. For example, the
Stringmodule contains functions for manipulating strings. Similarly, the
Listmodule provides functions for manipulating lists. There are many more modules in the standard library for working with almost any type of data, for example Dict, Set, and Date to name a few. Some functions such as
toStringwork on multiple types of data. These generic functions are placed inside the Basics module.
Modules are further grouped into packages.
Basicsall belong to a package called Core which comes pre-loaded with the Elm Platform. Only the most essential packages are included in Elm Platform. Others are available for download from the online catalog.
elm-repl session is started, the
String module gets loaded automatically. Otherwise we would have to explicitly import it like this:
elm-repl automatically loads modules that are most frequently used in Elm. When using a function, it’s a good practice to prefix it with a module name for two reasons:
The prefix tells us where the function came from.
The prefix prevents name clashes between functions from different modules.
If we want to, we can expose the
length function so that we don’t have to use the prefix.
We used a slightly different syntax to import the
String module here. The
exposing (length) part tells Elm to expose the
length function so that we don’t have to prefix it with
String. As it happens, the
List module also provides a function called
length. What will happen if we expose that function too? Let’s find out.
In Elm, a list is a data structure for storing multiple values. We can create one with square brackets, e.g. [“Titan”, “Encaladus”]. We will cover lists in detail later.
Elm is confused. It doesn’t know which
length function we meant to use. But if we add a prefix, it will work just fine.
String module provides a function called
isEmpty that tells us whether a given string is empty or not.
This is more readable than using the
length function, where we have to explicitly compare the length to
++ operator is used to concatenate two strings.
We don’t need to prefix operators with a module name.
We can’t use
++ to combine characters or numbers though. These will give errors:
One way to combine characters is by converting them to strings first. We can use the
fromChar function to do that.
We can also combine two strings using the
String.append function is a special case of
++ operator which puts two appendable things together such as strings and lists.
Concatenating multiple strings
We can also combine more than two strings using the
Technically speaking, the
++ operator combines only two strings. In our example above, Elm first applies
++ to “Bears. “ and “Beats. “ resulting in “Bears. Beats. “. It then applies
++ with “Battlestar Gallactica.” as a second argument to produce the final string. We can also use
append to combine more than two strings. Although it tends to get a bit verbose.
Another way of concatenating multiple strings is by using the
concat function which requires us to put individual strings into a list.
Notice how we included the space between words as part of the individual strings themselves. That looks awkward. If we use the
join function instead, we don’t have to do that.
join takes two parameters:
A separator that separates individual strings when they all get combined.
A list of strings.
The separator can be anything we want.
Splitting a String
We can use the
split function to break a string into multiple parts. It’s the exact opposite of
Did you notice that in the first example above, when we split on
" ", we end up with four strings, while in the other examples the result is three strings? That’s because there is a space between the words “Battlestar” and “Gallactica.” If we wanted to get a result of three strings, we’d have to be more specific on what to split on like the following example:
Reversing a String
Let’s write a function that tells us whether or not a word is a palindrome. Palindrome is a word or groups of words that read the same forward as backward.
We reverse the word using the
reverse function and compare it with the original. If they both are same, we return
True. Now let’s have some fun with this function.
Unfortunately, our function is too simple to recognize the last example as a palindrome. See if you can improve it to return
True for that phrase too. Also, why is the word “palindrome” not a palindrome?
Filtering a String
Let’s say we need to do a background check on every candidate that wants to join the Enceladus Program for exploring one of Saturn’s moons. So we have asked the candidates to give us their social security number. Someone miscommunicated and asked them to enter it like this: 222-11-5555 when in fact our system doesn’t accept dashes. We can use the
filter function to get rid of them. But we can’t just apply it like this:
It expects a function that takes a character and returns a boolean. Let’s create a function which does exactly that.
In mathematics, a function that takes a value and returns a boolean is called a predicate function. You will often hear functions like
isValid being called a predicate.
If the character is
- we return
True. Let’s give the
isValid function to
filter and see what happens.
Aha! The dashes are gone. The following diagram illustrates how
filter fed each chracter from the string we provided into
isValid. If it returned
True, the character was kept, otherwise discarded.
filter is a higher-order function because it takes another function as an argument. The String module provides many more higher-order functions like this such as
map. We won’t cover them all here, but you should check them out from the official documentation.
Sometimes its desirable to inline the function that determines whether or not a value should be filtered instead of defining it separately.
This time we gave
filter a function that doesn’t have a name. It’s called an anonymous function. The following diagram explains various components of an anonymous function.
Anonymous functions are quite useful for writing quick inline functions. We will see more examples later. We can actually re-write the
isValid function like this:
As it turns out a function name is just a constant pointing to an anonymous function definition.
Formatting a String
We often need to convert a string to all upper or lower case. String module provides just the functions we need.
We can also trim unnecessary whitespaces from a string.
If we want to stuff more characters into a string, String module has functions for that too.
pad function pads both sides of a string with a character of our choice until it reaches the given length:
10. We can also pad only one side if we want.
We can check for substrings using the
We can also find out if a string starts or ends with a certain substring.
We can even pinpoint where exactly the substring lies with the
indexes returns an empty list when it can’t find the specified substring. Otherwise it returns an index where the substring starts for each occurrence. And remember when we count indexes in Elm, we have to start from
0. We can also use the
indexes function on multi-line strings.
Most functions in the
String module that help us locate substrings are case-sensitive.
Now that we know how to look for substrings, let’s go ahead and extract them using the
slice takes start and end indices of the substring we are interested in. But there is a catch. It stops at the character right before the end index. When we extracted “Bears”, we had to give 5 as the end index even though the last character on that word (
s) is located at index
4. We can also count backwards like this:
Counting backwards can be confusing. Because of how the end index works, we can’t extract the last dot (
.) if we count from the back.
-1 is the index of the last dot, but
slice only extracts characters up until the index before it. If we try to use
0 as the end, we get an empty string. Let’s just stick with the positive indices.
String module doesn’t provide an easy way to replace substrings yet. We will have to use regular expressions for that. The next section is all about them.
So far we only covered some of the most commonly used functions for manipulating strings. The
String module provides plenty more functions. You can learn all about them here.