cover

El Parámetro Adaptador _ en Effect.gen: Una Sintaxis Alternativa Elegante


Escuchar este post

Selecciona una voz y genera audio para escuchar este post

Cuando trabajas con Effect.gen, es común encontrarse con dos sintaxis diferentes para manejar efectos. Una usa yield* directamente, y otra lo utiliza también pero con un parámetro adaptador representado comúnmente como _. Te explico todo sobre esta característica aquí. 👽

¿Qué es el Parámetro Adaptador?

El parámetro adaptador es una función que Effect.js proporciona como segundo parámetro en tu función generadora, permitiéndote ejecutar efectos de manera más explícita:

// Sintaxis tradicional con yield* Effect.gen(function* () { const config = yield* WhatsAppConfigSchema }) // Sintaxis con adaptador (_) Effect.gen(function* (_) { const config = yield* _(WhatsAppConfigSchema) })

Comparación de Sintaxis

Ambas sintaxis son funcionalmente idénticas y producen exactamente el mismo resultado:

| Método | Sintaxis | Ejemplo | | --- | --- | --- | | **Tradicional** | `yield* efecto` | `yield* Effect.succeed(42)` | | **Con Adaptador** | `yield* _(efecto)` | `yield* _(Effect.succeed(42))` |

Ejemplo Práctico: Configuración de WhatsApp

Veamos un ejemplo real que muestra ambas sintaxis:

import { Effect, Config } from "effect" // Schema de configuración const WhatsAppConfigSchema = Config.object({ apiKey: Config.string("WHATSAPP_API_KEY"), phoneNumber: Config.string("WHATSAPP_PHONE"), webhookUrl: Config.string("WHATSAPP_WEBHOOK_URL") }) // Versión tradicional const setupWhatsAppTraditional = Effect.gen(function* () { const config = yield* WhatsAppConfigSchema const client = yield* createWhatsAppClient(config) const webhook = yield* setupWebhook(config.webhookUrl) yield* Effect.log(`WhatsApp configurado para: ${config.phoneNumber}`) return { client, webhook, config } }) // Versión con adaptador const setupWhatsAppWithAdapter = Effect.gen(function* (_) { const config = yield* _(WhatsAppConfigSchema) const client = yield* _(createWhatsAppClient(config)) const webhook = yield* _(setupWebhook(config.webhookUrl)) yield* _(Effect.log(`WhatsApp configurado para: ${config.phoneNumber}`)) return { client, webhook, config } })

¿Por Qué Usar el Adaptador?

1. Claridad Visual y Explicitez

El adaptador hace más obvio que estás "ejecutando" un efecto:

Effect.gen(function* (_) { // Es muy claro que estas líneas ejecutan efectos const user = yield* _(getUserById("123")) const profile = yield* _(getProfile(user.id)) const settings = yield* _(getSettings(profile.id)) return { user, profile, settings } })

2. Compatibilidad con Herramientas

Algunas herramientas de análisis estático, linters o IDEs pueden manejar mejor la sintaxis con paréntesis:

// Algunas herramientas prefieren esto yield* _(Effect.tryPromise(() => fetch('/api/data'))) // Sobre esto yield* Effect.tryPromise(() => fetch('/api/data'))

3. Consistencia de Estilo

Algunos equipos adoptan esta sintaxis por consistencia y legibilidad:

Effect.gen(function* (_) { yield* _(Effect.log("Iniciando proceso")) const data = yield* _(fetchData()) const processed = yield* _(processData(data)) const result = yield* _(saveResult(processed)) yield* _(Effect.log("Proceso completado")) return result })

Ejemplo Complejo: Pipeline de Procesamiento

import { Effect, pipe } from "effect" interface ProcessingConfig { batchSize: number retryAttempts: number timeout: string } const processDataPipeline = (config: ProcessingConfig) => Effect.gen(function* (_) { yield* _(Effect.log("🚀 Iniciando pipeline de procesamiento")) // Configuración inicial const startTime = yield* _(Effect.sync(() => Date.now())) // Obtener datos const rawData = yield* _(fetchRawData(config.batchSize)) yield* _(Effect.log(`📥 Obtenidos ${rawData.length} registros`)) // Procesar en lotes const processedBatches = yield* _( Effect.forEach( rawData, (batch) => processBatch(batch, config.retryAttempts), { concurrency: "unbounded" } ) ) // Consolidar resultados const finalResult = yield* _(consolidateResults(processedBatches)) // Métricas finales const endTime = yield* _(Effect.sync(() => Date.now())) const duration = endTime - startTime yield* _(Effect.log(`✅ Pipeline completado en ${duration}ms`)) yield* _(Effect.log(`📊 Procesados ${finalResult.totalRecords} registros`)) return finalResult })

Firma de Tipos del Adaptador

La función adaptador tiene esta firma:

type Adapter = <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>

Es simplemente una función identidad que toma un efecto y devuelve el mismo efecto, pero proporciona una sintaxis más explícita. ✅

¿Cuál Sintaxis Elegir?

La elección entre ambas sintaxis es principalmente preferencia personal o convención de equipo:

Sintaxis Tradicional (sin adaptador)

Ventajas:

  • Más concisa y limpia
  • Menos caracteres para escribir
  • Sintaxis más directa

Cuándo usarla:

  • Proyectos personales o equipos que prefieren concisión
  • Cuando la legibilidad no se ve comprometida
  • Para efectos simples y directos

Sintaxis con Adaptador

Ventajas:

  • Más explícita sobre la ejecución de efectos
  • Mejor compatibilidad con algunas herramientas
  • Consistencia visual en pipelines complejos
  • Más clara para desarrolladores nuevos en Effect

Cuándo usarla:

  • Equipos que valoran la explicitez
  • Pipelines complejos con muchos efectos
  • Cuando se trabaja con herramientas que prefieren esta sintaxis
  • Proyectos donde la claridad es prioritaria

Consideraciones de TypeScript

Para usar cualquiera de las dos sintaxis correctamente, asegúrate de tener la configuración adecuada:

{ "compilerOptions": { "target": "es2015", // o superior "strict": true, // recomendado para mejor tipado "downlevelIteration": true // si usas target < es2015 } }

Recomendaciones Prácticas

  1. Mantén consistencia en tu proyecto - elige una sintaxis y úsala en todo el código
  2. Considera tu equipo - la sintaxis con adaptador puede ser más clara para principiantes
  3. Evalúa la complejidad - pipelines complejos pueden beneficiarse del adaptador
  4. Prueba ambas - experimenta para ver cuál se siente más natural

El parámetro adaptador (_) en Effect.gen es una característica elegante que proporciona una sintaxis alternativa para ejecutar efectos. 🧪

Aunque funcionalmente idéntica a la sintaxis tradicional con yield*, ofrece ventajas en términos de claridad, explicitez y compatibilidad con herramientas.

La elección entre ambas sintaxis depende de tus preferencias personales, las convenciones de tu equipo y la complejidad de tus pipelines de efectos. Lo importante es mantener consistencia y elegir la opción que haga tu código más legible y mantenible.


¿Te gustó este artículo? Compártelo con otros desarrolladores que puedan beneficiarse de aprender sobre Effect Generators.

Abrazo. Bliss. 🤓

Enlaces relacionados

Documentación oficial de Effect.js - Using Generators

meta cover

Astro. ¿Otro framework JavaScript?

Checa este otro Post

meta cover

Configurando Tailwind con Remix

Checa este otro Post

¡Nuevo curso!

Animaciones web con React + Motion 🧙🏻