featured image

Chandler Carruth propuso en la CppNorth 2022 la evolución de C++ hacia Carbon. Según indicaba en su charla, Java fue mejorado por Kotlin, JavaScript por TypeScript y ahora C++ puede serlo con Carbon, ¿puede ser un digno sucesor?

Comenzaremos analizando quién es Chandler Carruth, según la página de la conferencia, es el líder técnico de fundamentos de lenguajes de programación y software de Google. Parece una apuesta fuerte por parte de Google que nos deja muchos interrogantes como, ¿afectará este desarrollo a Go? ¿por qué no elegir Go, Rust, Zig o cualquier otro en lugar de crear Carbon?

¿Cuál es el objetivo de Carbon?

Carruth hizo una introducción mencionando la transición entre muchos lenguajes, de C a C++, de JavaScript a TypeScript, de Objetive-C a Swift, de Java a Kotlin, pero se preguntaba, ¿a qué evoluciona C++? ¿es un pokémon sin evolución?

Para poder vislumbrar un poco qué podría venir después de C++ tendríamos primero que ver para qué sirve o para qué es bueno C++. En 2019, Carruth habló hizo otra charla What is C++ Good For? (¿Para qué es bueno C++?) haciéndose estas preguntas junto con Titus Winters (también de Google) en una graciosa charla.

De esta última charla se desprenden algunas preocupaciones sobre C++ y algunas propuestas por prioridad:

  1. Software de rendimiento crítico. Uso de menos recursos, software más rápido.
  2. Evolución del Software, evolución del lenguaje. Si hay errores en el diseño, estos deben arreglarse.
  3. Simple, fácil de leer, fácil de entender, fácil de escribir. Pero priorizando la lectura porque se realizará muchas más veces.
  4. Garantías prácticas de seguridad y mecanismos de pruebas.
  5. Desarrollo rápido y escalable.
  6. Soporte para hardware, Sistemas Operativos y entornos a medida que evolucionen.

Estas propuestas crearon una semilla que según la cuenta de Github de Carbon comenzó a germinar y el 27 de abril de 2020 tuvo su primer commit (solo la licencia, Apache License 2.0), el 28 de abril su segundo commit con el código de conducta, forma de contribución y mucha documentación acerca de la propuesta.

En su documentación, al momento de hacer su primera subida, definen el proyecto de la siguiente forma:

El proyecto del lenguaje Carbon es un experimento para explorar un posible y distante futuro para el lenguaje de programación C++. Está diseñado alrededor de un conjunto específico de objetivos y casos de uso:

  1. Software de rendimiento crítico.
  2. Evolución de tanto lenguaje como software.
  3. Código fácil de leer, de entender y escribir.
  4. Garantías prácticas de seguridad y mecanismos de pruebas.
  5. Desarrollo rápido y escalable.
  6. Arquitecturas de hardware actuales, plataformas de SO y entornos a medida que evolucionen.
  7. Interoperatividad con y migración para código C++ existente.

Vemos que las promesas y objetivos se alinean con las propuestas o solicitudes realizadas en la presentación de 2019 y en vista de no poder realizar esto dentro de C++, piden al nuevo lenguaje la interoperatividad necesaria para convivir en proyectos de C++ existentes y permitir la migración progresiva.

Pero entonces, ¿quiere esto decir que Go, Rust, Zig, Nim u otros lenguajes no consiguen estos fines? ¿Por qué Carbon resuelve mejor este problema?

¿Por qué no elegir Go, Rust, Zig o cualquier otro?

Como menciona el último objetivo del proyecto Carbon, la interoperatividad es muy importante para ellos. Según indican en ese mismo documento inicial:

Otros lenguajes de programación no satisfacen actualmente estas necesidades eficientemente. Estos presentan desafíos en interoperatividad, migración y rendimiento que los hacen caros y potencialmente imposibles para migrar una base de código grande de C++.

Para empresas con proyectos enormes, no es una solución migrar a Rust o Go porque supone una reescritura demasiado costosa de la base de código fuente y un desafío importante para migrar porque al ser tan grande intervienen otros problemas específicos de las migraciones.

Aunque Google diseña, mantiene y usa Go, para ciertas bases de código que ellos mismos mantienen, el uso de Go es inviable por ese mismo problema. La transformación de todo el código a una base binaria completamente diferente supone el riesgo de no hacer la migración correctamente además de suponer un cambio enorme en un solo paso.

El empleo de Carbon supone un inicio sutil. Incorporar el lenguaje dentro de un proyecto grande e ir escribiendo código poco a poco, migrando solo pequeñas porciones cada vez hasta conseguir migrar todo el código.

La mayoría de gente piensa en lenguajes como Go o Rust como sucesores, pero realmente no se ven claros por los motivos anteriores y además porque para la mayoría de desarrollos en C++ el recolector de basura supone un despropósito. Volvemos al mismo punto de intentar mantener el mismo ecosistema.

El lenguaje sucesor tiene que:

  • Construirse en el ecosistema existente, sin crear uno nuevo.
  • Proporcionar interoperatividad bidireccional.
  • Optimizar la curva de aprendizaje y adopción.
  • Idealmente tener soporte de migración asistido por herramientas.

Siendo los tres pilares del lenguaje:

  • Interoperatividad.
  • Migración.
  • Evolución del lenguaje.

¿Afectará este desarrollo a Go?

La última pregunta y que muchos se realizan tras la presentación del proyecto, ¿es este lenguaje un competidor de Go? ¿cesará el desarrollo activo de Go al comenzar con Carbon?

En principio, el desarrollo de Carbon cubre otras necesidades diferentes a las que cubre Go. El lenguaje Go nació con unos objetivos a cumplir muy diferentes, enfocado en mantener una facilidad y rapidez importantes y cubrir desarrollos más enfocados en la concurrencia.

Go sigue siendo un lenguaje fuerte y cada vez más usado y al igual que Dart, se mantiene dentro de Google para los fines para los que se emplea que son diferentes a la motivación inicial y las necesidades a cubrir por Carbon.

¿Por qué un nuevo lenguaje y no arreglar C++?

Como hemos dicho anteriormente, la propuesta inicial de 2019 fue para mejorar el lenguaje C++. No obstante, un lenguaje que lleva con nosotros más de 30 años es difícil de arreglar, intentar mejorar su sistema se convierte en un tedioso y aburrido politiqueo con personas que pueden no querer cambiar el lenguaje o que simplemente tienen miedo de afectar a muchos haciendo esos cambios.

Parece que Google no estuvo por la labor de intentar convencer a la comunidad actual y al igual que pasó con Perl cuando surgió Raku, se optó por una salida tangencial, crear un nuevo lenguaje. Los motivos principales que les motivaron a tomar este camino fueron:

  1. La acumulación de deuda técnica en C++ heredada de C y que va aumentando año tras año.
  2. Se prioriza la retro-compatibilidad. Esto hace imposible arreglar algunos errores de diseño y haciendo aún más difícil arreglar la deuda técnica.
  3. El proceso de evolución de C++ hace que las mejoras sean difíciles. Cada proceso de mejorar el lenguaje debe pasar por ISO.

Un poco de código

Veamos un ejemplo de código, ¿cómo es este lenguaje?

// This code is in the `Geometry` package (and root namespace).
package Geometry api;

// It imports the default library of the `Math` package.
import Math;

class Circle {
  var r: f32;
}

fn ScaleAreaAndAppend(circle: Circle, log2_scale: i32,
                      results: Vector(f32)*) {
  var area: f32 = Math.Pi * c.r * c.r;

  // Compute the scale.
  let scale: i32 = 1 << log2_scale;

  // Apply the scale.
  area *= scale;

  // Append to in the provided container.
  results->append(area);
}

Vemos el código con algunos elementos que no pertenecen a C++ como var, let o fn pero que nos dejan claro qué realizan. Por un lado, var está claro que define nuevas variables y a diferencia de Go y otros lenguajes, los tipos no son inferidos, deben indicarse. También tenemos let que nos deja entrever su uso como una constante. Establece un valor pero este valor no cambiará. La palabra clave fn también está clara, define una función al igual que empleamos class para definir una clase.

La creación de los paquetes y su uso como podemos ver con Math indica una mejor organización del código al identificar cada llamada a función con el módulo del que proviene y cada fichero con el módulo (o paquete, package) que define.

Conclusiones

Creo que este patrón propuesto por Carruth es una muy inteligente forma de evolucionar un código. En lugar de cambiar completamente o migrar un código de un lenguaje antiguo o difícil, creamos un nuevo lenguaje dentro del mismo ecosistema que permita una alta interoperatividad y así facilitar el cambio y la migración poco a poco.

¿No estaría bien conseguir esto mismo con otros entornos y lenguajes como COBOL?

¿Qué te parece Carbon? ¿y la iniciativa de Carruth? ¿qué situaciones de migraciones o cambios has experimentado? ¡Déjanos tu comentario!