D: lenguaje de programación de sistemas, multiparadigma y alto rendimiento

Descubre D: lenguaje de programación de sistemas multiparadigma, seguro y de alto rendimiento, tan rápido como C++ pero más expresivo y compacto.

Autor: Leandro Alegsa

El lenguaje de programación D es un lenguaje de programación de sistemas orientado a objetos, imperativo y multiparadigma. El lenguaje D se originó como una reingeniería de C++, y los objetivos de diseño de D intentan combinar el rendimiento de los lenguajes compilados con la seguridad y el poder expresivo de los lenguajes dinámicos modernos. El código D nativo suele ser tan rápido como el código C++ equivalente, a la vez que es más corto y seguro para la memoria.

 

Historia y estado actual

D fue creado por Walter Bright (Digital Mars) como una evolución de ideas de C++ con la intención de conservar el control y rendimiento típico de los lenguajes de sistemas, añadiendo a la vez abstracciones modernas. A lo largo del tiempo se realizó una revisión importante (D2) que introdujo muchas características del lenguaje tal como se conocen hoy. Actualmente el lenguaje y sus implementaciones son de código abierto, con varias cadenas de herramientas y compiladores activos que mantienen y desarrollan el ecosistema.

Características principales

  • Alto rendimiento: código nativo compilado, comparable en velocidad al C++ en muchos casos.
  • Multiparadigma: soporta programación imperativa, orientada a objetos, funcional y genérica.
  • Sistema de tipos estático y expresivo: inferencia parcial con auto, tipos inmutables (immutable, const), y anotaciones de seguridad (@safe, @trusted, @system).
  • Metaprogramación avanzada: plantillas potentes, mixins de cadena, introspección de tipos y ejecución de funciones en tiempo de compilación (CTFE).
  • Contratos y pruebas integradas: soporte para contratos (in/out/invariant), aserciones y bloques de prueba (unittest), lo que mejora la comprobación y la fiabilidad del código.
  • Gestión de memoria flexible: dispone de un recolector de basura en la implementación estándar, pero permite programación sin GC (@nogc) y manejo manual/fino de memoria cuando se necesita control de bajo nivel.
  • Elementos de conveniencia: arrays dinámicos y slices integrados, arreglos asociativos, cierres (closures), UFCS (Uniform Function Call Syntax) y overloading de operadores.
  • Calificadores de funciones: pure, nothrow y otros que ayudan a producir código más seguro y optimizable.

Compiladores, runtime y herramientas

  • DMD: compilador de referencia, enfocado en compilaciones rápidas y desarrollo.
  • LDC: backend LLVM, orientado a generar binarios altamente optimizados y aprovechar las optimizaciones de LLVM.
  • GDC: backend de GCC que permite integrarse con la cadena de herramientas de GNU.
  • druntime y Phobos: druntime es la biblioteca de tiempo de ejecución del lenguaje; Phobos es la biblioteca estándar que ofrece utilidades para colecciones, concurrencia, I/O, manipulación de cadenas, ranges, etc.
  • dub: gestor de paquetes y construcción estándar del ecosistema, facilita la gestión de dependencias y la publicación de librerías.

Interoperabilidad

D está diseñado para interoperar fácilmente con C: declarar funciones con extern(C) permite llamar y enlazar con librerías C de forma directa. También ofrece mecanismos para interactuar con C++ (extern(C++)), aunque la interoperabilidad completa con C++ puede ser más compleja debido a diferencias en ABI y características del lenguaje.

Ámbitos de uso y adopción

Gracias a su enfoque en rendimiento y productividad, D se utiliza en proyectos de programación de sistemas, bibliotecas de alto rendimiento, servidores y algunos motores o herramientas donde se requiere control de recursos y desarrollo ágil. Aunque su comunidad es más pequeña comparada con la de C++ o Rust, existen marcos (por ejemplo, para desarrollo web y concurrencia) y librerías que facilitan diversos tipos de aplicaciones.

Ventajas y consideraciones

  • Ventajas: mezcla de rendimiento y abstracciones modernas, sintaxis concisa, metaprogramación potente y buenas herramientas para pruebas y contratos.
  • Consideraciones: menor adopción industrial comparada con C++ o Rust, y la presencia de un recolector de basura en la implementación por defecto que puede influir en decisiones para sistemas con restricciones de tiempo real (aunque es posible escribir código sin GC).

Ejemplo breve

// Ejemplo sencillo en D: "Hola, mundo" y uso de un rango simple import std.stdio;  void main() {     writeln("¡Hola, mundo desde D!");     int[] arr = [1, 2, 3, 4, 5];     foreach (i; arr)         write(i, " ");     writeln(); } 

En resumen, D ofrece una alternativa moderna para programación de sistemas que apuesta por combinar velocidad, seguridad y expresividad, con un conjunto de herramientas y bibliotecas que permiten desarrollar desde utilidades de bajo nivel hasta aplicaciones de alto rendimiento.

Ejemplos

Ejemplo 1

Este programa de ejemplo imprime sus argumentos de línea de comandos. La función main es el punto de entrada de un programa D, y args es una matriz de cadenas que representan los argumentos de la línea de comandos. Una cadena en D es una matriz de caracteres, representada por char[] en D1, o immutable(char)[] en D2.

import std. stdio: writefln; void main(string[] args) { foreach (i, arg; args) writefln("args[%d] = '%s'", i, arg); }

La sentencia foreach puede iterar sobre cualquier colección. En este caso, está produciendo una secuencia de índices (i) y valores (arg) del array args. El índice i y el valor arg tienen sus tipos inferidos del tipo del array args.

Ejemplo 2

A continuación se muestran varias capacidades de D y compensaciones de diseño de D en un programa muy corto. Recorre las líneas de un archivo de texto llamado palabras.txt que contiene una palabra diferente en cada línea, e imprime todas las palabras que son anagramas de otras palabras.

import std. stdio, std. algorithm, std. range, std. string; void main() { dstring[][dstring] signs2words; foreach(dchar[] w; lines(File("words.txt"))     { w = w. chomp(). toLower(); clave inmutable = w. dup. sort(). release(). idup; signs2words[key] ~= w. idup; } foreach(words; signs2words) if(words. length > 1) writefln(words. join(" ")); }
  1. signs2words es una matriz asociativa incorporada que asigna claves dstring (32 bits / char) a matrices de dstrings. Es similar a defaultdict(list) en Python.
  2. lines(File()) produce líneas de forma perezosa, con la nueva línea. Luego hay que copiarlo con idup para obtener una cadena que se utilizará para los valores de la matriz asociativa (la propiedad idup de las matrices devuelve un duplicado inmutable de la matriz, lo que es necesario ya que el tipo dstring es en realidad inmutable(dchar)[]). Las matrices asociativas incorporadas requieren claves inmutables.
  3. El operador ~= añade una nueva cadena d a los valores de la matriz dinámica asociada.
  4. toLower, join y chomp son funciones de cadena que D permite utilizar con una sintaxis de método. El nombre de estas funciones suele ser muy similar al de los métodos de cadena de Python. La función toLower convierte una cadena a minúsculas, join(" ") une una matriz de cadenas en una sola cadena usando un solo espacio como separador, y chomp elimina una nueva línea del final de la cadena si está presente.
  5. La ordenación es una función de std.algorithm que ordena el array en su lugar, creando una firma única para las palabras que son anagramas entre sí. El método release() en el valor de retorno de sort() es útil para mantener el código como una sola expresión.
  6. El segundo foreach itera sobre los valores del array asociativo, es capaz de inferir el tipo de palabras.
  7. se asigna a una variable inmutable, su tipo se infiere.
  8. Se utiliza UTF-32 dchar[] en lugar de UTF-8 char[] normal, de lo contrario sort() se niega a ordenarlo. Hay formas más eficientes de escribir este programa, que utilizan sólo UTF-8.
 


Buscar dentro de la enciclopedia
AlegsaOnline.com - 2020 / 2025 - License CC3