Retornar tupla em C?
Por definição matemática, de forma bem simples, uma tupla é um conjunto fixo e ordenado de itens. Algumas linguagens oferecem mecanismos parecidos. Go permite que uma função retorne múltiplos valores, enquanto Rust possui tuplas como parte da linguagem.
Quando falamos de C, não temos esse recurso diretamente na linguagem.
Para uma função retornar múltiplos dados, preciso fazer algo assim:
int parse_age(const char *str, enum parse_err *err);
Essa função retorna a idade se tudo estiver ok com str. Esse é um estilo clássico de programação em C. Se ocorrer um erro, a função pode retornar -1. E, se eu quiser mais uma camada de significado para esse erro, posso usar o ponteiro err para informar o que aconteceu.
Para ser bem sincero, gosto desse estilo.
Mas, também curto a ideia da função retornar tupla.
E posso simular isso em C. Disponibilizei uma lib utilitária
chamada Tuple-C.
DEF_CUSTOM_TUPLE_C(int, enum parse_err, tuple_age_t);
tuple_age_t parse_age(const char *str)
{
if (!str || *str == '\0') {
return (tuple_age_t) {
.data = 0,
.code = PARSE_ERR_INVALID_STR
};
}
/*...*/
tuple_age_t t;
t.data = age;
t.code = PARSE_OK;
return t;
}
O que mais gosto dessa proposta é que não ocorre alocação dinâmica de memória. Além disso, o tipo da tupla é criado durante a compilação a partir dos argumentos passados para o macro.
A tupla tuple_age_t é um struct que contém dois campos: "data" para receber o valor retorno
e "code" que representa um status que pode ser um código de erro. Se aplicarmos um zoom na
tupla vamos ver a seguinte definição de struct feita pelo macro DEF_CUSTOM_TUPLE_C().
typedef struct {
int data; /* argumento 1 do macro */
enum parse_err code; /* argumento 2 do macro */
} tuple_age_t; /* argumento 3 do macro */
O tipo de dados de data e code podem assumir qualquer tipo de dados, inclusive
ponteiro para um tipo de dado alocado via malloc(). Quanto ao nome da struct, ele pode
assumir o nome que fizer mais sentido para o contexto do seu projeto. A vantagem em usar Tuple-C é que não
preciso definir minhas structs manualmente para cada tipo de
dado e código de erro que quero que as funções retornem.
Para utilizar a biblioteca, basta incluir tuple_c.h no esquema de diretórios do
seu projeto. Mas recomendo testar antes, principalmente se não for um projeto pessoal.