Consider:
-module(example).
-export([cat/1]).
cat(string) -> "a" ++ " " ++ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ++ " long" ++ " string".
Are those concatenations performed at runtime?
A way to definitively answer that is to look at a readable intermediate compilation result - AKA, Core Erlang.
$ erlc +to_core example.erl
This yields an example.core file that answers the question:
module 'example' ['cat'/1,
'module_info'/0,
'module_info'/1]
attributes [%% Line 1
'file' =
%% Line 1
[{[101|[120|[97|[109|[112|[108|[101|[46|[101|[114|[108]]]]]]]]]]],1}]]
'cat'/1 =
%% Line 4
( fun (_0) ->
( case ( _0
-| [{'function',{'cat',1}}] ) of
<'string'> when 'true' ->
[97|[32|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[32|[108|[111|[110|[103|[32|[115|[116|[114|[105|[110|[103]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
( <_4> when 'true' ->
( primop 'match_fail'
(( {'function_clause',_4}
-| [{'function',{'cat',1}}] ))
-| [{'function',{'cat',1}}] )
-| ['compiler_generated'] )
end
-| [{'function',{'cat',1}}] )
-| [{'function',{'cat',1}}] )
'module_info'/0 =
( fun () ->
call 'erlang':'get_module_info'
('example')
-| [{'function',{'module_info',0}}] )
'module_info'/1 =
( fun (_0) ->
call 'erlang':'get_module_info'
('example', ( _0
-| [{'function',{'module_info',1}}] ))
-| [{'function',{'module_info',1}}] )
end
Useful discussion: https://erlangforums.com/t/core-erlang-why-have-e-1-e-n/3421
Although in this case, we're better off with BEAM assembly:
$ erlc -S example.erl
yielding example.S:
{module, example}. %% version = 0
{exports, [{cat,1},{module_info,0},{module_info,1}]}.
{attributes, []}.
{labels, 7}.
{function, cat, 1, 2}.
{label,1}.
{line,[{location,"example.erl",4}]}.
{func_info,{atom,example},{atom,cat},1}.
{label,2}.
{test,is_eq_exact,{f,1},[{x,0},{atom,string}]}.
{move,{literal,"a AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA long string"},
{x,0}}.
return.
{function, module_info, 0, 4}.
{label,3}.
{line,[]}.
{func_info,{atom,example},{atom,module_info},0}.
{label,4}.
{move,{atom,example},{x,0}}.
{call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
{function, module_info, 1, 6}.
{label,5}.
{line,[]}.
{func_info,{atom,example},{atom,module_info},1}.
{label,6}.
{move,{x,0},{x,1}}.
{move,{atom,example},{x,0}}.
{call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
You can go farther and get the machine assembly, but it's far from illustrative, and doesn't seem to include the string literal at all.
erl +JDdump true -eval 'example:cat(string), halt().' -noshell
yielding example.asm - along with .asm for every other loaded module.