Co-rotinas são um dos mais subestimados mecanismos de programação. Apesar de oferecerem um enorme poder expressivo e uma grande simplicidade de implementação, poucas linguagens oferecem mecanismos de co-rotinas. Um dos motivos para isto é a falta de uma caracterização precisa para co-rotinas. Os trabalhos pioneiros da área definiram e eventualmente implementaram co-rotinas de maneira confusa, o que levou a uma falta de consenso sobre o que são co-rotinas e qual seu real poder expressivo. Atualmente co-rotinas estão tendo um resurgimento de popularidade, mas novamente de forma confusa, com conceitos muito próximos (ou idênticos) a co-rotinas recebendo outros nomes (e.g., "fibers") e conceitos bem menos expressivos sendo apresentados como co-rotinas (e.g., "generators"). Neste trabalho, apresentamos um esquema de classificação para co-rotinas e discutimos o poder expressivo e a implementação dos vários tipos de co-rotinas. Em particular, mostramos que as chamadas "semi-co-rotinas" tem o mesmo poder expressivo que co-rotinas simétricas e que continuações "one-shot". Ilustramos também diversos usos de co-rotinas, como em algoritmos de busca de soluções e na implementação de multithreading não preemptivo.