Type of non-terminating function in Erlang
Asked Answered
Y

2

5

I'm learning Erlang and trying to use Dialyzer to get maximum type-safety when it's possible. There's a thing that I don't understand: what is the type of non-terminating function and how to denote it in -spec. Could anyone shed some light on this?

Yasminyasmine answered 12/5, 2016 at 10:49 Comment(0)
E
8

A function that loops forever and never terminates has the return type no_return(). (That return type is also used for functions that always throw exceptions, e.g. a custom error function. If you don't specify that return type, Dialyzer will tell you that the function "has no local return".)

This is mentioned in the Types and Function Specifications chapter of the Erlang Reference Manual:

Some functions in Erlang are not meant to return; either because they define servers or because they are used to throw exceptions, as in the following function:

my_error(Err) -> erlang:throw({error, Err}).

For such functions, it is recommended to use the special no_return() type for their "return", through a contract of the following form:

-spec my_error(term()) -> no_return().
Exude answered 12/5, 2016 at 11:20 Comment(2)
Thanks! I didn't think that this can be also applied to non-terminating functions!Yasminyasmine
This blog post describes the (unintentional) difference between no_return() and none() types in Dialyzer: joedevivo.com/2015/06/14/no-local-return.htmlGalliard
I
0

The following examples are in Elixir, but I believe they make the use of no_return and none in typespecs clear for Erlangers too:

 defmodule TypeSpecExamples do
   @moduledoc """
   Examples of typespecs using no_return and none.
   """

   @spec forever :: no_return
   def forever do
     forever()
   end

   @spec only_for_side_effects :: no_return
   def only_for_side_effects do
     IO.puts "only_for_side_effects"
     :useless_return_value # delete this line to return the value of the previous line
   end

   @spec print_dont_care :: no_return
   def print_dont_care do
     IO.puts("""
       A no_return function that does not loop always returns a value, \
       which can be anything, such as the atom #{only_for_side_effects()}
       """)
   end

   @spec always_crash :: none
   def always_crash do
     raise "boom!"
   end

   @spec value_or_crash(boolean) :: number | none
   def value_or_crash(b) do
     if b do
       1
     else
       raise "boom!"
     end
   end

 end
Intorsion answered 22/3, 2018 at 17:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.