🧩 PL/I — 1964

⬅️ Atlas · 🧟 Lenguajes que siguen vivos · 📚 Índice de clases

El lenguaje que quiso ser todos los lenguajes. IBM lo diseñó para unificar el mundo científico de Fortran y el mundo empresarial de COBOL en una sola herramienta. No lo consiguió, pero por el camino inventó buena parte de lo que hoy damos por sentado.

🎯 Por qué está en este programa

Criterio de inclusión: PL/I sigue en producción sobre z/OS. IBM mantiene y vende Enterprise PL/I for z/OS, integrado con CICS, Db2 e IMS, y publica documentación actual. Es un nicho mucho menor que el de COBOL, pero es un nicho real: bancos y aseguradoras con aplicaciones críticas que nunca se reescribieron.

Entra por dos conceptos que el núcleo no muestra. El primero es técnico: PL/I tuvo manejo estructurado de excepciones (ON conditions), punteros, multitarea y aritmética decimal a la vez, en 1964 — antes de que ninguna de esas ideas se considerara normal. Leerlo es ver el origen del try/catch. El segundo es una lección de diseño de lenguajes, que es de lo que trata la Parte 1: PL/I es el caso de estudio canónico de qué pasa cuando un lenguaje intenta cubrirlo todo. Dijkstra lo usó como advertencia; entender por qué es más útil que memorizar la anécdota.

Año 1964 (como NPL); estándar ANSI en 1976
Autoría IBM con el comité de usuarios SHARE, para el System/360
Familia Propósito general — síntesis deliberada de ALGOL, FORTRAN y COBOL
Paradigma Imperativo, procedimental, estructurado, con concurrencia
Tipado Estático, con conversión implícita muy permisiva entre tipos
Memoria Cuatro clases de almacenamiento: STATIC, AUTOMATIC, CONTROLLED, BASED
Ejecución Compilado a nativo (z/OS, AIX, Windows, OS/2)
Estado 🟡 Vivo pero minoritario — mainframe empresarial, mucho menor que COBOL

📜 Historia

En 1963 IBM tenía un problema de estrategia. Sus clientes científicos usaban FORTRAN, sus clientes empresariales usaban COBOL, y la nueva línea System/360 pretendía ser una sola familia de máquinas para todos. Tener dos lenguajes y dos comunidades separadas contradecía la idea. El comité Advanced Language Development del grupo de usuarios SHARE recibió el encargo de diseñar un lenguaje único.

El resultado, primero llamado NPL (New Programming Language) y renombrado PL/I por conflicto de marcas, se publicó en 1964. Su ambición era total: cálculo científico en punto flotante y aritmética decimal empresarial, procesamiento de cadenas, ficheros, punteros y estructuras dinámicas, multitarea, y manejo de condiciones excepcionales con ON ERROR, ON ENDFILE, ON OVERFLOW. Todo eso, en 1964, cuando FORTRAN no tenía siquiera estructuras de datos y COBOL no tenía punteros.

También llevó al extremo una idea peligrosa: no hay palabras reservadas. IF IF = THEN THEN THEN = ELSE; es una sentencia legal de PL/I, porque IF, THEN y ELSE pueden ser nombres de variable y el compilador lo resuelve por contexto. Sumado a la conversión automática entre casi cualquier par de tipos, el lenguaje se volvió difícil de compilar y, sobre todo, difícil de predecir.

Esa es la crítica que lo persigue. Edsger Dijkstra escribió en 1972, en su conferencia del Premio Turing The Humble Programmer, uno de los juicios más citados de la disciplina: describió a PL/I como un lenguaje cuya complejidad lo hacía inmanejable, comparándolo con una enfermedad fatal. La frase es célebre y algo injusta —PL/I hizo cosas notables— pero señala un problema real: la generalidad tiene un coste cognitivo, y ese coste lo paga quien lee el código.

Un dato que compensa la mala fama: Multics, el sistema operativo del MIT/Bell Labs que inspiró directamente a Unix, se escribió en un subconjunto de PL/I llamado EPL. Fue de los primeros sistemas operativos escritos en un lenguaje de alto nivel, y esa decisión influyó en que Ken Thompson y Dennis Ritchie escribieran Unix en C.

🏭 Dónde sobrevive hoy

Un patrón habitual: PL/I para la lógica compleja y de cálculo, COBOL para el grueso del proceso por lotes, ambos orquestados por JCL.

🧠 Por qué no ha muerto

1. Estaba donde estaba el dinero, y funcionó. Las razones son las de COBOL: reglas de negocio sedimentadas, riesgo asimétrico y coste de migración.

2. IBM lo sigue manteniendo. Enterprise PL/I for z/OS recibe versiones nuevas, con explotación de las instrucciones modernas del procesador z e interoperabilidad con COBOL, C y Java en el mismo sistema. No es un compilador abandonado.

3. Es más expresivo que COBOL para cálculo. Donde COBOL necesita rodeos, PL/I tiene expresiones, recursión, punteros y estructuras dinámicas. En aplicaciones actuariales o de riesgo, eso importaba.

4. Su modelo de excepciones es genuinamente bueno. Las ON conditions permiten instalar manejadores por condición (ZERODIVIDE, OVERFLOW, ENDFILE, KEY) y, en muchos casos, continuar la ejecución. Es más parecido al sistema de condiciones y reinicios de Common Lisp que al try/catch que heredamos.

🔄 Lo que se ha modernizado

Menos que COBOL, pero más de lo que su fama sugiere:

Lo que no ha ocurrido: no hay una comunidad libre significativa ni un compilador abierto de referencia. Esa es la diferencia práctica con COBOL, que sí tiene GnuCOBOL, y la razón por la que PL/I está en 🟡 y no en 🟢.

⚙️ Cómo se ejecuta hoy

En producción: IBM Enterprise PL/I for z/OS. Compilación mediante JCL invocando el compilador, enlace y ejecución.

Fuera del mainframe: existen implementaciones para otras plataformas —Micro Focus / OpenText Open PL/I y Iron Spring PL/I (un subconjunto para Linux y OS/2)— pero son minoritarias y parciales.

//COMPILA  EXEC PGM=IBMZPLI,PARM='OBJECT,SOURCE'
//SYSIN    DD   DSN=MI.FUENTE(TOTVTA),DISP=SHR
//SYSLIN   DD   DSN=&&OBJ,DISP=(NEW,PASS)

Es decir: para compilar PL/I hay que escribir JCL. Otro recordatorio de que en el mainframe ningún lenguaje se usa solo.

🧪 El programa de la clase 041 en PL/I

⚠️ Material de lectura, no verificado. No hay compilador PL/I en los runners de CI. El código está escrito para ser correcto e idiomático, pero sin el sello de la máquina, y así se declara.

 total_venta: procedure options(main);

    declare precio     fixed decimal(11,2);
    declare cantidad   fixed decimal(11,2);
    declare descuento  fixed decimal(5,4);
    declare total      fixed decimal(15,2);
    declare presenta   picture 'ZZZZZZZZZ9V.99';

    on endfile(sysin) stop;

    get list (precio, cantidad, descuento);

    total = precio * cantidad * (1 - descuento);

    presenta = total;
    put skip list ('Total: ' || trim(presenta));

 end total_venta;

Recorrido, línea a línea.

Lo que no se ve pero define al lenguaje: casi cualquier asignación entre tipos distintos funcionaría aquí. Asignar una cadena '27000' a un fixed decimal compila y convierte. Es cómodo y es, a la vez, exactamente la propiedad que hace que los errores de PL/I se manifiesten tarde. Compara con Ada, diseñado veinte años después con la filosofía contraria.

🔍 Qué reconocer si vienes de otro lenguaje

Si conoces… En PL/I es…
int / double fixed binary(31) / float binary(53)
decimal / BigDecimal fixed decimal(15,2) — nativo
try { } catch (E e) { } on condition ... ; — instalado, no envuelto
struct declare 1 registro, 2 campo ...; — niveles, como COBOL
Puntero pointer con variables based
malloc / free allocate / free sobre almacenamiento controlled o based
static / variable local static / automatic — las clases de almacenamiento son explícitas
Hilos task — multitarea en el lenguaje, en 1964
printf("%s", x) put skip list (x) o put edit (x) (formato)

⚠️ Errores comunes al leerlo

📚 Fuentes y bibliografía


⏮️ Volver al Atlas · 🧟 Los lenguajes que siguen vivos · 🔗 Relacionadas: COBOL · RPG · JCL · C