Вы можете использовать понимание списка, и даже не нужно отфильтровывать записи, которые не имеют вложенности.
Чтобы избежать проблем с читабельностью, я сократил определение вашей записи.
-record(l3, {key, value}).
-record(l2, {foo, bar, al3}).
-record(l1, {foo, bar, al2}).
Определите вспомогательную функцию для увеличения значения:
inc_value(#l1{al2=#l2{al3=#l3{value=Value}=L3}=L2}=L1) ->
L1#l1{al2=L2#l2{al3=L3#l3{value=Value+1}}};
inc_value(R) ->
R.
Обратите внимание на последнее предложение, которое отображает любые другие элементы, которые не соответствуют шаблону, к себе.
Позволяет определить примеры записей дляпопробуйте это:
1> R=#l1{foo=1, bar=2}.
#l1{foo = 1,bar = 2,al2 = undefined}
Это запись, для которой не определено полное вложение.
2> R1=#l1{foo=1, bar=2, al2=#l2{foo=3, bar=4, al3=#l3{key=mykey, value=10}}}.
#l1{foo = 1,bar = 2,
al2 = #l2{foo = 3,bar = 4,
al3 = #l3{key = mykey,value = 10}}}
Еще одна запись с полной структурой.
Попробуйте вспомогательную функцию:
4> inc_value(R).
#l1{foo = 1,bar = 2,al2 = undefined}
Он оставляет в стороне не полностью вложенную запись.
3> inc_value(R1).
#l1{foo = 1,bar = 2,
al2 = #l2{foo = 3,bar = 4,
al3 = #l3{key = mykey,value = 11}}}
Увеличивает полностью вложенную запись ok.
Теперь списокпонимание простое и читаемое:
5> [ inc_value(X) || X <- [R, R1] ].
[#l1{foo = 1,bar = 2,al2 = undefined},
#l1{foo = 1,bar = 2,
al2 = #l2{foo = 3,bar = 4,
al3 = #l3{key = mykey,value = 11}}}]