Funções

15/04/2008

Neste artigo vou falar um pouco mais sobre funções. Mais precisamente sobre como passar um número variável de parâmetros para elas.

Existem basicamente 3 (três) formas de se fazer isso:

1 – Passagem segura quanto ao tipo

Nesse tipo, a parte dos parâmetros com número variável é passada como um array. Sendo assim, apenas um tipo de parâmetro pode ser passado, mas em qualquer quantidade.

Considere o exemplo: 

void func(int[] p...)
{
    foreach(i, v; p)
        Stdout.formatln("p[{}] = {}", i, v);
}

Essa função pode ser usada como:
func()
func(10);
func(10, 15);

2 – Passagem estilo D

O porém de se usar a forma anterior é que apenas um tipo de argumento pode ser usado, e nem sempre isso é o desejado. Por isso existe um tipo, semalhante ao estilo C de se passar um número aleatório de parâmetros.

Considere o exemplo:

void func(...)
{
    foreach(i, arg; _arguments)
    {
        if(arg == typeid(int))
            Stdout.formatln("O argumento {} é um {} de valor {}", i, arg, *cast(int*)_argptr);
        else if(arg == typeid(float))
            Stdout.formatln("O argumento {} é um {} de valor {}", i, arg, *cast(float*)_argptr);
        _argptr += arg.tsize;
    }
}

Explanações

Quando é encontrado um “…” como argumento, você ganha duas variáveis ocultas: _arguments, um array de TypeInfo, e _argptr, um ponteiro void* para o primeiro argumento.´

Uma intância de TypeInfo é retornada pela expressão typeid, usada para RTTI (Run Time Type Information).

O método “tsize()” da classe TypeInfo retorna o tamanho do tipo.

Então basta ir tratando para cada tipo que você deseja que seja válido ou inválido:

assert(arg == typeid(char), "Tipo inválido");

Lembrando que um assert não termina o programa, simplesmente dispara um AssertError em Phobos ou um AssertException em Tango.

Só para frisar, se você estiver em um extern(C), você não ganha o _arguments.

3 – Tuplas

Esse tipo de passagem eu comecei a usar recentemente e, pelo menos para mim, já se tornou o melhor.

Uma tupla é um conjunto de coisas. Essas coisas podem ser tipos ou expressões, sendo que uma mesma tupla pode ter tipos e expressões, expressões de diferentes tipos, etc.

Esse tipo pode ser entendido como uma combinação dos dois anteriores, já que tuplas podem ser controladas como arrays, mas podem conter qualquer tipo em seu interior.

O único porém das tuplas é que seu tamanho deve estar disponível em tempo de compilação.

Para criar uma tupla, usa-se um template:

void func(P...)(P p)
{
    foreach(i, v; p)
        Stdout.formatln("p[{}] é um {} de valor {}", i, typeof(v).stringof, v);
}

Lembrando que void func(P...)(P p) é o mesmo que:

template func(P...)
{
    void func(P p)...
}

Lembrando que typeof retorna o tipo de uma expressão e a propriedade “.stringof” converte qualquer expressão para uma string. E quando eu digo expressão, dessa vez é a expressão mesmo. Por exemplo: (5 + 1).stringof não rende a string “6″, mas sim “5 + 1″.

Por hoje é só. Logo entrarei em mais detalhes sobre Tuplas (e templates no geral).

blogblogs tags:, ,

Entry Filed under: D, Dev. Tags: , , .

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Calendar

Abril 2008
D S T Q Q S S
« Fev   Mai »
 12345
6789101112
13141516171819
20212223242526
27282930  

Most Recent Posts