Introducción a Scala y configuración del entorno de desarrollo

1

Introducción al curso y presentación de los objetivos

2

Programación Funcional en Scala: Fundamentos y Beneficios

3

Instalación y configuración de herramientas para programar en Scala

4

Herramientas Esenciales para Programar en Scala

5

Hola Mundo en Scala con ScalaFiddle

Fundamentos de Programación Funcional

6

Tipos de Datos Básicos en Scala

7

Inmutabilidad en Programación Funcional con Scala

8

Expresiones en Scala: Conceptos y Ejemplos Prácticos

9

Funciones en Programación Funcional y Matemática

10

Colecciones Inmutables en Lenguajes Funcionales

11

Tuplas y objetos en programación funcional y orientada a objetos

12

Uso de `copy()` y Lentes en Programación Funcional

Conceptos básicos de Programación Funcional

13

Programación Funcional: Uso de Pattern Matching Avanzado

14

Optimización de Algoritmos con Tail Recursion

15

Agregación y acumuladores en programación funcional con Scala

Fundamentos teoricos

16

Funciones Totales y Parciales en Programación Funcional

17

Razonamiento Inductivo en Algoritmos Recursivos

18

Razonamiento con Tipos en Lenguajes Tipados y Dinámicos

19

Uso de Traits en Scala: Concepto y Ejemplos Prácticos

20

Tipos Genéricos en Programación: Uso y Ejemplos Prácticos

21

Tipos de Datos Algebraicos: Suma y Producto en Programación

22

Evaluación Perezosa en Scala: Variables y Colecciones Lazy

23

Manejo de Disyunciones Option en Programación Funcional

24

Manejo de Excepciones con Try y Either en Programación Funcional

Proyecto de Backend

25

Desarrollo de Backend con PlayFramework y Scala: Proyecto Platzi Video

26

Modelo de Actores en Scala: Akka y Erlang

27

Modelo de Datos y Configuración de Proyecto con Play Framework

28

Integración de Play con Slick y SQLite en Scala

29

Consultas Asíncronas y Futuros en Scala con Slick

30

Creación, actualización y eliminación de datos en bases de datos

31

Computación Paralela y Asíncrona en Scala: Conceptos y Aplicaciones

32

Serialización de Datos en Scala con Play Framework

33

Serialización y validación de JSON a objetos Scala

34

Manejo de Errores en Scala: Técnicas y Pruebas con Postman

35

Exportación de Aplicaciones Play con SBT Native Packager

Conclusiones

36

Conceptos Clave de la Programación Funcional en Scala

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Scala básico

Curso de Scala básico

Carlos Daniel Sanchez

Carlos Daniel Sanchez

Colecciones Inmutables en Lenguajes Funcionales

10/36
Recursos

¿Cuál es la importancia de las colecciones en lenguajes funcionales?

En el mundo de la programación funcional, las colecciones juegan un papel crucial. Comprender cómo funcionan las listas, conjuntos y mapas en estos lenguajes, como Scala, es fundamental para aprovechar al máximo sus capacidades. A diferencia de su contraparte en lenguajes tradicionales, las estructuras de datos en lenguajes funcionales son inmutables, lo que significa que no se pueden modificar una vez creadas. Esto implica que todas las operaciones devuelven nuevas instancias, manteniendo las originales sin cambios, lo cual es esencial para garantizar la integridad y seguridad del código.

¿Qué son las listas y cómo se trabajan en Scala?

Las listas en Scala son una de las principales formas de representar secuencias de datos. A diferencia de los arrays, que son mutables y están diseñados para compatibilidad, las listas en Scala son inmutables, lo que garantiza que una vez creadas, no se puedan modificar. Esto implica que al realizar operaciones, como agregar elementos, el resultado es una nueva lista sin alterar la original. Scala utiliza funciones como map, filter y foreach para iterar y manipular datos de manera funcional, evitando los bucles tradicionales como for o while.

val a1 = Seq(1, 2, 3)
val a2 = a1 :+ 4 // Crea una nueva lista agregando el 4

¿Cómo se diferencian los conjuntos y las listas?

Los conjuntos en Scala, implementados por la clase Set, se parecen a las listas, pero siguen las reglas de los conjuntos matemáticos. Permiten realizar operaciones como intersección y unión de manera nativa. Los conjuntos también son inmutables, lo que significa que las operaciones como agregar un elemento crean un nuevo conjunto.

val c1 = Set(1, 2, 3)
val c2 = c1 + 4 // Crea un nuevo conjunto incluyendo el 4

¿Qué papel juegan los mapas en Scala?

Los mapas, conocidos como diccionarios en otros lenguajes, permiten almacenar datos en pares clave-valor. En Scala, los mapas son inmutables y se definen mediante la clase Map. Al igual que las listas y conjuntos, los mapas en Scala no se modifican directamente. Las claves y los valores deben proporcionarse como pares, y cualquier operación que implique agregar elementos regresará un nuevo mapa.

val m1 = Map(1 -> "hola")
val m2 = m1 + (2 -> "hello")

¿Cómo se manipulan las colecciones usando funciones?

El manejo de colecciones en Scala se realiza mediante funciones internas y librerías. La función map permite aplicar una función a cada elemento de una colección, transformándola según sea necesario. Las funciones lambda o anónimas son comunes en estas operaciones, lo que facilita la manipulación funcional de listas, conjuntos y mapas.

val a2Incremental = a2.map(x => x + 1) // Incrementa cada valor en la lista

Reto para mejorar tus habilidades

Para fortalecer tu comprensión, te invitamos a crear un grupo de funciones que calculen la media, mediana y moda de una lista de números, y devuelvan los resultados en un mapa. Esta práctica reforzará tus conocimientos sobre la manipulación de colecciones usando funciones en Scala, un paso relevante en tu camino hacia la maestría en lenguajes funcionales. ¡Adelante y mantén la curiosidad por el aprendizaje!

Aportes 23

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Reto!

object colecciones {
  def main(args: Array[String]): Unit = {
    val lista: Seq[Int] = Seq(1,3,5,7,9,9,11,17,20,20,100)

    medidasT(lista)
  }

  //  funciones

  def media(args: Seq[Int]): Int = {
    val media = (args.sum)/(args.size)
    media
  }

  def mediana(args: Seq[Int]): Int = {
    val indice = (args.size/2)
    args(indice)
  }

  def moda(args: Seq[Int]): Int = {
    args
      .groupBy(x => x)
      .maxBy(x => x._2.size)
      ._1
  }


  // funcion de medidas de tendencia central
  def medidasT(args: Seq[Int]): Unit = {
    val lista = args.sorted
    val mapa = Map(
      "media"   -> media(lista),
      "mediana" -> mediana(lista),
      "moda"    -> moda(lista)
    )


    mapa foreach ( x => println(x._1 + " -> " + x._2) )

  }
}

En la versión actual 2.12, no se dispone de la función appended.
To append or prepend one or more elements to a Vector or Seq, use these methods:

to append one item, use :+
to append multiple items, use ++
to prepend one item, use +:
to prepend multiple items, use ++:

Solución del reto:

def media(numbers: Seq[Int]) = numbers.sum / numbers.size
def mediana(numbers: Seq[Int]) = if(numbers.size % 2 == 1) {
numbers(numbers.size/2)
} else {
val position = numbers.size / 2
(numbers(position) + numbers(position - 1))/ 2
}
def moda(numbers: Seq[Int]) = numbers.groupBy(group => group).maxBy( num => num._2.size)._1

val numbers = Seq(1, 2, 3, 5, 6, 6)

val result: ( Seq[Int] => Map[String, Int] ) = { numbers: Seq[Int] => Map(
(“Media”, media(numbers)), (“Mediana”, mediana(numbers)), (“Moda”, moda(numbers))
)}
println(result( numbers ))

cualquier feedback es bienvenido 😃

Listas

Es el tipo de dato más básico en lenguajes funcionales. A diferencia de las listas en otros lenguajes, aquí por defecto son inmutables

  • List, Seq, Array

Conjuntos

Es muy similar a usar una lista, pero conceptualmente es distinto. Por definición, los elementos en un conjunto no tienen orden, ni pudeden estar repetidos.

  • Set,

Mapas

También se les conoce como diccionarios. No es muy diferente a lo que ya conocemos, solo que también son inmutables por defecto

  • Map

Loops en FP

En programación funcional no usaremos un for o un while como se hace en lenguajes imperativos. Por el contrario, usaremos funciones que recorran los elementos de una lista por nosotros.

  • map()
  • filter()
  • filterNot()
  • forEach()
  • zip()
  • find()
val a1 = Seq(1,2,3
// a1: Seq[Int] = List(1, 2, 3)

a1.appendded

val a2 = a1.appended(4)
// a1: Seq[Int] = List(1, 2, 3, 4)

a1 :+ 4
// res18: Seq[Int] = List(1, 2, 3, 4)

a1.:+(4)
// res19: Seq[Int] = List(1, 2, 3, 4)

a1 appended 4
// res21: Seq[Int] = List(1, 2, 3, 4)

a2(0) // devuelve el valor en la posición 0
// res22: Int = 1

val c1 = Set(1,2,3)
//c1: scala.collection.immutable.Set[Int] = Set(1,2,3)

c1.incl(4)
//res: scala.collection.immutable.Set[Int] = Set(1,2,3,4)

val c2 = c1.incl(4)
//c2: scala.collection.immutable.Set[Int] = Set(1,2,3,4)

c1 + 4
//res: scala.collection.immutable.Set[Int] = Set(1,2,3,4)

c2(4)
// res29: Boolean = true

val m1 = Map(1) // error

val m1 = Map((1,"hola"))
//m1 scala.collection.immutable.Map[Int,String] = Map(1 -> hola)

val m1 = Map(1 -> "hola")
//m1 scala.collection.immutable.Map[Int,String] = Map(1 -> hola)

val m2 = m1 + (2, "hello") //error

val m2 = m1 + (2 -> "hello")
//m1 scala.collection.immutable.Map[Int,String] = Map(1 -> hola, 2 -> "hello")

c2.map(x => x+1)
//res: scala.collection.immutable.Set[Int] = Set(2,3,4,5)

a2.map(x => x+1)
// res19: Seq[Int] = List(2, 3, 4, 5)

m2.view.mapValues(s => s + "!")
//m1 scala.collection.MapView[Int,String] = MapView(<not computed>)

mi propuesta def calcularMedia(lista: List\[Double]): Double = {  if (lista.isEmpty) throw new IllegalArgumentException("La lista no puede estar vacía")  lista.sum / lista.length } def calcularModa(lista: List\[Double]): List\[Double] = {  if (lista.isEmpty) throw new IllegalArgumentException("La lista no puede estar vacía")  val frecuencias = lista.groupBy(identity).mapValues(\_.size)    maxFrecuencia = frecuencias.values.max  frecuencias.filter(\_.\_2 == maxFrecuencia).keys.toList } def calcularMediana(lista: List\[Double]): Double = {  if (lista.isEmpty) throw new IllegalArgumentException("La lista no puede estar vacía")  val ordenada = lista.sorted val n = ordenada.length if (n % 2 == 0) {  (ordenada(n / 2 - 1) + ordenada(n / 2)) / 2 } else {  ordenada(n / 2)  } } val numeros = List(1.0, 3.0, 2.0, 5.0, 4.0) val mediana = calcularMediana(numeros)println(s"La mediana de la lista es: $mediana") val media = calcularMedia(numeros)println(s"La media de la lista es: $media") val moda = calcularModa(numeros)println(s"La moda de la lista es: $moda")
Pequeño aporte de solución: `object Ejercicios{` ` def media(x: Seq[Int]): Double = {` ` x.sum.toDouble/x.size` ` }` ` def mediana(x: Seq[Int]): Double = {` ` val ordenada = x.sorted` ` val indice = ((ordenada.size.toDouble/2) - 0.5).toInt` ` if (x.size % 2 == 0) {` ` (ordenada(indice)+ordenada(indice+1)).toDouble/2` ` }` ` else {` ` ordenada(indice)` ` }` ` }` ` def moda(x: Seq[Int]): Int = {` ` x.groupBy(identity).view.map{case(valor,ocurrencias) => (valor, ocurrencias.size)}.maxBy(_._2)._1` ` }` `}` `val lista: Seq[Int] = Seq(1,120,6,6,6,8,10,100)` `val media = ("Media:",Ejercicios.media(lista))` `val mediana = ("Mediana:",Ejercicios.mediana(lista))` `val moda = ("Moda:",Ejercicios.moda(lista))` `val respuesta = Map((media),(mediana),(moda))` `print(respuesta)` Se agradece la critica constructiva :D
```js import scala.util.Random def getMean(sample: Seq[Int]): (String, Double) = if (sample.isEmpty) { ("mean" -> 0.0) } else { ("mean" -> sample.sum.toDouble / sample.length) } def getMedian(sample: Seq[Int]): (String, Double) = { val sortedSample = sample.sorted val sortedLength = sample.length if (sortedSample.isEmpty) { ("median" -> 0.0) } else if (sortedLength % 2 == 1) { ("median" -> sortedSample(sortedLength/2).toDouble) } else { val middel1 = sortedSample((sortedLength-1)/2) val middel2 = sortedSample(sortedLength/2) val median = (middel1 + middel2).toDouble / 2 ("median" -> median) } } def getMode(sample: Seq[Int]): (String, Double) = { val freqMap = sample.groupBy(identity).view.mapValues(_.size) val maxFreq = freqMap.values.max val mode = freqMap.filter { case (_, freq) => freq == maxFreq }.keys.head ("mode", mode.toDouble) } def getStatistics(sample: Seq[Int]): Map[String, Double] = Map(getMean(sample), getMedian(sample), getMode(sample)) val randomeSample = Seq.fill(100)(Random.nextInt(1000)) val statistics = getStatistics(randomeSample) println(randomeSample) println(statistics) ```

Reto !

  val numbers = List(1,3,5,7,9,9,11,17,20,20,100)

  def mediaMedianaModa(numbers:List[Int]):Unit =
    val media =Math.round(numbers.sum.toDouble / numbers.length)
      val numbersOrder = numbers.sorted
      val mediana = if (numbersOrder.length % 2 == 0) {
        val mitadSuperior = numbersOrder.length / 2
        val mitadInferior = mitadSuperior - 1
        Math.round((numbersOrder(mitadInferior).toDouble + numbersOrder(mitadSuperior).toDouble) / 2)
      } else {
        Math.round(numbersOrder(numbersOrder.length / 2).toDouble)
      }
    val frecuencias = numbers.groupBy(identity).view.mapValues(_.size)
    val maxFrecuencia = frecuencias.values.max
    val moda=frecuencias.filter(_._2 == maxFrecuencia).keys.toList

    println(s"Media:$media, Mediana:$mediana, Moda:${if(moda.size==numbers.size) "no hay moda" else if(moda.size==1)moda(0) else moda} ")

  mediaMedianaModa(numbers)
object calculo {
     |  def media(x:Seq[Int]) = { val l = x.length; val s = x.sum; val result =  s / l; result}
     |  def mediana(x:Seq[Int]) = {val l = x.length; val r = l / 2 ;val result = x(r.round); result}
     |  def getData(x:Seq[Int]) = {val result = Map("Media: " -> media(x), "Mediana: " -> mediana(x)); result}
     | }

Resultado del reto:

package demo

object Demo {
  // Main Method
  def main(args: Array[String]) {

    val nums: List[Int] = List(1, 2, 3, 2, 4, 4, 4)
    val numsOrdered = nums.sorted

    // Media
    val sumaLista = numsOrdered.sum
    val conteoLista = numsOrdered.size

    val mediana = sumaLista/conteoLista
    val media = conteoLista/2
    val moda = numsOrdered.groupBy(identity).maxBy(_._2.size)._1

    println(Map(("mediana",mediana)))
    println(Map(("moda",moda)))
    println(Map(("media",media)))

  }
}


Si queremos hacer una secuencia, lista o colección sin inicializarla pero con los tipos que contendrá definidos podemos usar la siquiente sintaxis.

val a = Seq[Int]()

En ocasiones, queremos declarar una lista vacia que contenga elementos de cierto tipo de dato.

En el siguiente ejemplo se trata de añadir un elemento a una lista vacia y falla.

Sin embargo, al utilizar la sintaxis descrita anteriormente, no tenemos ningún problema.

Este seria el equivalente a los tipos genéricos en otros lenguajes de programación donde se suele utilizar “<>”.

También puede utilizarse:

var a : Seq[Int] = Seq()

Por útlimo, en Scala3 podemos utilizar la siguiente sintaxis si quisieramos hacer una colección que contenga más de un tipo de dato.

Mi solución al reto V2:

// Utils
def getCount(list:Iterable[Int]) = {
  list.fold(0)((item,next)=> item + 1)
}
def getMiddle(list:List[Int]) = {
  val middle = getCount(list).toFloat / 2
  if (middle.isValidInt) {
    (list(middle.toInt - 1),list(middle.toInt))
  }
  else {
    list(middle.floor.toInt)
  }
}
def getFrequency(list:List[Int]) = {
 list.toList.groupMapReduce(identity)(_ => 1)(_ + _)
}

// Controllers

def getAverage(list:Iterable[Int]) = {
  list.sum / getCount(list)
}

def getMedian(list:Iterable[Int]) = {
  getMiddle(list.toList.sorted)
}
def getMode(list:Iterable[Int]) = {
 val frequencyMap = getFrequency(list.toList)
 frequencyMap.filter(item=>{
   item._2 == frequencyMap.valuesIterator.max
 })
}

val getMean = getAverage(_)

// View
def getStats(list:Iterable[Int]) = {
  Map(
	("mean",getMean(list)),
	("median",getMedian(list)),
	("mode",getMode(list))
  )
}

// Data
val data = List(100,2000,2,4151,1515,3,3)

// Rendering view
getStats(data)

Mi solución al reto:

// Utils
def getTotal(list:Iterable[Int]) = {
  list.reduce((item,next)=>item+next)
}
def getCount(list:Iterable[Int]) = {
  list.fold(0)((item,next)=>item+1)
}
def getMiddle(list:List[Int]) = {
  val middle = getCount(list).toFloat / 2
  if (middle.isValidInt) {
    (list(middle.toInt - 1),list(middle.toInt))
  }
  else {
    list(middle.floor.toInt)
  }
}
def getFrequency(list:List[Int]) = {
 list.toList.groupMapReduce(identity)(_ => 1)(_ + _)
}

// Controllers

def getAverage(list:Iterable[Int]) = {
  getTotal(list) / getCount(list)
}

def getMedian(list:Iterable[Int]) = {
  getMiddle(list.toList.sorted)
}
def getMode(list:Iterable[Int]) = {
 val frequencyMap = getFrequency(list.toList)
 frequencyMap.filter(item=>{
   item._2 == frequencyMap.valuesIterator.max
 })
}

val getMean = getAverage(_)

// View
def getStats(list:Iterable[Int]) = {
  Map(
	("mean",getMean(list)),
	("median",getMedian(list)),
	("mode",getMode(list))
  )
}

// Data
val data = List(100,2000,2,4151,1515,3,3)

// Rendering view
getStats(data)

Aqui va mi reto. Aún no me acostumbro a usar solo valores y no variables. jajajaja Esto de la inmutabilidad es dificil de adoptar jajajaj

import scala.collection.mutable
import scala.util.Random

object Measures extends App{

  val random = Random

  val input:Seq[Int]=for (i<- 1 to 13) yield random.nextInt(10)

  var lowest:mutable.PriorityQueue[Int]=mutable.PriorityQueue.empty[Int]
  var highest: mutable.PriorityQueue[Int]=mutable.PriorityQueue.empty[Int]

  var mediana:Double=0
  var moda:Seq[Int] = Seq.empty[Int]

  def media(x:Seq[Int]): Double = x.sum.toDouble/x.size

  def mediana(x:Int): Unit = {
    lowest.addOne(x)
    highest.addOne(-lowest.dequeue())

    if(highest.size>lowest.size){lowest.addOne(-highest.dequeue())}

    if(lowest.size>highest.size)mediana=lowest.head
    else mediana=(lowest.head-highest.head).toDouble/2
  }

  def calculateModa(): Seq[Int] = {

    val max:Int = input.groupBy(identity).maxBy(_._2.size)._2.size

    input.groupBy(identity).
      foreach { case (k, v) =>
        if (v.size == max) {
          moda=moda.appended(k)
        }
      }
  }

    println("Los datos ingresados son :")
    input.foreach(println(_))
    println( "La media de los datos ingresados es" + media(input))
    println("La mediana es :")
    input.foreach(mediana(_))
    println(mediana)
    if(calculateModa().isEmpty){println("No hay moda")}
    else{
      println("La moda es:")
      moda.foreach(println(_))
    }

}


La solución del reto la pueden encontrar aquí en mi GitHub: GitHub - @RianoJNicolas

scala> def promedio(lista:Seq[Int]):Unit ={
| val suma: Float= lista.sum.toFloat
| val tamanio= (lista.map(x=>1)).sum
| val promedio = suma/tamanio
| Map(“Media”-> promedio)
| println(promedio)
| }

scala> def mediana(lista:Seq[Int])={
| val tamanio= (lista.map(x=>1)).sum.toFloat
| val mitad = tamanio/2
| if (mitad%2==0){
| val mediana: Float = (lista(mitad.toInt-1)+lista(mitad.toInt))/2.toFloat
| Map(“Mediana”->mediana)}
| else Map(“Mediana”-> lista(mitad.toInt))
| }

scala> def moda(lista: Seq[Int])={
| lista.groupBy(x=>x).maxBy(x => x._2.size)
| }

Duda por que cuando haces le map a una lista por ejemplo
override def main(args: Array[String]): Unit = {
val numbers = List (1,2,3,4)
println(numbers)
val numbers2 = numbers.map(x => x+1)
println(numbers2)
}
}

en la salida me recorre el valor iniciando en 2, ósea si agrega el 5 en mi lista pero me quita el primer valor

List(1, 2, 3, 4)
List(2, 3, 4, 5)

scala> val mediana = (lista: List[Int]) => lista.sorted.lift(lista.size/2).get
mediana: List[Int] => Int = $$Lambda$1107/0x0000000801151040@9ab495b

scala> val moda = (lista: List[Int]) => lista.groupBy(identity).view.mapValues(_.size).maxBy(_._2)._1
moda: List[Int] => Int = $$Lambda$1108/0x0000000801151840@25bcbc72

scala> val media = (lista: List[Int]) => lista.sum / lista.size
media: List[Int] => Int = $$Lambda$1109/0x0000000801152840@1a1e5b4b

scala> val entrada = List(1, 5, 3, 7, 7, 8, 8, 9, 10, 1, 3, 5, 1, 1)
entrada: List[Int] = List(1, 5, 3, 7, 7, 8, 8, 9, 10, 1, 3, 5, 1, 1)

scala> Map("mediana" -> mediana(entrada), "moda" -> moda(entrada), "media" -> media(entrada))
res57: scala.collection.immutable.Map[String,Int] = Map(mediana -> 5, moda -> 1, media -> 4)```

Les comparto el código del ejercicio

object stats {
// Para la media o promedio
def media(l: Seq[Int]) : Double = l.sum.toDouble / l.size.toDouble
// Para la mediana
def mediana(l: Seq[Int]) : Double = {
if(l.size % 2 == 1) l(l.size/2) else (l(l.size / 2) + l((l.size / 2) - 1))/ 2
}
// Para la moda
def moda(l: Seq[Int]) : Double = l.groupBy(group => group).maxBy( num => num._2.size)._1
// Resultado
def resultado(l: Seq[Int]) : Map[String, Double] = {
Map((“Media”, media(l)),(“Medina”, mediana(l)),(“Moda”,moda(l)))
}
}
// Resultados
val lista = Seq(1, 6, 6, 5, 2, 3).sorted
stats.resultado(lista)

MEDIA

  1. Suma de los Elementos / Nº de Elementos

MEDIANA

  1. Orden de datos
  2. Verificar si el subset es par o impar
    2.1 Si es par, suma de la posicion de la mitad (entera) y la posicion anterior (-1) entre 2
    2.2 Si es impar, posicion de la mitad (entera)

MODA

  1. Agrupacion por numeros
  2. Conteo de cada numero
  3. Elegir el mayor de todos
// Code
scala> object reto {
     |   def media(lista: Seq[Int]): Double = {
     |           lista.sum.toDouble / lista.size.toDouble;
     |   }
     |   def mediana(lista: Seq[Int]): Double = {
     |           val ltOr = lista.sorted;
     |           if(ltOr.size%2 == 1){
     |                   ltOr(ltOr.size/2);
     |           }
     |           else{
     |                   ( ltOr(ltOr.size/2) + ltOr(ltOr.size/2 - 1) )/2
     |           }
     |   }
     |   def moda(lista: Seq[Int]): Double = {
     |           lista.groupBy(
     |					group => group
     |			 ).maxBy(
     |					num => num._2.size
     |			 )._1
     |   }
     |   def resultadoMap(lista: Seq[Int]): Map[String,Double] = {
     |           Map(
     |                   "Media" -> media(lista)
     |                   ,"Mediana" -> mediana(lista)
     |                   ,"Moda" -> moda(lista)
     |           );
     |   }
     | }
defined object reto

scala> val lista = Seq(1,2,4,4)
lista: Seq[Int] = List(1, 2, 4, 4)

scala> reto.resultadoMap(lista)
res2: Map[String,Double] = Map(Media -> 2.75, Mediana -> 3.0, Moda -> 4.0)

scala> conj.incl(12) <console>:26: error: value incl is not a member of scala.collection.immutable.Set[Int] conj.incl(12)

para agregar valores solo se usa el operador/método +
el valor es agregado en cualquier orden

Espero lograr el reto!

// Data Test Case
val nums = List(1,2,3,4,3,3)

// Functions for Average, Median and Mode
def average(nums: List[Int]) = {
val sum = nums.reduce( (x,y) => x+y)
sum / nums.size
}

def median(nums: List[Int] ) = {
val sorted = nums.sorted
sorted({sorted.size / 2} - 1) // 0 index based
}
def mode(nums: List[Int]) = {
nums.maxBy( x => nums.count(_ == x))
}
// Result in Map Format
val myMap = Map( “Avergae” -> average(nums), “Median” -> median(nums), “Mode” -> mode(nums2))
//val myMap: scala.collection.immutable.Map[String,Int] = Map(Avergae -> 2, Median -> 3, Mode -> 3)