Programación funcional reactiva

Programación funcional y reactiva - Computación

Profesor: Ing. Santiago Quiñones

Docente Investigador

Departamento de Ingeniería Civil

Contenidos

Introducción a la programación funcional reactiva

Programación reactiva

Manejo de datos

  • Flujo infinitos de datos
  • Se reacciona cuando llega un grupo de datos
  • Reacciones de manera asíncrona
  • Patrón observer

 

Enfoques

Programación reactiva

Functional reactive programming

  • Comportamiento o señales
  • Comportamientos son valores continuos que siempre tienen un valor actual. Ej. la posición del mouse

 

Enfoques

Eventos vs Comportamientos

Diferencias

Functional Reactive Programming

Enfoques

¿Cómo hacer algo parecido usando PF?

Functional Reactive Programming

Definición

Una forma de expresar un programa como una reacción a sus entradas o como un flujo de datos.

Functional Reactive Programming

Configuración de entorno

Configura tu archivo build.sbt con la siguiente dependencia

"de.tu-darmstadt.stg" %% "rescala" % "0.35.0"

Import necesario

import rescala.default._

 

 

Functional Reactive Programming

Ejemplo

  • Var: variable inteligente
  • Signal: definición reactiva (re-calcula cuando su dependencias cambian)
  • Obs: Var o Signal

Functional Reactive Programming

Funcionamiento

Functional Reactive Programming

Ejemplo

import rescala.default.*

object GrafoDependenciasEncadenadas extends App {
  val a = Var(1) // 1
  val b = Var(2) // 2
  
  val c = Signal { a.value + b.value } // 3
  val d = Signal { c.value * 5 } // 15
  val e = Signal { c.value + 4 } // 7
  val f = Signal { d.value + e.value + 4 } // 26
  
  println(f.now) // 26
  
  a.set(3)
  
  println(f.now) // 38
}

Functional Reactive Programming

Ejemplo

import rescala.default.*

object Ejemplo2 extends App {
  val a = Var(1)                             //  1
  val b = Var(2)                             //  2
  val c = Signal { a.value + b.value }       //  3
  val d = Signal { c.value * 5 }             // 15
  val e = Signal { c.value + 4 }             //  7
  val f = Signal { d.value + e.value + 4 }   // 26

  println(f.now)                             // 26
}

Functional Reactive Programming

Ejemplo

import rx._

object Ejemplo2 extends App{
  val a = Var(1)                  
  val b = Var(2)                                //  2
  val c = Signal { a.value + b.value }          //  5
  val d = Signal { c.value * 5 }                // 25
  val e = Signal { c.value + 4 }                //  9
  val f = Signal { d.value + e.value + 4 }      // 38

  println(f.now)                  
 a.set(3)                                       //  3
  println(f.now)                                // 38
}

Functional Reactive Programming

Observers - Obs

import rescala.default.*

object ObserverInmediato extends App {
  val a = Var(1)
  var contador = 0

  // Se ejecuta AHORA y en futuros cambios
  val observer = a.observe { valor =>
    contador = valor + 1
    println(s"Evento detectado. Nuevo valor: $valor, Contador: $contador")
  }
  // Salida inmediata: "Evento detectado. Nuevo valor: 1, Contador: 2"

  a.set(4) 
  // Salida reactiva: "Evento detectado. Nuevo valor: 4, Contador: 5"
}

Los Observers permiten ejecutar efectos secundarios (como imprimir en consola, actualizar una base de datos o una UI) cada vez que una señal cambia.

Functional Reactive Programming

Observers - Obs

Si solo nos interesan las actualizaciones futuras (ignorando el estado inicial), usamos .changed

import rescala.default.*

object ObserverCambios extends App {
  val a = Var(1)
  
  // Convierte la señal en un evento de cambio
  val observer = a.changed.observe { valor =>
    println(s"La variable cambió a: $valor")
  }
  
  // No imprime nada todavía (ignora el 1 inicial)

  a.set(10)
  // Salida: "La variable cambió a: 10"
}

Functional Reactive Programming

Kill Obs

import rescala.default.*

object ControlRecursos extends App {
  val sensor = Var(10)
  val procesado = Signal { sensor.value * 2 }
  
  val monitor = procesado.observe { valor =>
    println(s"Monitor activo: $valor")
  }

  sensor.set(20) // Imprime: Monitor activo: 40

  // Desconectamos el observador
  monitor.disconnect()

  sensor.set(30) // Ya no imprime nada, aunque 'procesado' internamente valga 60
}

Para detener la ejecución de un Observer y liberar recursos, utilizamos el método .disconnect().

Functional Reactive Programming

Determinar la salida

Determine la salida del siguiente programa

import rescala.default.*

object TransformacionDatos extends App {
  val lista = Var(List(1, 2, 3))
  val multiplicador = Var(3)
  
  // 1. Agregar elemento al inicio (prepend)
  val secuenciaExpandida = Signal { multiplicador.value +: lista.value } 
  
  // 2. Transformar cada elemento (Map)
  val estrellas = Signal { 
    secuenciaExpandida.value.map(n => "★" * n) 
  }

  val sufijo = Var("FIN")

  // 3. Reducir a String
  val resultadoFinal = Signal { 
    (estrellas.value :+ sufijo.value).mkString(" | ") 
  }

  println(resultadoFinal.now)
  // Salida: ★★★ | ★ | ★★ | ★★★ | FIN

  lista.set(Nil) // Lista vacía
  println(resultadoFinal.now)
  // Salida: ★★★ | FIN
}

Trabajo de consulta

Trabajo de consulta

Detalles

  • Repositorio en GitHub 
  • Consulta sobre EDA (Exploratory Data Analysis) y estadística descriptiva

 

Proyecto Integrador o Bimestral

Proyecto Integrador o bimestral

Entrega 1

  • Repositorio en GitHub (incluir todos los integrantes + docentes)
  • Tablas de datos (nombre de columna, tipo, propósito y observaciones) - Readme.md 
  • Limpieza de datos
  • Análisis de datos en columnas numéricas (estadísticas básicas)
  • Análisis de datos en columnas tipo texto (algunas col. - distribución de frecuencia). OJO: no considerar columnas en formato JSON
  • Consultar sobre librería play-json (trabajo json en scala) y hacer:
    • Usar cualquier JSON pequeño para aprender play-json
    • Usar en algunas columnas JSON para obtener datos. 

 

Proyecto Integrador o bimestral

Comentarios entrega Nro. 1

  • Es necesario realizar limpieza de datos:
    • Cadenas vacías
  • Algunas columnas necesitan análisis cuidadoso, ejemplo:
    • Separador no definido: genres, cast (nombres)
    • Dato estructurado: release_date (fecha)

 

B2S10 Programación reactiva, segundo enfoque

By Santiago Quiñones Cuenca

B2S10 Programación reactiva, segundo enfoque

Introducción a la programación reactiva. Patrón Observer. Implementación, uso de ReactiveX.

  • 328