Em programação, uma sub-rotina aninhada (ou função aninhada) é uma sub-rotina encapsulada dentro de outra. A sub-rotina aninhada é acessível apenas na sub-rotina que a encapsula, ou pelas sub-rotinas aninhadas diretamente, ou indiretamente dentro da mesma sub-rotina encapsuladora. Teoricamente o aninhamento pode ser ilimitado, mas, na prática, apenas alguns níveis são aceitos, dependendo da implementação.
Essa técnica é uma forma de encapsulamento, e permite dividir tarefas procedimentais em sub tarefas que fazem sentido somente localmente. Em linguagens que suportam essa técnica, são geralmente aceitos outros tipos de aninhamento, como o aninhamento de constantes e tipos de dado.
Quando disponíveis, as sub-rotinas aninhadas são uma abordagem comum para implementar algoritmos com laços de repetição em linguagens funcionais.
O suporte a funções aninhadas varia entre as linguagens de programação. Enquanto é encontrado em linguagens estruturadas mais antigas, como C, ALGOL, Simula 67 e Pascal, além de ser amplamente utilizado no JavaScript, sua presença é comum em linguagens dinâmicas e funcionais. No entanto, não é suportado em algumas linguagens amplamente utilizadas, como C++.
Outras linguagens de programação oferecem vantagens semelhantes. Por exemplo, uma função lambda também permite que uma função seja definida em uma função (bem como noutro local) e permite a ocultação e o encapsulamento de dados semelhantes.
O escopo de uma função aninhada é o bloco que a contém, seja ele um bloco de função ou um bloco no corpo de uma função. Fora desse bloco, a função aninhada não é visível e não pode ser chamada pelo nome.
Uma função aninhada tem acesso aos identificadores (nomes de funções, variáveis, tipos, classes) declarados em qualquer bloco envolvente, exceto quando esses identificadores são mascarados por declarações internas com os mesmos nomes.
É possível declarar funções aninhadas dentro de outras funções, recursivamente, formando uma estrutura profundamente aninhada. Uma função profundamente aninhada pode acessar identificadores declarados em todos os blocos que a envolvem, incluindo funções anexas.
Por exemplo, se uma função PAI contém uma função FILHA
, a função FILHA
pode acessar as variáveis de PAI
. Se PAi
está dentro de outra função AVÓ
, então FILHA
também pode acessar as variáveis de AVÓ
.
Essas considerações são uma das razões pelas quais as funções aninhadas não são implementadas em algumas linguagens mais simples.
Segue um exemplo em Pascal:
function E(x: real): real
function F(y: real): real
begin
F := x + y
end
begin
E := F(3)
end
A função F
está aninhada em E
(note que x
é visível em F
, enquanto y
é invisível fora de F
).
Linguagens que suportam sub-rotinas aninhadas incluem: