title: Elixir: Dynamic infix operator
body: <p>I'm trying to write a simple module function that takes an expression as a string like <code>"123 + 45"</code> and returns an answer. So:</p>
  
  <pre><code>Calculator.calculate("123 + 45")
  # =&gt; 168
  </code></pre>
  
  <p>I thought about just splitting the string on <code>(" ")</code> to get the integers and the operator, then basically calling <code>Code.eval_string</code> on it. Here was my first naive attempt:</p>
  
  <pre><code>defmodule Calculator do
    def calculate(str) do
      [x, oper, y] = String.split(str, " ")
      formula = "a = fn (c, d) -&gt; c operator d end; a.(c, d)"
      {answer, _ } = Code.eval_string(formula, [
        c: String.to_integer(x),
        operator: String.to_atom(oper),
        d: String.to_integer(y)
      ])
      answer
    end
  end
  </code></pre>
  
  <p>Then, in running it, I receive this error:</p>
  
  <pre><code>** (CompileError) nofile:1: undefined function c/1
      (elixir) src/elixir_fn.erl:10: anonymous fn/3 in :elixir_fn.expand/3
      (stdlib) lists.erl:1239: :lists.map/2
      (elixir) src/elixir_fn.erl:14: :elixir_fn.expand/3
  </code></pre>
  
  <p>I couldn't figure out why <code>c</code> was being evaluated as a function. I suspect that it has to do with the <code>operator</code> variable in the anonymous function. I confirmed that by rewriting it with a hardcoded operator:</p>
  
  <pre><code>defmodule Calculator do
    def calculate(str) do
      [x, _, y] = String.split(str, " ")
      formula = "a = fn (c, d) -&gt; c + d end; a.(c, d)"
      {answer, _ } = Code.eval_string(formula, [
        c: String.to_integer(x),
        d: String.to_integer(y)
      ])
      answer
    end
  end
  </code></pre>
  
  <p>Indeed, this produces the expected result. The question is:</p>
  
  <p><strong>Why did the presence of the <code>operator</code> variable binding in the anonymous function cause <code>c</code> to be evaluated as a function?</strong> </p>
  
  <p>It appears from the docs on <a href="https://hexdocs.pm/elixir/Code.html#eval_string/3" rel="nofollow noreferrer"><code>Code.eval_string</code></a> makes it seem as though the variable bindings can be just about anything as long as they're found in the keyword list that is the second argument to <code>eval_string</code>.</p>
  
  <p>In my second attempt, I thought about trying to convert the operator from the input string into an atom and convert the operator from an infix to a function call (i.e., from <code>1 + 3</code> to something like <code>1.(:+, [3])</code>. But that doesn't appear to be valid syntax.</p>
  
  <p>So my second question is:</p>
  
  <p><strong>Is it possible to write an expression with an infix operator such as <code>+</code> as a function, and then to be able do dynamically define that operator as an atom?</strong></p>