Asking ChatGPT to translate Erlang to Elixir

I recently asked ChatGPT to translate some Erlang code into Elixir. Here’s an edited transcript, for your amusement and edification…

Me: Can you translate Erlang source code to idiomatic Elixir?

It: Yes, I can help translate Erlang code into idiomatic Elixir. Please provide the specific code you would like translated.

Me: [copies and pastes in https://raw.githubusercontent.com/erlang/otp/master/lib/observer/src/cdv_atom_cb.erl]

It: Here is the Elixir equivalent of the Erlang code you provided:

Screen Shot 2023-01-30 at 20.51.33

Me: Please try again, retaining comments.

It: Certainly, here is the translated Elixir code with the comments included:

Screen Shot 2023-01-30 at 20.50.48

Me: You omitted the header comment block.

It: My apologies! Here’s the complete code with the header comment block included:

Screen Shot 2023-01-30 at 20.54.53

Me: Why does the header bar on your responses say “python”?

It: The header bar displays the language that the code block is in. I apologize for the mistake. The code block above is in Elixir.

Me: Please reformat the code to match the output of “mix format”.

It: Certainly! Here’s the reformatted code:

Screen Shot 2023-01-30 at 20.56.39

Me: Hmmmm. The header bar still says “python”.

It: I apologize for the mistake. The code is indeed in Elixir, not Python. Here’s the corrected code:

Screen Shot 2023-01-30 at 20.57.41

Me: Please translate the code into idiomatic Elixir, retaining all comments (including header comments) and formatting the result to match the output of “mix format”. Be sure to use the correct language in the header bar.

It: Screen Shot 2023-01-30 at 21.01.13

Eventually, I managed to get a plausible translation:

It: Here’s the complete version of the code, including all comments and formatted to match the output of “mix format”:

defmodule CdvAtomCb do
  @moduledoc """
  Copyright Ericsson AB 2013-2018. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  """

  @doc """
  Callbacks for cdv_virtual_list_wx
  """
  @spec col_to_elem(id) :: atom | integer
  def col_to_elem(id), do: :id
  def col_to_elem(id), do: id + 1

  @doc """
  Defines the columns
  """
  @spec col_spec() :: [{"Creation order", :center, 100}, {"Atom", :left, 100}]
  def col_spec, do: [{"Creation order", :center, 100}, {"Atom", :left, 100}]

  @spec get_info(term) :: {:ok, {list, _}, _}
  def get_info(_), do: {:ok, info, tw} = CrashdumpViewer.atoms, {info, tw}

  @spec format({binary, atom}) :: [binary] | binary
  def format({bin, q}), do: [bin] when is_binary(bin)
  def format({bin, nq}), do: bin when is_binary(bin)
  def format(d), do: d
end

Careful Reader will notice that the first col_to_elem/1 definition needs a guard clause that only fires when id is an atom. In any event, I haven’t even tried to compile this code. Still, it’s pretty impressive, IMHO…

7 Likes

I saw a Tweet recently that described generating code with ChatGPT as “like trying to get an inattentive and mediocre interview candidate to complete a coding exercise” and this feels like one of those cases.


  @spec col_to_elem(id) :: atom | integer
  def col_to_elem(id), do: :id
  def col_to_elem(id), do: id + 1

As you noted, this is missing a pattern-match for :id on the first part - it also returns the wrong type since the callback is expected to return an integer. The incorrect return type is correctly inferred in the @spec, but the id in the spec will fail compilation.

  @spec col_spec() :: [{"Creation order", :center, 100}, {"Atom", :left, 100}]
  def col_spec, do: [{"Creation order", :center, 100}, {"Atom", :left, 100}]

I don’t believe this spec is wrong, but it’s likely not what a developer would write. There are two other problems with this function:

  • the original had charlists in the first position, this has binaries
  • the original relied on defines from wx.hrl to fill in ?wxLIST_FORMAT_CENTER, which is the number 2 not :center
  @spec get_info(term) :: {:ok, {list, _}, _}
  def get_info(_), do: {:ok, info, tw} = CrashdumpViewer.atoms, {info, tw}

This won’t compile, as the comma doesn’t work as an expression separator - apart from that, the code would work. The generated @spec is… confused.

  @spec format({binary, atom}) :: [binary] | binary
  def format({bin, q}), do: [bin] when is_binary(bin)
  def format({bin, nq}), do: bin when is_binary(bin)
  def format(d), do: d

Interestingly, the generated @spec included the idea that the second element of the tuple could be an atom despite getting the return type completely wrong (it should be a charlist). The generated code didn’t use that information, and uses guard clauses in the wrong place.

It also entirely loses the key distinction between the :q and :nq code paths: putting a literal ' character in the resulting charlist.


Final score

Functions: 4
Valid functions: 1
Functions that would return the right types if the compiler errors were fixed: 0

4 Likes

Thanks for the detailed analysis!

I have had a lot of problems getting ChatGPT to write Elixir. I asked it to port some Ruby to Elixir and the result was mostly Ruby. It’s probably because Elixir isn’t “mainstream” enough.