Powered by AppSignal & Oban Pro

Typespec Drills

exercises/typespec_drills.livemd

Typespec Drills

Mix.install([
  {:jason, "~> 1.4"},
  {:kino, "~> 0.9", override: true},
  {:youtube, github: "brooklinjazz/youtube"},
  {:hidden_cell, github: "brooklinjazz/hidden_cell"}
])

Navigation

Home Report An Issue Documentation And Static Analysis Games: Documentation And Static Analysis

Typespec Drills

Drills help you develop familiarity and muscle memory with syntax through repeated exercises. Unlike usual problems, Drills are not intended to develop problem solving skills, they are purely for developing comfort and speed.

This set of drills is for typespecs. Follow the instructions for each drill and complete them as quickly as you can.

Review

You can define a function spec using the @spec module attribute. Each @spec includes the function parameter types, and the return value type.

@spec add(integer(), integer()) :: integer()
def add(int1, int2) do
  int1 + int2
end

You can define custom types using the @type module attribute. These custom types can be used inside and outside of the current module.

@type user :: %{
  name: string(),
  age: integer()
}

You can include multiple types using the | operator. This works for functions using @spec and in custom types.

@spec double(integer() | nil)

Function Specs

Add function @specs based on the function parameter names and return value.

Example Solution ```elixir defmodule FunctionSpecs do @spec do_nothing :: nil def do_nothing do nil end @spec accept_and_return_anything(any()) :: any() def accept_and_return_anything(anything) do anything end @spec double(float()) :: float() def double(float) when is_float(float) do float * 2.0 end @spec double(integer()) :: integer() def double(integer) when is_integer(integer) do integer * 2 end @spec double(number()) :: number() def double(number) do number * 2 end @spec add(integer(), integer()) :: integer() def add(integer1, integer2) do integer1 + integer2 end @spec multiply(integer(), integer()) :: integer() def multiply(integer1, integer2) do integer1 * integer2 end @spec divide(integer(), integer()) :: float() def divide(integer1, integer2) do integer1 / integer2 end @spec rounded_divide(integer(), integer()) :: integer() def rounded_divide(integer1, integer2) do div(integer1, integer2) end @spec concat(String.t(), String.t()) :: String.t() def concat(string1, string2) do string1 <> string2 end @spec to_string(integer()) :: String.t() def to_string(integer) do Integer.to_string(integer) end @spec merge(map(), map()) :: map() def merge(map1, map2) do Map.merge(map1, map2) end @spec split_and_lowercase(String.t()) :: [String.t()] def split_and_lowercase(string) do string |> String.downcase() |> String.split("", trim: true) end @spec string_to_int(String.t()) :: integer() def string_to_int(string) do String.to_integer(string) end @spec integers_to_strings([integer()]) :: [String.t()] def integers_to_strings(integers) do Enum.map(integers, fn int -> Integer.to_string(int) end) end @spec one_to_two(1) :: 2 def one_to_two(1) do 2 end end ```
defmodule FunctionSpecs do
  def do_nothing do
    nil
  end

  def accept_and_return_anything(anything) do
    anything
  end

  def double(float) when is_float(float) do
    float * 2.0
  end

  def double(integer) when is_integer(integer) do
    integer * 2
  end

  def double(number) do
    number * 2
  end

  def add(integer1, integer2) do
    integer1 + integer2
  end

  def multiply(integer1, integer2) do
    integer1 * integer2
  end

  def divide(integer1, integer2) do
    integer1 / integer2
  end

  def rounded_divide(integer1, integer2) do
    div(integer1, integer2)
  end

  def concat(string1, string2) do
    string1 <> string2
  end

  def to_string(integer) do
    Integer.to_string(integer)
  end

  def merge(map1, map2) do
    Map.merge(map1, map2)
  end

  def split_and_lowercase(string) do
    string
    |> String.downcase()
    |> String.split("", trim: true)
  end

  def string_to_int(string) do
    String.to_integer(string)
  end

  def integers_to_strings(integers) do
    Enum.map(integers, fn int -> Integer.to_string(int) end)
  end

  def one_to_two(1) do
    2
  end
end

Custom Types

Implement the following custom @types in the module below based on the comment describing them.

Example Solution ```elixir defmodule CustomTypes do # a string or number @type unparsed_number :: String.t() | number() # a list of strings @type strings :: [String.t()] # a map with :title (string) and :content (string) keys. @type book :: %{title: String.t(), content: String.t()} # A map with :name (string) and `:books` (a list of books) keys. @type author :: %{name: String.t(), books: [book()]} end ```
defmodule CustomTypes do
  # a string or number
  @type unparsed_number
  # a list of strings
  @type strings
  # a map with :title (string) and :content (string) keys. 
  @type book
  # A map with :name (string) and `:books` (a list of books) keys.
  @type author
end

Commit Your Progress

DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.

Run git status to ensure there are no undesirable changes. Then run the following in your command line from the curriculum folder to commit your progress.

$ git add .
$ git commit -m "finish Typespec Drills exercise"
$ git push

We’re proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.

We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.

Navigation

Home Report An Issue Documentation And Static Analysis Games: Documentation And Static Analysis