lunes, 6 de abril de 2026

LLVM: una herramienta para crear compiladores

LLVM (Low Level Virtual Machine) es una infraestructura de compiladores que permite transformar y optimizar código de distintos lenguajes de programación. No es un compilador único, sino un conjunto de herramientas que sirven para crear compiladores, analizadores y optimizadores de código.

En este blog ya hemos hablado, burdamente, de lo que conforma un lenguaje de programación. Sin embargo, sería importante recordar algunos detalles.

Un compilador es un programa que traduce el código que escribes (por ejemplo en C, Rust o Java) a un lenguaje que la computadora entiende directamente: el código máquina. Ejemplo, tú escribes una receta en español, el compilador la traduce al "idioma" de la computadora para que pueda cocinarla.

Un analizador de código es la parte del compilador que lee y entiende tu código fuente. Verifica que lo que escribiste tenga sentido (sintaxis correcta, variables bien usadas, etc.). Es como un profesor que revisa tu redacción y te dice si las frases están bien construidas antes de publicarlas.

Un optimizador de código es una herramienta que mejora el código para que sea más rápido o consuma menos recursos. Reorganiza instrucciones, elimina pasos innecesarios y aprovecha mejor el hardware. Llanamente, el optimizador busca el camino más corto y rápido para llegar a algo.

Estos tres se relacionan de esta manera:

  • Analizador: entiende tu código y lo valida. 
  • Compilador: traduce ese código a instrucciones que la máquina entiende. 
  • Optimizador: pule esas instrucciones para que se ejecuten de la mejor manera posible.

LLVM al ser un conjunto de bibliotecas y herramientas que permiten construir compiladores y optimizadores no está limitado a un lenguaje específico; se usa en C, C++, Rust, Swift, Julia, Haskell, entre otros. Está diseñado como bloques reutilizables (frontends, optimizadores, backends).

¿Para qué sirve LLVM?

  • Compilación: Convierte código fuente en código máquina optimizado. 
  • Optimización: Mejora el rendimiento del código en tiempo de compilación y ejecución. 
  • Portabilidad: Permite que un mismo lenguaje se ejecute en múltiples plataformas. 
  • Experimentación: Ideal para investigadores y desarrolladores que quieren crear nuevos lenguajes o probar técnicas de optimización.
  • Ejemplo real: El compilador Clang (para C/C++/Objective-C) está construido sobre LLVM.

¿Qué hace LLVM?

  1. Traduce código a un lenguaje intermedio (LLVM IR) que es más fácil de analizar y optimizar. 
  2. Optimiza ese código para que sea más rápido y eficiente. 
  3. Genera código máquina para distintas arquitecturas (x86, ARM, etc.), lo que permite que tu programa corra en diferentes dispositivos.

LLVM es como el motor universal que hace funcionar muchos lenguajes modernos (Rust, Swift, Julia, Haskell).

Como desarrollador, puedes usarlo para compilar, optimizar y experimentar con lenguajes modernos o incluso crear el tuyo propio.

Probando LLVM

Vamos a comenzar instalandolo:

Linux:

$ sudo apt update
$ sudo apt install llvm clang

Windows:

$ choco install llvm

Vamos a crear un sencillo programa que verifique si un número entero es mayor a 100.

mayor.c

#include <stdio.h>

int main() {
    printf("\t Determinar si un número es mayor a 100 \n");
int numero = 120; if (numero > 100) { printf("El número es mayor que 100\n"); } else { printf("El número es menor o igual a 100\n"); } return 0; }

Compilams con la herramienta ``clang``:

$ clang mayor.c -o mayor

Creará un ejecutable:

$ ./mayor

Salida:

El número es mayor que 100

Ahora usaremos LLVM para ver el código intermedio (LLVM IR):

$ clang -S -emit-llvm mayor.c -o mayor.ll

Esto genera un archivo ``mayor.ll`` con el Intermediate Representation (IR). En ese archivo verás instrucciones más “básicas” que LLVM entiende, por ejemplo:

define i32 @main() {
entry:
  %numero = alloca i32, align 4
  store i32 120, i32* %numero, align 4
  %0 = load i32, i32* %numero, align 4
  %cmp = icmp sgt i32 %0, 100
  br i1 %cmp, label %if.then, label %if.else
  ...
}

Optimizamos el código:

$ clang -S -emit-llvm mayor.c -o mayor.ll

Esto genera una versión optimizada del IR, eliminando redundancias y mejorando el rendimiento.

Enlaces:

https://llvm.org/
https://codemonkeyjunior.blogspot.com/2024/02/lo-que-conforma-un-lenguaje-de.html
https://clang.llvm.org/
https://es.wikipedia.org/wiki/LLVM
https://www.reddit.com/r/ProgrammingLanguages/comments/kl7n03/what_is_meant_by_llvm_and_a_language_frontend/
https://aosabook.org/en/index.html

sábado, 4 de abril de 2026

WebAssembly con Dlang

WebAssembly es un lenguaje de bajo nivel, similar a ensamblador, diseñado para ser rápido de cargar y ejecutar en navegadores modernos. Su objetivo es permitir que aplicaciones escritas en distintos lenguajes se ejecuten en la web con velocidad casi nativa.

Los formatos que soporta son:

  • .wasm: un formato binario ejecutable. 
  •  .wat: un formato formato de texto legible.

Se complementa con JavaScript; permite invocar funciones WASM desde JS y viceversa. Y como vimos en este blog, también puedes optar por usar un lenguaje como Grain cuya compilación es directa a WASM.

¿Cuál es el objetivo de WebAssembly?

El objetivo de WebAssembly es compilar código escrito en lenguajes como Rust, C o C++ (entre otros) y transformarlo en un módulo .wasm que puede ejecutarse en navegadores o en entornos como Node.js con rendimiento cercano al nativo.

Flujo típico de trabajo con WebAssembly:

  1. Escribimos nuestro código en un lenguaje soportado (ej. Rust, C, C++, Go, AssemblyScript). 
  2. Compilamos ese código a WebAssembly y se generará un archivo .wasm
  3. Cargamos el módulo en tu aplicación web usando JavaScript. 
  4. Ejecutamos las funciones exportadas desde el módulo .wasm  como si fueran algo nativo.

¿Y qué con Dlang?

Dlang es un lenguaje similar al mítico y poderoso C. No solo en su sintaxis sino en su filosofía.

Dlang permite generar código WASM mediante la herramienta LDC.

Creando código WASM con Dlang

Crearemos una sencilla función llamada ``suma_wasm.d``.

extern(C): 

double suma(double a, double b) { return a + b; }

void _start() {}

Compilamos para generar el código WASM:

$ ldc2 -mtriple=wasm32-unknown-unknown-wasm -betterC suma_wasm.d

Ahora crearemos una página HTML para cargar el código WASM generado (suma_wasm.wasm).

index.html

<html>
  <head>
    <script>
      const request = new XMLHttpRequest();
      request.open('GET', 'suma_wasm.wasm');
      request.responseType = 'arraybuffer';
      request.onload = () => {
        console.log('respuesta recibida');
        const bytes = request.response;
        const importObject = {};
        WebAssembly.instantiate(bytes, importObject).then(result => {
          console.log('iniciado');
          const { exports } = result.instance;
          const r = exports.suma(33, 10.88);
          console.log('r = ' + r);
        });
      };
      request.send();
      console.log('solicitud enviada');
    </script>
  </head>
  <body>
    Código D desde WebAssembly
  </body>
</html>

Ahora ejecutaremos este comando para abrir la página web:

$ python -m http.server 8000

Abrimos un navegador en la ruta: http://localhost:8000

Salida:

solicitud enviada
respuesta recibida
iniciado
r = 43.88

WebAssembly permite que aplicaciones complejas escritas en lenguajes de alto nivel como D, C/C++, Rust, etc. se ejecuten en aplicaciones web a través de un compilado .wasm.

Imaginemos que hemos creado una aplicación para gestionar datos complejos en Rust o Java y la queremos ejecutar como una aplicación web. Con WebAssembly es posible. Se podrá compialr ese código y generar un archivo .wasm que podrá ser cargado en una página web.

Continuaremos con este tema en próximas entregas.

Enlaces:

https://dlang.org/
https://webassembly.org/
https://wiki.dlang.org/Generating_WebAssembly_with_LDC
https://alquimistadecodigo.blogspot.com/2026/04/webassembly-con-rust.html


jueves, 2 de abril de 2026

Grain, un lenguaje para WebAssembly

Grain es un lenguaje de programación funcional, moderno y de código abierto, diseñado principalmente para compilarse a WebAssembly (Wasm), lo que le permite funcionar eficientemente tanto en navegadores web como en servidores. Su objetivo es hacer accesibles las características avanzadas de los lenguajes funcionales, siendo fácil de aprender, fuertemente tipado y flexible.

¿Qué es WebAssembly?

  • Un formato de instrucciones binarias para una máquina virtual basada en pila. 
  • Diseñado como un destino de compilación portátil para lenguajes de programación, lo que permite su implementación en la web para aplicaciones cliente y servidor.

Características más importantes:

  • Eficiente y rápido. 
  • Seguro. 
  • Abierto y depurable. 
  • Parte de la plataforma web abierta.

Grain es una alternativa directa a la compilación de código wasm. Si quieres usar lenguajes como C o C++ tendrías que usar https://emscripten.org/. Si quieres usar Python podrás elegir entre https://pyodide.org/en/stable/, https://github.com/wasmerio/py2wasm o https://pygame-web.github.io/. Entre otras alternativas dependiende el lenguaje de programación (Java, C#, Kotlin, Scala, Go, etc.).

Grain posee sus propias herramientas para compilar código y su línea de comandos.

Lo puedes instalar en sistemas Mac OS, Linux y Windows.  Si no deseas instalarlo, puede visitar este sitio y probar el lenguaje: https://grain-lang.org/try/

Otra forma de obtenerlo es con Node (V22 como mínima versión). Primero clonamos el repositorio:

$ git clone https://github.com/grain-lang/grain
$ cd grain

Una vez clonado el repositorio y ubicandonos en el directorio ejecutamose estos comandos para su construcción:

$ npm ci
$ npm run compiler build

Validamos la instalación:

$ grain --version

¡Tenemos instalado Grain en nuestro sistema!

Ahora demos un vistazo al lenguaje.

Al ser un lenguaje fuertemente tipado posee tipos básicos como Number, Bool, String y Char. Observemos la siguiente tabla:

Tipo Descripción Ejemplo
Number Representa números enteros o decimales. let x: Number = 42
Bool Valores booleanos: verdadero o falso. let flag: Bool = true
String Secuencia de caracteres, texto. let msg: String = "Hola Grain"
Char Un solo carácter Unicode. let letter: Char = 'A'

Grain usa la palabra clave ``let`` para introducir nuevos valores con un nombre determinado, a los que se les llama enlaces:

module Main

let numero = 42
let bandera = true
let saludo = "Bienvenido a Grain!"
and letra = 'A'

Hola mundo en Grain

Probemos el clásico programa "Hola, mundo" en este lenguaje.

holamundo.gr

module HolaMundo

print("Hola, mundo en Grain")

Para compilar y ejecutarlo directamente tecleamos:

$ grain holamundo.gr

Con pasos separados:

$ grain compile holamundo.gr 
# Te creará un archivo `holamundo.gr.wasm`
$ grain run holamundo.gr.wasm

Notar que te crea un archivo WASM ejecutable.

Continuaremos con este tema en próximas entregas.

Enlaces:

https://grain-lang.org/
https://webassembly.org/
https://alquimistadecodigo.blogspot.com/2026/04/webassembly-hola-mundo-en-python-con.html




viernes, 27 de marzo de 2026

Programando en C# no. 14: gRPC con .NET

 

En el post pasado vimos cómo crear un sencillo proyecto tipo cliente-servidor con .Net y gRPC.

Continuando con el tema vamos a recordar un poco.

  • gRPC es una tecnología moderna ideal para microservicios de alto rendimiento, escalables y seguros. 
  • Protobuff es el mecanismo de serialización que usa gRPC
  • HTTP/2 como protocolo de comunicación, el cual prioriza solicitudes, permite la comprensión de encabezados, multiplexación (múltiples llamadas simultáneas) y tiene mayor seguridad.

Creando un proyecto cliente-servidor en .Net (C#)

Crearemos un proyecto cliente-servidor en el cual el cliente mandará un número entero y el servidor evaluará si es mayor o no a 100.

1. Creamos nuestro proyecto servidor:

$ dotnet new grpc -o GrpcServer

2. Entramos al directorio creado y agregamos los siguientes Nuget:

Por línea de comandos:

$ dotnet add package Grpc.AspNetCore
$ dotnet add package Google.Protobuf
$ dotnet add package Grpc.Tools

Desde el archivo ``GrpcServer.csproj``:

<ItemGroup>
  <PackageReference Include="Grpc.AspNetCore" Version="2.60.0" />
  <PackageReference Include="Google.Protobuf" Version="3.25.0" />
  <PackageReference Include="Grpc.Tools" Version="2.60.0" PrivateAssets="All" />
</ItemGroup>

Ejecutar esto para descargar paquetes:

$ dotnet restore

3. Crearemos un archivo *.proto, el cual tendrá el un servicio llamado Validar y un método llamado EsMayorQue100 que recibirá un NumeroRequest y devolverá un NumeroResponse.

Protos\validar.proto

syntax = "proto3";

option csharp_namespace = "GrpcDemo";

package validar;

service Validar {
  rpc EsMayorQue100 (NumeroRequest) returns (NumeroResponse);
}

message NumeroRequest {
  int32 valor = 1;
}

message NumeroResponse {
  bool es_mayor = 1;
}

4. Editamos el archivo ``GrpcServer.csproj`` para agregar el archivo *.proto:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <!--<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />-->
	<Protobuf Include="Protos\validar.proto" GrpcServices="Server" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Google.Protobuf" Version="3.34.1" />
    <PackageReference Include="Grpc.AspNetCore" Version="2.76.0" />
    <PackageReference Include="Grpc.Tools" Version="2.78.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

</Project>

5. Creamos el servicio:

ValidarService.cs

using GrpcDemo;
using Grpc.Core;

public class ValidarService : Validar.ValidarBase
{
    public override Task<NumeroResponse> EsMayorQue100(NumeroRequest request, ServerCallContext context)
    {
        bool resultado = request.Valor > 100;
        return Task.FromResult(new NumeroResponse { EsMayor = resultado });
    }
}

6. El programa principal del servidor será el siguiente:

Program.cs

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<ValidarService>();
app.Run();

Ahora vamos por el proyecto cliente.

7. Creamos el proyecto:

$ dotnet new console -o GrpcClient

8. Nos ubicamos en el directorio creado. Y configuramos el archivo ``GrpcClient.csproj``:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  
  
  
  <ItemGroup>
  <Protobuf Include="..\GrpcServer\Protos\validar.proto" GrpcServices="Client" />
</ItemGroup>
<ItemGroup>
  <PackageReference Include="Grpc.Net.Client" Version="2.60.0" />
  <PackageReference Include="Google.Protobuf" Version="3.34.1" />
  <PackageReference Include="Grpc.Tools" Version="2.78.0" PrivateAssets="All" />
</ItemGroup>


</Project>

Ejecutar esto para descargar paquetes:

$ dotnet restore

9. El programa principal del cliente será este:

Program.cs

using Grpc.Net.Client;
using GrpcDemo;

class Program
{
    static async Task Main(string[] args)
    {
        using var channel = GrpcChannel.ForAddress("http://localhost:5203");
        var client = new Validar.ValidarClient(channel);

        Console.Write("Ingrese un número: ");
        int numero = int.Parse(Console.ReadLine());

        var response = await client.EsMayorQue100Async(new NumeroRequest { Valor = numero });
        Console.WriteLine($"¿Es mayor a 100? {response.EsMayor}");
    }
}

10. Ejecutamos el servidor:

$ dotnet run --project GrpcServer

11. Ejecutamos el cliente:

$ dotnet run --project GrpcClient

Si todo va bien veremos esto en el servidor:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5203
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]

Del lado del cliente:

Ingrese un número: 23
¿Es mayor a 100? False

Podemos modificar el programa cliente de tal manera que solicite salir o continuar.

using Grpc.Net.Client;
using GrpcDemo;

class Program
{
    static async Task Main(string[] args)
    {
        using var channel = GrpcChannel.ForAddress("http://localhost:5203");
        var client = new Validar.ValidarClient(channel);

        string continuar;
        do
        {
            Console.Write("Ingrese un número: ");
            int numero = int.Parse(Console.ReadLine());

            var response = await client.EsMayorQue100Async(new NumeroRequest { Valor = numero });
            Console.WriteLine($"¿Es mayor a 100? {response.EsMayor}");
            Console.WriteLine();

            Console.Write("¿Desea continuar [s-n]? ");
            continuar = Console.ReadLine()?.Trim().ToLower();
            Console.WriteLine();

        } while (continuar == "s");

        Console.WriteLine("Adios");
    }
}

Salida:

Ingrese un número: 23
¿Es mayor a 100? False

¿Desea continuar [s-n]? s 
Ingrese un número: 200
¿Es mayor a 100? True 

¿Desea continuar [s-n]? n 
Adios

¡Hemos creado un proyecto cliente-servidor con gRPC y .NET!

Continuaremos con este tema en próximas entregas.

Enlaces:

https://codemonkeyjunior.blogspot.com/2026/02/grpc-una-alternativa-para-servicios-de.html
https://alquimistadecodigo.blogspot.com/2026/03/grpc-con-go.html
https://alquimistadecodigo.blogspot.com/2026/03/grpc-con-python.html


domingo, 22 de marzo de 2026

Una comparativa entre C# y Beef

Como vimos en una entrega anterior, Beef es un lenguaje de programación similar a C#. Con la peculiaridad que al instalarlo nos provee de su propio IDE.

Observemos un ejemplo. El clásico programa "Hola, mundo" escrito en Beef(lang):

HolaMundo.bf

using System;

class Program
{
    public static void Main()
    {
        Console.WriteLine("Hola, mundo en Beef!");
    }
}

Cualquier despistado diría que está escrito en C#, pero no nos confiemos en lo que vemos. Ahora observemos el mismo programa escrito en C#.

Program.cs

using System;

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Hola, mundo en C#!");
    }
}

La diferencia entre un programa y el otro es casi nula. Para hacer una comparativa entre estos dos lenguajes nos enfocaremos en:

  1. Paradigma que usan.
  2. Características más importantes.
  3. Tipos de datos que manejan.
  4. Sus estructuras de control.
  5. Funciones y procedimientos.
  6. Estructuras de datos.
  7. Manejo de errores.

Comparativa entre C# y Beef

1. Paradigma.

  • Ambos lenguajes son multiparadigma. 
  • Lo que sugiere que puedes crear programas con paradigma estructurado, funcional y orientado a objetos.

2. Principales características.

De C#:

  • Orientado a Objetos (POO). 
  • Seguridad de Tipos (Strongly Typed).
  • Multiplataforma.
  • Gestión Automática de Memoria.
  • Orientado a Componentes.
  • Integración con .NET. 
  • Sintaxis Moderna y Limpia. 
  • Interoperabilidad. 
  • Programación Asíncrona. 
  • LINQ (Language Integrated Query).

De Beef:

  • Sintaxis y Estructura. 
  • Alto Rendimiento. 
  • Productividad del Desarrollador. 
  • Gestión de Memoria. 
  • Características Modernas. 
  • Seguridad en Depuración. 
  • Compilación e IDE.

3. Tipos de datos.

Observemos una tabla comparativa.

Categoría C# Beef
Booleano bool bool
Enteros con signo sbyte, short, int, long, nint int8, int16, int32, int64, int
Enteros sin signo byte, ushort, uint, ulong, nuint uint8, uint16, uint32, uint64, uint
Punto flotante float, double, decimal float, double
Caracteres char char8, char16, char32
Cadenas string No hay tipo nativo, se usan arrays de char*
Referencia / Objeto object, dynamic, delegate structs (colecciones definidas por el usuario)
Especiales void, nullable types (ej. int?) void

C# es más rico que Beef en tipos de referencia y abstracciones de alto nivel.

Categoría C# Beef
Booleano
// C#
bool flag = true;
// Beef
bool flag = true;
Enteros con signo
// C#
int x = -42;
long y = 123456789;
// Beef
int32 x = -42;
int64 y = 123456789;
Enteros sin signo
// C#
uint a = 42;
byte b = 255;
// Beef
uint32 a = 42;
uint8 b = 255;
Punto flotante
// C#
float pi = 3.14f;
double e = 2.718;
decimal money = 99.99m;
// Beef
float pi = 3.14f;
double e = 2.718;
Caracteres
// C#
char letter = 'A';
// Beef
char16 letter = 'A';
Cadenas
// C#
string name = "Carlos";
// Beef
char8* name = "Carlos";
Referencia / Objeto
// C#
object obj = new object();
delegate void MyDelegate();
// Beef
struct Point { int x; int y; }
Point p = .(10, 20);
Especiales
// C#
void DoSomething() { }
int? maybe = null;
// Beef
void DoSomething() { }

4. Estructuras de control.

Observemos la siguiente tabla comparativa entre C# y Beef.

Estructura C# Beef
Condicional if/else
// C#
if (x > 10)
{
    Console.WriteLine("Mayor a 10");
}
else
{
    Console.WriteLine("Menor o igual a 10");
}
// Beef
if (x > 10)
{
    Console.WriteLine("Mayor a 10");
}
else
{
    Console.WriteLine("Menor o igual a 10");
}
switch / match
// C#
switch (day)
{
    case 1: Console.WriteLine("Lunes"); break;
    case 2: Console.WriteLine("Martes"); break;
    default: Console.WriteLine("Otro día"); break;
}
// Beef
switch (day)
{
    case 1: Console.WriteLine("Lunes"); break;
    case 2: Console.WriteLine("Martes"); break;
    default: Console.WriteLine("Otro día"); break;
}
Bucle for
// C#
for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}
// Beef
for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}
Bucle while
// C#
while (x < 10)
{
    x++;
}
// Beef
while (x < 10)
{
    x++;
}
Bucle do-while
// C#
do
{
    x++;
} while (x < 10);
// Beef
do
{
    x++;
} while (x < 10);
foreach
// C#
foreach (var item in list)
{
    Console.WriteLine(item);
}
// Beef
for (var item in list)
{
    Console.WriteLine(item);
}
break / continue
// C#
for (int i = 0; i < 10; i++)
{
    if (i == 5) break;
    if (i % 2 == 0) continue;
    Console.WriteLine(i);
}
// Beef
for (int i = 0; i < 10; i++)
{
    if (i == 5) break;
    if (i % 2 == 0) continue;
    Console.WriteLine(i);
}

La sintaxis de estructuras de control en Beef es prácticamente idéntica a la de C#, lo que facilita la transición entre ambos lenguajes.

La diferencia más notable está en el uso de foreach : en C# existe como palabra reservada, mientras que en Beef se usa un for con iteración directa sobre colecciones.

Ambos lenguajes soportan break y continue dentro de bucles, así como switch con casos y default.

5. Funciones y procedimientos.

Concepto C# Beef
Función simple
// C#
int Sumar(int a, int b)
{
    return a + b;
}
// Beef
int Sumar(int a, int b)
{
    return a + b;
}
Procedimiento (sin retorno)
// C#
void MostrarMensaje(string msg)
{
    Console.WriteLine(msg);
}
// Beef
void MostrarMensaje(String msg)
{
    Console.WriteLine(msg);
}
Parámetros por referencia
// C#
void Incrementar(ref int x)
{
    x++;
}
// Beef
void Incrementar(ref int x)
{
    x++;
}
Parámetros opcionales
// C#
void Saludar(string nombre = "Invitado")
{
    Console.WriteLine($"Hola {nombre}");
}
// Beef
void Saludar(String nombre = "Invitado")
{
    Console.WriteLine("Hola " + nombre);
}
Funciones anónimas / lambdas
// C#
Func cuadrado = x => x * x;
// Beef
function int(int) cuadrado = (x) => x * x;
Funciones dentro de estructuras/clases
// C#
class Persona
{
    public void Hablar()
    {
        Console.WriteLine("Hola!");
    }
}
// Beef
struct Persona
{
    public void Hablar()
    {
        Console.WriteLine("Hola!");
    }
}

6. Estructuras de datos.

Observemos la siguiente tabla comparativa.

Estructura C# Beef
Arreglos
// C#
int[] numeros = {1, 2, 3};
// Beef
int[] numeros = .(1, 2, 3);
Listas dinámicas
// C#
List lista = new List();
lista.Add(10);
// Beef
List lista = new List();
lista.Add(10);
Diccionarios / Mapas
// C#
Dictionary edades = new Dictionary();
edades["Ana"] = 25;
// Beef
Dictionary edades = new Dictionary();
edades["Ana"] = 25;
Conjuntos
// C#
HashSet conjunto = new HashSet();
conjunto.Add(5);
// Beef
HashSet conjunto = new HashSet();
conjunto.Add(5);
Pilas (Stack)
// C#
Stack pila = new Stack();
pila.Push(1);
// Beef
Stack pila = new Stack();
pila.Push(1);
Colas (Queue)
// C#
Queue cola = new Queue();
cola.Enqueue(2);
// Beef
Queue cola = new Queue();
cola.Enqueue(2);
Estructuras definidas por el usuario
// C#
struct Punto
{
    public int X;
    public int Y;
}
// Beef
struct Punto
{
    public int X;
    public int Y;
}

7. Manejo de errores.

Observemos la siguiente tabla comparativa.

Concepto C# Beef
Bloque básico try-catch
// C#
try
{
    int x = int.Parse("abc");
}
catch (FormatException ex)
{
    Console.WriteLine("Error de formato: " + ex.Message);
}
// Beef
try
{
    int x = int.Parse("abc");
}
catch (Exception ex)
{
    Console.WriteLine("Error: " + ex.Message);
}
try-catch-finally
// C#
try
{
    var file = File.Open("data.txt", FileMode.Open);
}
catch (IOException ex)
{
    Console.WriteLine("Error de E/S: " + ex.Message);
}
finally
{
    Console.WriteLine("Liberando recursos...");
}
// Beef
try
{
    var file = File.Open("data.txt", FileMode.Open);
}
catch (Exception ex)
{
    Console.WriteLine("Error: " + ex.Message);
}
finally
{
    Console.WriteLine("Liberando recursos...");
}
Lanzar excepciones
// C#
throw new InvalidOperationException("Operación inválida");
// Beef
throw new Exception("Operación inválida");
Excepciones personalizadas
// C#
class MiExcepcion : Exception
{
    public MiExcepcion(string msg) : base(msg) { }
}
// Beef
struct MiExcepcion : Exception
{
    public this(String msg) : base(msg) { }
}

Ejemplo. Crear un procedimiento donde se calcule el nuevo salario de una persona. Si el empleado es casado, tiene un salario menor a $30000.00 se le de un aumento del 0.05, en caso contrario solo será del 0.01.

En Beef:

        static void CalculoSalario()
	{
	        Console.WriteLine("\t [ Calculando nuevo salario en Beef  ]");
	        int edad = 0;
		String nombre = scope String();
		String edo_civil = scope String();
		double salario_bruto = 0;
		double salario_neto = 0;

		Console.WriteLine("Introduce tu nombre:");
		Console.ReadLine(nombre); // escribe en el buffer 'nombre'

		Console.WriteLine("Introduce tu edad:");
		String edadStr = scope String();
		Console.ReadLine(edadStr);
		edad = int.Parse(edadStr);

		Console.WriteLine("Introduce tu estado civil:");
		Console.ReadLine(edo_civil);

		Console.WriteLine("Introduce tu salario bruto:");
		String salarioStr = scope String();
		Console.ReadLine(salarioStr);
		salario_bruto = double.Parse(salarioStr);

		if (salario_bruto < 30000)
		{
		    if (edo_civil == "casado")
		    {
		        salario_bruto += salario_bruto * 0.05;
		    }
		    else
		    {
		        salario_bruto += salario_bruto * 0.01;
		    }

		    if (edad > 40)
		    {
		        salario_bruto += salario_bruto * 0.05;
		    }
		    else
		    {
		        salario_bruto += salario_bruto * 0.01;
		    }
		}

		salario_neto = salario_bruto;
		Console.WriteLine("Salario neto: {0}", salario_neto);
	}

En C#:

public static void CalculoSalario()
    {
        Console.WriteLine("\t [ Calculando nuevo salario en C# ]");
        int edad = 0;
        string nombre = "";
        string edo_civil = "";
        double salario_bruto = 0;
        double salario_neto = 0;

        Console.WriteLine("Introduce tu nombre:");
        nombre = Console.ReadLine();

        Console.WriteLine("Introduce tu edad:");
        string edadStr = Console.ReadLine();
        edad = int.Parse(edadStr);

        Console.WriteLine("Introduce tu estado civil:");
        edo_civil = Console.ReadLine();

        Console.WriteLine("Introduce tu salario bruto:");
        string salarioStr = Console.ReadLine();
        salario_bruto = double.Parse(salarioStr);

        if (salario_bruto < 30000)
        {
            if (edo_civil == "casado")
            {
                salario_bruto += salario_bruto * 0.05;
            }
            else
            {
                salario_bruto += salario_bruto * 0.01;
            }

            if (edad > 40)
            {
                salario_bruto += salario_bruto * 0.05;
            }
            else
            {
                salario_bruto += salario_bruto * 0.01;
            }
        }

        salario_neto = salario_bruto;
        Console.WriteLine("Salario neto: {0}", salario_neto);
      
    }

Salida:

         [ Calculando nuevo salario en C# ]
Introduce tu nombre:
Thomas Muller
Introduce tu edad:
34
Introduce tu estado civil:
casado
Introduce tu salario bruto:
29000
Salario neto: 30754.5

Como hemos visto, Beef es un lenguaje de programación que toma inspiración del lenguaje C#. Tanto su sitaxis como tipos de datos. Paradigma y esencia.

Sin embargo, C# es mucho más rico, más completo. Si tuvieras que elegir un lenguaje para crear un nuevo proyecto, C# sería mejor opción, pero Beef no se queda atrás, apenas comienza.

Continuaremos con esta serie de lenguajes de programación.

Enlaces:

https://www.beeflang.org/
https://dotnet.microsoft.com/es-es/languages/csharp
https://codemonkeyjunior.blogspot.com/2026/02/beef-y-c3-dos-lenguajes-de-programacion.html



LLVM: una herramienta para crear compiladores

LLVM ( Low Level Virtual Machine ) es una infraestructura de compiladores que permite transformar y optimizar código de distintos lengua...

Etiquetas

Archivo del blog