Ask HN: Reversible function definitions
There is a natural generalization of functions, called  <i>relations</i>. To benefit from relations, have a look at a <i>logic programming</i> language such as Prolog. In Prolog, relations are defined by <i>predicates</i> and constitute the basic building blocks of all Prolog programs.<p>A predicate is indeed sometimes called &quot;reversible&quot; if it can also be used in a direction that seems somewhat unexpected at first. For example, the predicate length&#x2F;2 can be used to <i>both</i> compute the length of a list and <i>generate</i> a list of a <i>given</i> length.<p>However, a predicate should ideally not only be &quot;reversible&quot;, but indeed <i>completely general</i>. This means that we should also be able to ask: Which solutions are there <i>at all</i>? This is a query where <i>nothing</i> is given, and the Prolog system must find solutions on its own. Indeed, length&#x2F;2 also satisfies this criterion. We can ask for example:<p><pre><code>   ?- length(Ls, L).
   Ls = [],
   L = 0 ;
   Ls = [_2168],
   L = 1 ;
   Ls = [_2168, _2174],
   L = 2 ;
   etc.
</code></pre>
and the Prolog system <i>generates</i> as many lists (and their lengths) as we want.<p>So, calling such predicates &quot;reversible&quot; still does not do justice to what they actually are, namely completely general <i>relations</i> that work in <i>all</i> directions. Therefore, when programming in Prolog, do not fall into the trap of calling your predicates &quot;reversible&quot; or &quot;usable in <i>the</i> other direction&quot; is if there were only <i>one</i> such other direction. Instead, think in terms of <i>relations</i> between entities, and use language features that allow such general reasoning.<p>For instance, let us consider your concrete example. Using Prolog and its CLP(R) <i>constraints</i>, we can very generally describe the <i>relation</i> between floating point numbers. CLP(R) is for example available in SICStus Prolog and also a few other systems:<p><pre><code>    :- use_module(library(clpr)).

    pi(Pi) :- Pi is 4*atan(1).

    rad_deg(Rad, Deg) :-
            pi(Pi),
            { Rad = Pi &#x2F; 180 * Deg }.
</code></pre>
Now the point: rad_deg&#x2F;2 is a general <i>relation</i> and can be used in <i>all</i> directions.<p>For example, it can be used to compute the first argument if only the second is known:<p><pre><code>  ?- rad_deg(Alpha, 45).
  Alpha = 0.7853981633974483 .
</code></pre>
Conversely, it can be used to compute the second argument if only the first is known:<p><pre><code>  ?- rad_deg(0.7853981633974483, Beta).
  Beta = 45.0 .
</code></pre>
Here is your slightly more complex example, which is also an instance of computing the <i>second</i> argument:<p><pre><code>   ?- pi(Pi),
      rad_deg(Alpha0, 45),
      { Alpha = Pi&#x2F;4 + Alpha0 },
      rad_deg(Alpha, Beta).
   ...,
   Beta = 90.0 .
</code></pre>
But it <i>does not stop</i> there! The relation can also be used <i>in the most general way</i> to answer: Which solutions are there <i>at all</i>?<p><pre><code>  ?- rad_deg(R, D).
  {D=57.29577951308232*R}.
</code></pre>
In this case, it provides an <i>answer</i> that expresses the <i>general relation</i> between the two arguments even though none of them are known.<p>And it <i>still</i> doesn&#x27;t stop there! The relation can also be used to ask: Does the relation hold between two <i>given</i> numbers?<p><pre><code>  ?- rad_deg(0, 0).
  true.
</code></pre>
If the relation <i>doesn&#x27;t</i> hold between two given floating point numbers, the system tells us:<p><pre><code>  ?- rad_deg(0, 1).
  false.
</code></pre>
So, this is a true <i>relation</i> between floating point numbers, usable in <i>all</i> directions!<p>Caveat: Floating point numbers are an extremely bad way to represent numbers, and I can only advice to use better representations instead. For example, Unum computing looks very promising. In Prolog, consider using <i>rational</i> numbers, available via CLP(Q). Declarative reasoning over <i>integers</i> is available via CLP(FD) constraints. All these systems let you implement general <i>relations</i> between numeric expressions.