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

¿Cómo usar el Dev Mode en Figma?

Checa este otro Post

meta cover

Efectos secundarios con useEffect

Checa este otro Post

¡Nuevo curso!

Animaciones web con React + Motion 🧙🏻