Sync’ up! … without getting drained

apr 23

Vibin’ With Erlang

In a previous post, the subject was how to reduce Erlang’s syntax ugliness. With a few heuristics, fuggly source code was something that could be mitigated.

Which is why it is with great sadness that I have to report that Erlang could be the worst victim from the transition to vibe coding.

With vibe coding, Erlang has fallen back into its old ways, and is ugly once again. (Perhaps the ugliest it has ever been). Here is a piece of code that is in the wild who’s author has confessed that it was written by an LLM:


handle_post_job(Req) ->
    case elli_request:body(Req) of
        <<>> ->
            ErrorResp = #{status => error, reason => <<"Missing request body">>},
            case msc_lib:term_to_json(ErrorResp) of
                Json when is_binary(Json) ->
                    {400, headers(json), Json};
                {error, _} ->
                    {400, headers(json), <<"{\"status\":\"error\",\"reason\":\"Missing request body\"}">>}
            end;
        Body ->
            % Convert JSON to Erlang terms at Elli boundary
            case msc_lib:json_to_term(Body) of
                RequestData when is_map(RequestData) ->
                    % Generate unique job ID
                    JobId = generate_job_id(),
                    % Start state machine worker
                    case msc_sm_sup:start_sm({id, JobId}, RequestData) of
                        {ok, Pid} ->
                            % Store in registry
                            store_job(JobId, Pid, pending),
                            % Send initial request to state machine
                            msc_sm:process_request(Pid, RequestData),
                            % Return job ID immediately
                            Response = #{status => ok, job_id => JobId},
                            case msc_lib:term_to_json(Response) of
                                Json when is_binary(Json) ->
                                    {201, headers(json), Json};
                                {error, _} ->
                                    {500, headers(json), <<"{\"status\":\"error\",\"reason\":\"JSON encoding failed\"}">>}
                            end;
                        {error, Reason} ->
                            % Format error reason for JSON response
                            ReasonBin = case Reason of
                                supervisor_not_started -> <<"Supervisor not started">>;
                                {invalid_supervisor, _} -> <<"Invalid supervisor">>;
                                {already_started, _} -> <<"Already started">>;
                                {shutdown, _} -> <<"Shutdown">>;
                                _ when is_atom(Reason) -> atom_to_binary(Reason, utf8);
                                _ when is_binary(Reason) -> Reason;
                                _ when is_list(Reason) -> 
                                    try list_to_binary(Reason)
                                    catch _:_ -> <<"List error">>
                                    end;
                                {Class, Detail} when is_atom(Class) ->
                                    DetailBin = case Detail of
                                        _ when is_binary(Detail) -> Detail;
                                        _ when is_atom(Detail) -> atom_to_binary(Detail, utf8);
                                        _ -> <<"Error detail">>
                                    end,
                                    <<(atom_to_binary(Class, utf8))/binary, ": ", DetailBin/binary>>;
                                _ ->
                                    % For complex terms, use a simple message
                                    <<"State machine startup failed">>
                            end,
                            ErrorResp = #{status => error, reason => ReasonBin},
                            case msc_lib:term_to_json(ErrorResp) of
                                Json when is_binary(Json) ->
                                    {500, headers(json), Json};
                                {error, _} ->
                                    {500, headers(json), <<"{\"status\":\"error\",\"reason\":\"JSON encoding failed\"}">>}
                            end
                    end;
                {error, _Reason} ->
                    ErrorResp = #{status => error, reason => <<"Invalid JSON">>},
                    case msc_lib:term_to_json(ErrorResp) of
                        Json when is_binary(Json) ->
                            {400, headers(json), Json};
                        {error, _} ->
                            {400, headers(json), <<"{\"status\":\"error\",\"reason\":\"Invalid JSON\"}">>}
                    end
            end
    end.

No human can read this. A typical juggler can have three balls going with ease, but throwing five, six, seven, eight, etc., into the fray — there’s no way he can keep up.

This is how it is with AI generated source code for languages that require a craftmaker’s touch. Here, the many nested case expressions are par for the course in something imperative like C, but for AI to assume this is the way forward for all languages, is just wrong.

Erlang, like SQL, is a declarative language. To write code that looks like C isn’t playing to the language’s strengths.

The worrying bit is that code like the forementioned could be the standard for what we tolerate — or even what we strive for. This sort of thing happens all the time in everyday life. This could even spawn a ‘race to the bottom’ in source code quality, where AI generates slop, slop is more prevalent in the wild, thereby reinforcing the per-cent slop that inspires future source code.

Times are changing

Not too far back, I sat with a friend of mine who is a seasoned developer over at Google, and we both agreed, sure, AI would be a great assistant to writing code. Give it mundane tasks to do, and presto, work is done a tad faster.

He has since fallen into the camp that developers are going bye-bye, and AI will be taking over code-bases.

I am still firmly in the first camp, but worry that the inmates — AI — will indeed take over the asylum. I worry only because of the craft of fine code will be lost for good. That’s the only aspect I worry about — an aesthetic one. I’m not sure what camp that puts me in — a group that worries about losing something like ‘beauty’ in code. But that’s just me: sad to see something like fine source code gone forever.