Up until now, this project has had a severe lack of emojis. In this lesson, we'll learn how to use an external module to translate text into emojis. Once we're done, it should look something like this:
Your code should currently look like the code in
Part2.elm. You can either carry your code over from the last lesson, or start with the
- Access and utilize code in other modules
- Be able to write helper functions
- Understand where to place domain-specific code
Spoiler alert: Emojis are complicated! And creating a decoder-ring-style translator between plain text and emojis is no small feat. Thankfully, one of your teammates has already written an emoji converter library for you to use, so you don't have to deal with that complexity! The code is already in your skeleton, in
(In the style of secret decoder rings,
EmojiConverter implements a simple substitution cipher that works by replacing all the letters in a message with the corresponding letter in a shifted alphabet. A shared, secret value (called the "key") determines how much shifting occurs, and the original message can later be recovered if the key is known.)
We'll need to use that code to convert the display text from plain text to emojis. But how do we pull that code in to our application code?
That's where the Elm module system comes into play. Modules are simply collections of related functions. They are helpful for encapsulating behavior, and for providing clear boundaries between libraries. Let's take a look at the first few lines of
module EmojiConverter exposing (textToEmoji, emojiToText, supportedEmojis)
Like all Elm files,
EmojiConverter.elm starts off by telling us what module it defines. In other files, we'll be able to call its functions by using the
EmojiConverter namespace, in the same way we use the
This line also tells us the public API for the
EmojiConverter module — regardless of what else is defined in this file, other files can, at most, access the three functions defined above. Of the three publicly accessible functions, the
textToEmoji function seems like exactly what we are looking for.
Let's import the module into our file, by adding this to the list of imports:
Now let's try using the
textToEmoji function in our output text section.
Html.p [ Html.Attributes.class "center output-text emoji-size" ] [ Html.text (EmojiConverter.textToEmoji model.currentText) ]
Let's try to compile this, and...uh oh! You should be getting the following error:
-- TYPE MISMATCH -------------------------------------------------- ././Part2.elm The argument to function `text` is causing a mismatch. 42| Html.text (EmojiConverter.textToEmoji model.currentText) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Function `text` is expecting the argument to be: String But it is: String -> String
This error might seem like gibberish at first, but stay strong — Elm error messages are very good at telling you exactly what you need to know. In this case, it seems that, instead of passing
Html.text a string to render, we are passing it a function that takes a string and returns a string. In Elm-land, that often means that you passed too few arguments into a function — if a function takes two arguments, and you only provided it one, it will return a partially-applied function that still needs one more argument!
As you may have guessed, it seems like we're using
EmojiConverter.textToEmoji incorrectly. Let's take a look at its definition in
EmojiConverter.elm to figure out how to use it:
type alias Key = String textToEmoji : Key -> String -> String textToEmoji key text = ...
textToEmoji takes two arguments — a
Key and a
String, and returns a converted
String. If we look a few lines above in the file, we see that
Key is simply an alias for
Of course! Like any good decoder ring, the
EmojiConverter library uses a key to determine how to encode and decode messages. In this case, the key can be one of the emojis supported by the library. In order to turn text into emojis, we need to give it a key, as well as the text we hope to translate.
Let's go back to our code, and hard-code an emoji as the translation key.
Html.p [ Html.Attributes.class "center output-text emoji-size" ] [ Html.text (EmojiConverter.textToEmoji "😅" model.currentText) ]
Recompile the code, refresh your browser, and you should be in business!
Our First Refactor
While this solution works, I'd argue that the code has become harder to follow. Let's refactor!
First off, let's extract a helper function for translating text. We can add a function that consumes a model and returns emojis:
translateText model = EmojiConverter.textToEmoji "😅" model.currentText
Note: Type signatures are always optional in Elm, but they are highly encouraged — type signatures can be a good form of documentation, and they help the compiler make educated guesses about what went wrong when your code fails to recompile. Feel free to add your own to
We can now use this function in our
Html.text (translateText model)
Recompile your code and make sure everything still works!
Finally, let's pull out the hard-coded emoji key into something more readable. Let's create a
defaultKey that returns the "😅" emoji. Switch out the reference to the "😅" emoji key with references to the new
Once you think you've got it, recompile to make sure it worked. If you get stuck, check out
Part3.elm to see how we've implemented it, or flag down a TA or instructor.