diff options
Diffstat (limited to 'es-es')
| -rw-r--r-- | es-es/go-es.html.markdown | 618 | ||||
| -rw-r--r-- | es-es/javascript-es.html.markdown | 9 | ||||
| -rw-r--r-- | es-es/julia-es.html.markdown | 1268 | ||||
| -rw-r--r-- | es-es/python-es.html.markdown | 120 | 
4 files changed, 1196 insertions, 819 deletions
| diff --git a/es-es/go-es.html.markdown b/es-es/go-es.html.markdown index 86de33ec..c41d693d 100644 --- a/es-es/go-es.html.markdown +++ b/es-es/go-es.html.markdown @@ -1,326 +1,450 @@  --- +name: Go +category: language  language: Go  lang: es-es  filename: learngo-es.go  contributors:      - ["Sonia Keys", "https://github.com/soniakeys"] +    - ["Christopher Bess", "https://github.com/cbess"] +    - ["Jesse Johnson", "https://github.com/holocronweaver"] +    - ["Quint Guvernator", "https://github.com/qguv"] +    - ["Jose Donizetti", "https://github.com/josedonizetti"] +    - ["Alexej Friesen", "https://github.com/heyalexej"]  translators:      - ["Adrian Espinosa", "http://www.adrianespinosa.com"]      - ["Jesse Johnson", "https://github.com/holocronweaver"] +    - ["Nacho Pacheco -- Feb/2015", "https://github.com/gitnacho"]  --- -Go fue creado por la necesidad de hacer el trabajo rápidamente.  No es -la última tendencia en informática, pero es la forma nueva y más -rápida de resolver problemas reales. +Go fue creado por la necesidad de hacer el trabajo rápidamente. No es la +última tendencia en informática, pero es la forma nueva y más rápida de +resolver problemas reales. -Tiene conceptos familiares de lenguajes imperativos con tipado -estático.  Es rápido compilando y rápido al ejecutar, añade una -concurrencia fácil de entender para las CPUs de varios núcleos de hoy -en día, y tiene características que ayudan con la programación a gran -escala. +Tiene conceptos familiares de lenguajes imperativos con tipado estático. +Es rápido compilando y rápido al ejecutar, añade una concurrencia fácil de +entender para las CPUs de varios núcleos de hoy día, y tiene +características que ayudan con la programación a gran escala. -Go viene con una librería estándar muy buena y una comunidad entusiasta. +Go viene con una biblioteca estándar muy buena y una entusiasta comunidad.  ```go  // Comentario de una sola línea -/* Comentario  -   multi línea */ +/* Comentario +   multilínea */ -// La cláusula package aparece al comienzo de cada archivo fuente. -// Main es un nombre especial que declara un ejecutable en vez de una librería. +// La cláusula `package` aparece al comienzo de cada fichero fuente. +// `main` es un nombre especial que declara un ejecutable en vez de una +// biblioteca.  package main -// La declaración Import declara los paquetes de librerías -// referenciados en este archivo. +// La instrucción `import` declara los paquetes de bibliotecas referidos +// en este fichero.  import ( -    "fmt"      // Un paquete en la librería estándar de Go. -    "net/http" // Sí, un servidor web! -    "strconv"  // Conversiones de cadenas. -    m "math"   // Librería matemáticas con alias local m. +	"fmt"      // Un paquete en la biblioteca estándar de Go. +	"io/ioutil" // Implementa algunas útiles funciones de E/S. +	m "math"   // Biblioteca de matemáticas con alias local m. +	"net/http" // Sí, ¡un servidor web! +	"strconv"  // Conversiones de cadenas.  ) -// Definición de una función. Main es especial.  Es el punto de -// entrada para el ejecutable.  Te guste o no, Go utiliza llaves. +// Definición de una función. `main` es especial. Es el punto de entrada +// para el ejecutable. Te guste o no, Go utiliza llaves.  func main() { -    // Println imprime una línea a stdout. -    // Cualificalo con el nombre del paquete, fmt. -    fmt.Println("Hello world!") +	// Println imprime una línea a stdout. +	// Cualificalo con el nombre del paquete, fmt. +	fmt.Println("¡Hola mundo!") -    // Llama a otra función de este paquete. -    beyondHello() +	// Llama a otra función de este paquete. +	másAlláDelHola()  }  // Las funciones llevan parámetros entre paréntesis.  // Si no hay parámetros, los paréntesis siguen siendo obligatorios. -func beyondHello() { -    var x int // Declaración de una variable. -              // Las variables se deben declarar antes de utilizarlas. -    x = 3     // Asignación de variables. -    // Declaración "corta" con := para inferir el tipo, declarar y asignar. -    y := 4 -    sum, prod := learnMultiple(x, y)        // Función devuelve dos valores. -    fmt.Println("sum:", sum, "prod:", prod) // Simple salida. -    learnTypes()                            // < y minutes, learn more! +func másAlláDelHola() { +	var x int // Declaración de una variable. + 	          // Las variables se deben declarar antes de utilizarlas. +	x = 3     // Asignación de variable. +	// Declaración "corta" con := para inferir el tipo, declarar y asignar. +	y := 4 +	suma, producto := aprendeMúltiple(x, y) // La función devuelve dos +											// valores. +	fmt.Println("suma:", suma, "producto:", producto) // Simple salida. +	aprendeTipos()                        // < y minutos, ¡aprende más!  } -// Las funciones pueden tener parámetros y (múltiples!) valores de retorno. -func learnMultiple(x, y int) (sum, prod int) { -    return x + y, x * y // Devolver dos valores. +// Las funciones pueden tener parámetros y (¡múltiples!) valores de +// retorno. +func aprendeMúltiple(x, y int) (suma, producto int) { +    return x + y, x * y // Devuelve dos valores.  }  // Algunos tipos incorporados y literales. -func learnTypes() { -    // La declaración corta suele darte lo que quieres. -    s := "Learn Go!" // tipo cadena - -    s2 := ` Un tipo cadena "puro" puede incluir +func aprendeTipos() { +	// La declaración corta suele darte lo que quieres. +	s := "¡Aprende Go!" // tipo cadena. +	s2 := `Un tipo cadena "puro" puede incluir  saltos de línea.` // mismo tipo cadena -    // Literal no ASCII. Los fuentes de Go son UTF-8. -    g := 'Σ' // Tipo rune, un alias de int32, alberga un punto unicode. -    f := 3.14195 // float64, el estándar IEEE-754 de coma flotante 64-bit. -    c := 3 + 4i  // complex128, representado internamente por dos float64. -    // Sintaxis Var con inicializadores. -    var u uint = 7 // Sin signo, pero la implementación depende del -                   // tamaño como en int. -    var pi float32 = 22. / 7 - -    // Sintáxis de conversión con una declaración corta. -    n := byte('\n') // byte es un alias de uint8. - -    // Los Arrays tienen un tamaño fijo a la hora de compilar. -    var a4 [4]int           // Un array de 4 ints, inicializados a 0. -    a3 := [...]int{3, 1, 5} // Un array de 3 ints, inicializados como se indica. - -    // Los Slices tienen tamaño dinámico. Los arrays y slices tienen sus ventajas -    // y desventajas pero los casos de uso para los slices son más comunes. -    s3 := []int{4, 5, 9}    // Comparar con a3. No hay puntos suspensivos. -    s4 := make([]int, 4)    // Asigna slices de 4 ints, inicializados a 0. -    var d2 [][]float64      // Solo declaración, sin asignación. -    bs := []byte("a slice") // Sintaxis de conversión de tipo. - -    p, q := learnMemory() // Declara p, q para ser un tipo puntero a int. -    fmt.Println(*p, *q)   // * sigue un puntero. Esto imprime dos ints. - -    // Los Maps son arrays asociativos dinámicos, como los hash o -    // diccionarios de otros lenguajes. -    m := map[string]int{"three": 3, "four": 4} -    m["one"] = 1 - -    // Las variables no utilizadas en Go producen error. -    // El guión bajo permite "utilizar" una variable, pero descartar su valor. -    _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs -    // Esto cuenta como utilización de variables. -    fmt.Println(s, c, a4, s3, d2, m) - -    learnFlowControl() // Vuelta al flujo. +	// Literal no ASCII. Los ficheros fuente de Go son UTF-8. +	g := 'Σ' // Tipo rune, un alias de int32, alberga un carácter unicode. +	f := 3.14195 // float64, el estándar IEEE-754 de coma flotante 64-bit. +	c := 3 + 4i  // complex128, representado internamente por dos float64. +	// Sintaxis Var con iniciadores. +	var u uint = 7 // Sin signo, pero la implementación depende del tamaño +	               // como en int. +	var pi float32 = 22. / 7 + +	// Sintáxis de conversión con una declaración corta. +	n := byte('\n') // byte es un alias para uint8. + +	// Los Arreglos tienen un tamaño fijo a la hora de compilar. +	var a4 [4]int           // Un arreglo de 4 ints, iniciados a 0. +	a3 := [...]int{3, 1, 5} // Un arreglo iniciado con un tamaño fijo de tres +							// elementos, con valores 3, 1 y 5. +	// Los Sectores tienen tamaño dinámico. Los arreglos y sectores tienen +	// sus ventajas y desventajas pero los casos de uso para los sectores +	// son más comunes. +	s3 := []int{4, 5, 9}     // Comparar con a3. No hay puntos suspensivos. +	s4 := make([]int, 4)     // Asigna sectores de 4 ints, iniciados a 0. +	var d2 [][]float64       // Solo declaración, sin asignación. +	bs := []byte("a sector") // Sintaxis de conversión de tipo. +	// Debido a que son dinámicos, los sectores pueden crecer bajo demanda. +	// Para añadir elementos a un sector, se utiliza la función incorporada +	// append(). +	// El primer argumento es el sector al que se está anexando. Comúnmente, +	// la variable del arreglo se actualiza en su lugar, como en el  +	// siguiente ejemplo. +	sec := []int{1, 2 , 3}      // El resultado es un sector de longitud 3. +	sec = append(sec, 4, 5, 6)  // Añade 3 elementos. El sector ahora tiene una +								// longitud de 6. +	fmt.Println(sec) // El sector actualizado ahora es [1 2 3 4 5 6] +	// Para anexar otro sector, en lugar de la lista de elementos atómicos +	// podemos pasar una referencia a un sector o un sector literal como +	// este, con elipsis al final, lo que significa tomar un sector y +	// desempacar sus elementos, añadiéndolos al sector sec. +	sec = append(sec, []int{7, 8, 9} ...) // El segundo argumento es un +										  // sector literal. +	fmt.Println(sec)  // El sector actualizado ahora es [1 2 3 4 5 6 7 8 9] +	p, q := aprendeMemoria() // Declara p, q para ser un tipo puntero a +							 // int. +	fmt.Println(*p, *q)      // * sigue un puntero. Esto imprime dos ints. + +	// Los Mapas son arreglos asociativos dinámicos, como los hash o +	// diccionarios de otros lenguajes. +	m := map[string]int{"tres": 3, "cuatro": 4} +	m["uno"] = 1 + +	// Las variables no utilizadas en Go producen error. +	// El guión bajo permite "utilizar" una variable, pero descartar su +	// valor. +	_, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs +	// Esto cuenta como utilización de variables. +	fmt.Println(s, c, a4, s3, d2, m) + +	aprendeControlDeFlujo() // Vuelta al flujo. +} + +// Es posible, a diferencia de muchos otros lenguajes tener valores de +// retorno con nombre en las funciones. +// Asignar un nombre al tipo que se devuelve en la línea de declaración de +// la función nos permite volver fácilmente desde múltiples puntos en una +// función, así como sólo utilizar la palabra clave `return`, sin nada +// más. +func aprendeRetornosNombrados(x, y int) (z int) { +	z = x * y +	return // aquí z es implícito, porque lo nombramos antes.  } -// Go posee recolector de basura. Tiene puntero pero no aritmética de -// punteros.  Puedes cometer un errores con un puntero nil, pero no +// Go posee recolector de basura. Tiene punteros pero no aritmética de +// punteros. Puedes cometer errores con un puntero nil, pero no  // incrementando un puntero. -func learnMemory() (p, q *int) { -    // q y p tienen un tipo puntero a int. -    p = new(int) // Función incorporada que asigna memoria. -    // La asignación de int se inicializa a 0, p ya no es nil. -    s := make([]int, 20) // Asigna 20 ints a un solo bloque de memoria. -    s[3] = 7             // Asignar uno de ellos. -    r := -2              // Declarar otra variable local. -    return &s[3], &r     // & toma la dirección de un objeto. +func aprendeMemoria() (p, q *int) { +	// Los valores de retorno nombrados q y p tienen un tipo puntero +	// a int. +	p = new(int) // Función incorporada que reserva memoria. +	// La asignación de int se inicia a 0, p ya no es nil. +	s := make([]int, 20) // Reserva 20 ints en un solo bloque de memoria. +	s[3] = 7             // Asigna uno de ellos. +	r := -2              // Declara otra variable local. +	return &s[3], &r     // & toma la dirección de un objeto.  } -func expensiveComputation() float64 { -    return m.Exp(10) +func cálculoCaro() float64 { +	return m.Exp(10)  } -func learnFlowControl() { -    // La declaración If requiere llaves, pero no paréntesis. -    if true { -        fmt.Println("told ya") -    } -    // El formato está estandarizado por el comando "go fmt." -    if false { -        // Pout. -    } else { -        // Gloat. -    } -    // Utiliza switch preferiblemente para if encadenados. -    x := 42.0 -    switch x { -    case 0: -    case 1: -    case 42: -        // Los cases no se mezclan, no requieren de "break". -    case 43: -        // No llega. +func aprendeControlDeFlujo() { +	// La declaración If requiere llaves, pero no paréntesis. +	if true { +		fmt.Println("ya relatado") +	} +	// El formato está estandarizado por la orden "go fmt." +	if false { +		// Abadejo. +	} else { +		// Relamido. +	} +	// Utiliza switch preferentemente para if encadenados. +	x := 42.0 +	switch x { +	case 0: +	case 1: +	case 42: +		// Los cases no se mezclan, no requieren de "break". +	case 43: +		// No llega. +	} +	// Como if, for no utiliza paréntesis tampoco. +	// Variables declaradas en for e if son locales a su ámbito. +	for x := 0; x < 3; x++ { // ++ es una instrucción. +		fmt.Println("iteración", x) +	} +	// aquí x == 42. + +	// For es la única instrucción de bucle en Go, pero tiene formas +	// alternativas. +	for { // Bucle infinito. +		break    // ¡Solo bromeaba! +		continue // No llega. +	} + +	// Puedes usar `range` para iterar en un arreglo, un sector, una +	// cadena, un mapa o un canal. +	// `range` devuelve o bien, un canal o de uno a dos valores (arreglo, +	// sector, cadena y mapa). +	for clave, valor := range map[string]int{"uno": 1, "dos": 2, "tres": 3} { +		// por cada par en el mapa, imprime la clave y el valor +		fmt.Printf("clave=%s, valor=%d\n", clave, valor) +	} + +	// Como en for, := en una instrucción if significa declarar y asignar +	// primero, luego comprobar y > x. +	if y := cálculoCaro(); y > x { +		x = y      } -    // Como if, for no utiliza paréntesis tampoco. -    // Variables declaradas en for y if son locales de su ámbito local. -    for x := 0; x < 3; x++ { // ++ es una sentencia. -        fmt.Println("iteration", x) -    } -    // x == 42 aqui. +	// Las funciones literales son "cierres". +	granX := func() bool { +		return x > 100 // Referencia a x declarada encima de la instrucción +							// switch. +	} +	fmt.Println("granX:", granX()) // cierto (la última vez asignamos +											 // 1e6 a x). +	x /= 1.3e3                   // Esto hace a x == 1300 +	fmt.Println("granX:", granX()) // Ahora es falso. + +	// Es más las funciones literales se pueden definir y llamar en línea, +	// actuando como un argumento para la función, siempre y cuando: +	// a) la función literal sea llamada inmediatamente (), +	// b) el tipo del resultado sea del tipo esperado del argumento +	fmt.Println("Suma dos números + doble: ", +		func(a, b int) int { +			return (a + b) * 2 +		}(10, 2)) // Llamada con argumentos 10 y 2 +	// => Suma dos números + doble: 24 + +	// Cuando lo necesites, te encantará. +	goto encanto +encanto: + +	aprendeFunciónFábrica() // func devolviendo func es divertido(3)(3) +	aprendeADiferir()       // Un rápido desvío a una importante palabra clave. +	aprendeInterfaces()     // ¡Buen material dentro de poco! +} -    // For es la única sentencia de bucle en Go, pero tiene formas alternativas. -    for { // Bucle infinito. -        break    // Solo bromeaba! -        continue // No llega. -    } -    // Como en for, := en una sentencia if significa declarar y asignar primero, -    // luego comprobar y > x. -    if y := expensiveComputation(); y > x { -        x = y -    } -    // Los literales de funciones son "closures". -    xBig := func() bool { -        return x > 100 // Referencia a x declarada encima de la sentencia switch. -    } -    fmt.Println("xBig:", xBig()) // verdadero (la última vez asignamos 1e6 a x). -    x /= m.Exp(9)                // Esto lo hace x == e. -    fmt.Println("xBig:", xBig()) // Ahora es falso. +func aprendeFunciónFábrica() { +	// Las dos siguientes son equivalentes, la segunda es más práctica +	fmt.Println(instrucciónFábrica("día")("Un bello", "de verano")) + +	d := instrucciónFábrica("atardecer") +	fmt.Println(d("Un hermoso", "de verano")) +	fmt.Println(d("Un maravilloso", "de verano")) +} -    // Cuando lo necesites, te encantará. -    goto love -love: +// Los decoradores son comunes en otros lenguajes. Lo mismo se puede hacer +// en Go con funciónes literales que aceptan argumentos. +func instrucciónFábrica(micadena string) func(antes, después string) string { +	return func(antes, después string) string { +		return fmt.Sprintf("¡%s %s %s!", antes, micadena, después) // nueva cadena +	} +} -    learnInterfaces() // Buen material dentro de poco! +func aprendeADiferir() (ok bool) { +	// las instrucciones diferidas se ejecutan justo antes de que la +	// función regrese. +	defer fmt.Println("las instrucciones diferidas se ejecutan en orden inverso (PEPS).") +	defer fmt.Println("\nEsta línea se imprime primero debido a que") +	// Defer se usa comunmente para cerrar un fichero, por lo que la +	// función que cierra el fichero se mantiene cerca de la función que lo +	// abrió. +	return true  }  // Define Stringer como un tipo interfaz con un método, String.  type Stringer interface { -    String() string +	String() string  } -// Define pair como un struct con dos campos int, x e y. -type pair struct { -    x, y int +// Define par como una estructura con dos campos int, x e y. +type par struct { +	x, y int  } -// Define un método del tipo pair. Pair ahora implementa Stringer. -func (p pair) String() string { // p se llama "recibidor" -    // Sprintf es otra función pública del paquete fmt. -    // La sintaxis con punto referencia campos de p. -    return fmt.Sprintf("(%d, %d)", p.x, p.y) +// Define un método en el tipo par. Par ahora implementa a Stringer. +func (p par) String() string { // p se conoce como el "receptor" +	// Sprintf es otra función pública del paquete fmt. +	// La sintaxis con punto se refiere a los campos de p. +	return fmt.Sprintf("(%d, %d)", p.x, p.y)  } -func learnInterfaces() { -    // La sintaxis de llaves es un "literal struct". Evalúa a un struct -    // inicializado.  La sintaxis := declara e inicializa p a este struct. -    p := pair{3, 4} -    fmt.Println(p.String()) // Llamar al método String de p, de tipo pair. -    var i Stringer          // Declarar i como interfaz tipo Stringer. -    i = p                   // Válido porque pair implementa Stringer. -    // Llamar al metodo String de i, de tipo Stringer. Misma salida que arriba. -    fmt.Println(i.String()) - -    // Las funciones en el paquete fmt llaman al método String para -    // preguntar a un objeto por una versión imprimible de si mismo. -    fmt.Println(p) // Salida igual que arriba. Println llama al método String. -    fmt.Println(i) // Salida igual que arriba. - -    learnVariadicParams("great", "learning", "here!") +func aprendeInterfaces() { +	// La sintaxis de llaves es una "estructura literal". Evalúa a una +	// estructura iniciada. La sintaxis := declara e inicia p a esta +	// estructura. +	p := par{3, 4} +	fmt.Println(p.String()) // Llama al método String de p, de tipo par. +	var i Stringer          // Declara i como interfaz de tipo Stringer. +	i = p                   // Válido porque par implementa Stringer. +	// Llama al metodo String de i, de tipo Stringer. Misma salida que +	// arriba. +	fmt.Println(i.String()) + +	// Las funciones en el paquete fmt llaman al método String para +	// consultar un objeto por una representación imprimible de si +	// mismo. +	fmt.Println(p) // Salida igual que arriba. Println llama al método +				   // String. +	fmt.Println(i) // Salida igual que arriba. +	aprendeNúmeroVariableDeParámetros("¡gran", "aprendizaje", "aquí!")  }  // Las funciones pueden tener número variable de argumentos. -func learnVariadicParams(myStrings ...interface{}) { -    // Iterar cada valor de la variadic. -    for _, param := range myStrings { -        fmt.Println("param:", param) -    } -     -    // Pasar valor variadic como parámetro variadic. -    fmt.Println("params:", fmt.Sprintln(myStrings...)) - -    learnErrorHandling() +func aprendeNúmeroVariableDeParámetros(misCadenas ...interface{}) { +	// Itera en cada valor de los argumentos variables. +	// El espacio en blanco aquí omite el índice del argumento arreglo. +	for _, parámetro := range misCadenas { +		fmt.Println("parámetro:", parámetro) +	} + +	// Pasa el valor de múltiples variables como parámetro variadic. +	fmt.Println("parámetros:", fmt.Sprintln(misCadenas...)) +	aprendeManejoDeError()  } -func learnErrorHandling() { -    // ", ok" forma utilizada para saber si algo funcionó o no. -    m := map[int]string{3: "three", 4: "four"} -    if x, ok := m[1]; !ok { // ok será falso porque 1 no está en el map. -        fmt.Println("no one there") -    } else { -        fmt.Print(x) // x sería el valor, si estuviera en el map. -    } -    // Un valor de error comunica más información sobre el problema aparte de "ok". -    if _, err := strconv.Atoi("non-int"); err != nil { // _ descarta el valor -        // Imprime "strconv.ParseInt: parsing "non-int": invalid syntax". -        fmt.Println(err) -    } -    // Revisarmeos las interfaces más tarde. Mientras tanto, -    learnConcurrency() +func aprendeManejoDeError() { +	// ", ok" forma utilizada para saber si algo funcionó o no. +	m := map[int]string{3: "tres", 4: "cuatro"} +	if x, ok := m[1]; !ok { // ok será falso porque 1 no está en el mapa. +		fmt.Println("nada allí") +	} else { +		fmt.Print(x) // x sería el valor, si estuviera en el mapa. +	} +	// Un valor de error comunica más información sobre el problema aparte +	// de "ok". +	if _, err := strconv.Atoi("no-int"); err != nil { // _ descarta el +																	  // valor +		// Imprime "strconv.ParseInt: parsing "no-int": invalid syntax". +		fmt.Println(err) +	} +	// Revisaremos las interfaces más adelante. Mientras tanto... +	aprendeConcurrencia()  } -// c es un canal,  un objeto de comunicación de concurrencia segura. +// c es un canal, un objeto de comunicación concurrente seguro.  func inc(i int, c chan int) { -    c <- i + 1 // <- es el operador "enviar" cuando un canal aparece a la izquierda. +	c <- i + 1 // <- es el operador "enviar" cuando aparece un canal a la +				  // izquierda.  }  // Utilizaremos inc para incrementar algunos números concurrentemente. -func learnConcurrency() { -    // Misma función make utilizada antes para crear un slice. Make asigna e -    // inicializa slices, maps, y channels. -    c := make(chan int) -    // Iniciar tres goroutines concurrentes. Los números serán incrementados -    // concurrentemente, quizás en paralelo si la máquina es capaz y -    // está correctamente configurada. Las tres envían al mismo channel. -    go inc(0, c) // go es una sentencia que inicia una nueva goroutine. -    go inc(10, c) -    go inc(-805, c) -    // Leer los tres resultados del channel e imprimirlos. -    // No se puede saber en que orden llegarán los resultados! -    fmt.Println(<-c, <-c, <-c) // Channel a la derecha, <- es el operador "recibir". - -    cs := make(chan string)       // Otro channel, este gestiona cadenas. -    ccs := make(chan chan string) // Un channel de cadenas de channels. -    go func() { c <- 84 }()       // Iniciar una nueva goroutine solo para -                                  // enviar un valor. -    go func() { cs <- "wordy" }() // Otra vez, para cs en esta ocasión. -    // Select tiene una sintáxis parecida a la sentencia switch pero -    // cada caso involucra una operacion de channels. Selecciona un caso -    // de forma aleatoria de los casos que están listos para comunicarse. -    select { -    case i := <-c: // El valor recibido puede ser asignado a una variable, -        fmt.Printf("it's a %T", i) -    case <-cs:     // o el valor puede ser descartado. -        fmt.Println("it's a string") -    case <-ccs:    // Channel vacío, no está listo para la comunicación. -        fmt.Println("didn't happen.") -    } - -    // En este punto un valor fue devuelvto de c o cs. Uno de las dos -    // goroutines que se iniciaron se ha completado, la otrá permancerá -    // bloqueada. - -    learnWebProgramming() // Go lo hace. Tu también quieres hacerlo. +func aprendeConcurrencia() { +	// Misma función make utilizada antes para crear un sector. Make asigna +	// e inicia sectores, mapas y canales. +	c := make(chan int) +	// Inicia tres rutinasgo concurrentes. Los números serán incrementados +	// concurrentemente, quizás en paralelo si la máquina es capaz y está +	// correctamente configurada. Las tres envían al mismo canal. +	go inc(0, c) // go es una instrucción que inicia una nueva rutinago. +	go inc(10, c) +	go inc(-805, c) +	// Lee los tres resultados del canal y los imprime. +	// ¡No se puede saber en que orden llegarán los resultados! +	fmt.Println(<-c, <-c, <-c) // Canal a la derecha, <- es el operador +										// "recibe". + +	cs := make(chan string)       // Otro canal, este gestiona cadenas. +	ccs := make(chan chan string) // Un canal de canales cadena. +	go func() { c <- 84 }()       // Inicia una nueva rutinago solo para +											// enviar un valor. +	go func() { cs <- "verboso" }() // Otra vez, para cs en esta ocasión. +	// Select tiene una sintáxis parecida a la instrucción switch pero cada +	// caso involucra una operacion con un canal. Selecciona un caso de +	// forma aleatoria de los casos que están listos para comunicarse. +	select { +	case i := <-c: // El valor recibido se puede asignar a una variable, +		fmt.Printf("es un %T", i) +	case <-cs:     // o el valor se puede descartar. +		fmt.Println("es una cadena") +	case <-ccs:    // Canal vacío, no está listo para la comunicación. +		fmt.Println("no sucedió.") +	} + +	// En este punto un valor fue devuelto de c o cs. Una de las dos +	// rutinasgo que se iniciaron se ha completado, la otrá permancerá +	// bloqueada. + +	aprendeProgramaciónWeb() // Go lo hace. Tú también quieres hacerlo.  }  // Una simple función del paquete http inicia un servidor web. -func learnWebProgramming() { -    // El primer parámetro de la direccinón TCP a la que escuchar. -    // El segundo parámetro es una interfaz, concretamente http.Handler. -    err := http.ListenAndServe(":8080", pair{}) -    fmt.Println(err) // no ignorar errores +func aprendeProgramaciónWeb() { +// El primer parámetro es la direccinón TCP a la que escuchar. +	// El segundo parámetro es una interfaz, concretamente http.Handler. +	go func() { +		err := http.ListenAndServe(":8080", par{}) +		fmt.Println(err) // no ignora errores +	}() +	consultaAlServidor()  } -// Haz pair un http.Handler implementando su único método, ServeHTTP. -func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { -    // Servir datos con un método de http.ResponseWriter. -    w.Write([]byte("You learned Go in Y minutes!")) +// Hace un http.Handler de par implementando su único método, ServeHTTP. +func (p par) ServeHTTP(w http.ResponseWriter, r *http.Request) { +	// Sirve datos con un método de http.ResponseWriter. +	w.Write([]byte("¡Aprendiste Go en Y minutos!")) +} + +func consultaAlServidor() { +	resp, err := http.Get("http://localhost:8080") +	fmt.Println(err) +	defer resp.Body.Close() +	cuerpo, err := ioutil.ReadAll(resp.Body) +	fmt.Printf("\nEl servidor web dijo: `%s`\n", string(cuerpo))  }  ``` -## Para leer más  +## Más información + +La raíz de todas las cosas sobre Go es el +[sitio web oficial de Go](http://golang.org/). +Allí puedes seguir el tutorial, jugar interactivamente y leer mucho más. -La raíz de todas las cosas de Go es la [web oficial de Go](http://golang.org/). -Ahí puedes seguir el tutorial, jugar interactivamente y leer mucho. +La definición del lenguaje es altamente recomendada.  Es fácil de leer y +sorprendentemente corta (como la definición del lenguaje Go en estos +días). -La propia definición del lenguaje también está altamente -recomendada. Es fácil de leer e increíblemente corta (como otras -definiciones de lenguajes hoy en día) +Puedes jugar con el código en el +[parque de diversiones Go](https://play.golang.org/p/ncRC2Zevag).  ¡Trata +de cambiarlo y ejecutarlo desde tu navegador!  Ten en cuenta que puedes +utilizar [https://play.golang.org]( https://play.golang.org) como un +[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) para probar +cosas y el código en el navegador, sin ni siquiera instalar Go. -En la lista de lectura de estudiantes de Go está el código fuente de -la librería estándar. Muy bien documentada, demuestra lo mejor de Go -leíble, comprendible, estilo Go y formas Go. Pincha en el nombre de -una función en la documentación y te aparecerá el código fuente! +En la lista de lecturas para estudiantes de Go está el +[código fuente de la biblioteca estándar](http://golang.org/src/pkg/).  +Ampliamente documentado, que demuestra lo mejor del legible y comprensible +Go, con su característico estilo y modismos.  ¡O puedes hacer clic en un +nombre de función en [la documentación](http://golang.org/pkg/) y +aparecerá el código fuente! +Otro gran recurso para aprender Go está en +[Go con ejemplos](http://goconejemplos.com/). diff --git a/es-es/javascript-es.html.markdown b/es-es/javascript-es.html.markdown index a1348508..fd01e7b9 100644 --- a/es-es/javascript-es.html.markdown +++ b/es-es/javascript-es.html.markdown @@ -16,8 +16,7 @@ con Java para aplicaciones más complejas. Debido a su integracion estrecha con  web y soporte por defecto de los navegadores modernos se ha vuelto mucho más común   para front-end que Java. -JavaScript no sólo se limita a los navegadores web: -* Node.js: Un proyecto que provee con un ambiente para el motor V8 de Google Chrome. +JavaScript no sólo se limita a los navegadores web, aunque: Node.js, Un proyecto que proporciona un entorno de ejecución independiente para el motor V8 de Google Chrome, se está volviendo más y más popular.  ¡La retroalimentación es bienvenida! Puedes encontrarme en:   [@adambrenecki](https://twitter.com/adambrenecki), o @@ -49,6 +48,7 @@ hazAlgo()  // Toda la aritmética básica funciona como uno esperaría.  1 + 1; // = 2 +0.1 + 0.2; // = 0.30000000000000004  8 - 1; // = 7  10 * 2; // = 20  35 / 5; // = 7 @@ -102,9 +102,11 @@ false;  // Los tipos no importan con el operador ==...  "5" == 5; // = true +null == undefined; // = true  // ...a menos que uses ===  "5" === 5; // = false +null === undefined; // false  // Los Strings funcionan como arreglos de caracteres  // Puedes accesar a cada caracter con la función charAt() @@ -126,7 +128,7 @@ undefined; // usado para indicar que un valor no está presente actualmente  // Aunque 0 === "0" sí es false.  /////////////////////////////////// -// 2. Variables, Arreglos y Objetos +// 2. Variables, Arrays y Objetos  // Las variables se declaran con la palabra var. JavaScript cuenta con tipado dinámico,  // así que no se necesitan aplicar tipos. La asignación se logra con el operador =. @@ -220,7 +222,6 @@ for (var i = 0; i < 5; i++){  }  // && es un "y" lógico, || es un "o" lógico -var casa = {tamano:"grande",casa:"color"};  if (casa.tamano == "grande" && casa.color == "azul"){      casa.contiene = "oso";  } diff --git a/es-es/julia-es.html.markdown b/es-es/julia-es.html.markdown index 203ee3bb..1e01c2e3 100644 --- a/es-es/julia-es.html.markdown +++ b/es-es/julia-es.html.markdown @@ -4,757 +4,937 @@ contributors:      - ["Leah Hanson", "http://leahhanson.us"]  translators:      - ["Guillermo Garza", "http://github.com/ggarza"] +    - ["Ismael Venegas Castelló", "https://github.com/Ismael-VC"]  filename: learnjulia-es.jl  lang: es-es  --- -Julia es un nuevo lenguaje funcional homoiconic enfocado en computación técnica. -Aunque que tiene todo el poder de macros homoiconic, funciones de primera -clase, y control de bajo nivel, Julia es tan fácil de aprender y utilizar como -Python. + -Esto se basa en la versión de desarrollo actual de Julia, del 18 de octubre de -2013. +[Julia](http://julialanges.github.io) es un [lenguaje de programación](http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n) [multiplataforma](http://es.wikipedia.org/wiki/Multiplataforma) y [multiparadigma](http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_multiparadigma) de [tipado dinámico](http://es.wikipedia.org/wiki/Tipado_din%C3%A1mico), [alto nivel](http://es.wikipedia.org/wiki/Lenguaje_de_alto_nivel) y [alto desempeño](http://es.wikipedia.org/wiki/Computaci%C3%B3n_de_alto_rendimiento) para la computación [genérica](http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_de_prop%C3%B3sito_general), [técnica y científica](http://es.wikipedia.org/wiki/Computaci%C3%B3n_cient%C3%ADfica),  con una sintaxis que es familiar para los usuarios de otros entornos de computación técnica y científica. Provee de un [sofisticado compilador JIT](http://es.wikipedia.org/wiki/Compilaci%C3%B3n_en_tiempo_de_ejecuci%C3%B3n), [ejecución distribuida y paralela](http://docs.julialang.org/en/release-0.3/manual/parallel-computing), [precisión numérica](http://julia.readthedocs.org/en/latest/manual/integers-and-floating-point-numbers) y de una [extensa librería con funciones matemáticas](http://docs.julialang.org/en/release-0.3/stdlib). La librería estándar, escrita casi completamente en Julia, también integra las mejores y más maduras librerías de C y Fortran para el [álgebra lineal](http://docs.julialang.org/en/release-0.3/stdlib/linalg), [generación de números aleatorios](http://docs.julialang.org/en/release-0.3/stdlib/numbers/?highlight=random#random-numbers), [procesamiento de señales](http://docs.julialang.org/en/release-0.3/stdlib/math/?highlight=signal#signal-processing), y [procesamiento de cadenas](http://docs.julialang.org/en/release-0.3/stdlib/strings). Adicionalmente, la comunidad de [desarrolladores de Julia](https://github.com/JuliaLang/julia/graphs/contributors) contribuye un número de [paquetes externos](http://pkg.julialang.org) a través del gestor de paquetes integrado de Julia a un paso acelerado. [IJulia](https://github.com/JuliaLang/IJulia.jl), una colaboración entre las comunidades de [IPython](http://ipython.org) y Julia, provee de una poderosa interfaz gráfica basada en el [navegador para Julia](https://juliabox.org). -```ruby +En Julia los programas están organizados entorno al [despacho múltiple](http://docs.julialang.org/en/release-0.3/manual/methods/#man-methods); definiendo funciones y sobrecargándolas para diferentes combinaciones de tipos de argumentos, los cuales también pueden ser definidos por el usuario. -# Comentarios de una línea comienzan con una almohadilla (o signo gato) +### ¡Prueba Julia ahora mismo! -#= Commentarios multilinea pueden escribirse -   usando '#=' antes de el texto  y '=#'  -   después del texto. También se pueden anidar. +* [TryJupyter](https://try.jupyter.org) +* [JuliaBox](https://juliabox.org) +* [SageMathCloud](https://cloud.sagemath.com) + +### Resumen de Características: + +* [Despacho múltiple](http://en.wikipedia.org/wiki/Multiple_dispatch): permite definir el comportamiento de las funciones a través de múltiples combinaciones de tipos de argumentos (**métodos**). +* Sistema de **tipado dinámico**: tipos para la documentación, la optimización y el despacho. +* [Buen desempeño](http://julialang.org/benchmarks), comparado al de lenguajes **estáticamente compilados** como C. +* [Gestor de paquetes](http://docs.julialang.org/en/release-0.3/stdlib/pkg) integrado. +* [Macros tipo Lisp](http://docs.julialang.org/en/release-0.3/manual/metaprogramming/#macros) y otras comodidades para la [meta programación](http://docs.julialang.org/en/release-0.3/manual/metaprogramming). +* Llamar funciones de otros lenguajes, mediante paquetes como: **Python** ([PyCall](https://github.com/stevengj/PyCall.jl)), [Mathematica](http://github.com/one-more-minute/Mathematica.jl), **Java** ([JavaCall](http://github.com/aviks/JavaCall.jl)), **R** ([Rif](http://github.com/lgautier/Rif.jl) y [RCall](http://github.com/JuliaStats/RCall.jl)) y **Matlab** ([MATLAB](http://github.com/JuliaLang/MATLAB.jl)). +* [Llamar funciones de C y Fortran](http://docs.julialang.org/en/release-0.3/manual/calling-c-and-fortran-code) **directamente**: sin necesidad de usar envoltorios u APIs especiales. +* Poderosas características de **línea de comandos** para [gestionar otros procesos](http://docs.julialang.org/en/release-0.3/manual/running-external-programs). +* Diseñado para la [computación paralela y distribuida](http://docs.julialang.org/en/release-0.3/manual/parallel-computing) **desde el principio**. +* [Corrutinas](http://en.wikipedia.org/wiki/Coroutine): hilos ligeros "**verdes**". +* Los [tipos definidos por el usuario](http://docs.julialang.org/en/release-0.3/manual/types) son tan **rápidos y compactos** como los tipos estándar integrados. +* [Generación automática de código](http://docs.julialang.org/en/release-0.3/stdlib/base/?highlight=%40code#internals) **eficiente y especializado** para diferentes tipos de argumentos. +* [Conversiones y promociones](http://docs.julialang.org/en/release-0.3/manual/conversion-and-promotion) para tipos numéricos y de otros tipos, **elegantes y extensibles**. +* Soporte eficiente para [Unicode](http://es.wikipedia.org/wiki/Unicode), incluyendo [UTF-8](http://es.wikipedia.org/wiki/UTF-8) pero sin limitarse solo a este. +* [Licencia MIT](https://github.com/JuliaLang/julia/blob/master/LICENSE.md): libre y de código abierto. + +Esto se basa en la versión `0.3.11`. + +```julia +# Los comentarios de una línea comienzan con una almohadilla (o signo de gato). + +#= +  Los commentarios multilínea pueden escribirse +  usando '#=' antes de el texto  y '=#' +  después del texto. También se pueden anidar.  =# -#################################################### -## 1. Tipos de datos primitivos y operadores. -#################################################### -# Todo en Julia es una expresión. +############################################## +# 1. Tipos de datos primitivos y operadores. # +############################################## + +# Todo en Julia es una expresión (Expr).  # Hay varios tipos básicos de números. -3 # => 3 (Int64) -3.2 # => 3.2 (Float64) -2 + 1im # => 2 + 1im (Complex{Int64}) -2//3 # => 2//3 (Rational{Int64}) +3          # => 3          # Int64 +3.2        # => 3.2        # Float64 +2 + 1im    # => 2 + 1im    # Complex{Int64} +2 // 3     # => 2//3       # Rational{Int64}  # Todos los operadores infijos normales están disponibles. -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 -35 / 5 # => 7.0 -5/2 # => 2.5 # dividir un Int por un Int siempre resulta en un Float -div (5, 2) # => 2 # para un resultado truncado, usa div -5 \ 35 # => 7.0 -2 ^ 2 # => 4 # exponente, no es xor -12 % 10 # => 2 - -# Refuerza la precedencia con paréntesis -(1 + 3) * 2 # => 8 - -# Operadores a nivel de bit -~2 # => -3   # bitwise not -3 & 5 # => 1 # bitwise and -2 | 4 # => 6 # bitwise or -2 $ 4 # => 6 # bitwise xor -2 >>> 1 # => 1 # logical shift right -2 >> 1  # => 1 # arithmetic shift right -2 << 1  # => 4 # logical/arithmetic shift left - -# Se puede utilizar la función bits para ver la representación binaria de un -# número. +1 + 1        # => 2 +8 - 1        # => 7 +10 * 2       # => 20 +35 / 5       # => 7.0    # dividir un Int por un Int siempre resulta +                         # en un Float +5 / 2        # => 2.5 +div(5, 2)    # => 2      # para un resultado truncado, usa la función div +5 \ 35       # => 7.0 +2 ^ 2        # => 4      # exponente, no es XOR +12 % 10      # => 2 + +# Refuerza la precedencia con paréntesis. +(1 + 3) * 2    # => 8 + +# Operadores a nivel de bit. +~2         # => -3    # bitwise NOT +3 & 5      # => 1     # bitwise AND +2 | 4      # => 6     # bitwise OR +2 $ 4      # => 6     # bitwise XOR +2 >>> 1    # => 1     # desplazamiento lógico hacia la derecha +2 >> 1     # => 1     # desplazamiento aritmético hacia la derecha +2 << 1     # => 4     # desplazamiento lógico/aritmético hacia la izquierda + +# Se puede utilizar la función bits para ver la representación +# binaria de un número.  bits(12345)  # => "0000000000000000000000000000000000000000000000000011000000111001" +  bits(12345.0)  # => "0100000011001000000111001000000000000000000000000000000000000000" -# Valores 'boolean' (booleanos) son primitivos -true -false - -# Operadores Boolean (booleanos) -!true # => false -!false # => true -1 == 1 # => true -2 == 1 # => false -1 != 1 # => false -2 != 1 # => true -1 < 10 # => true -1 > 10 # => false -2 <= 2 # => true -2 >= 2 # => true +# Los valores booleanos (Bool) son primitivos. +true     # => true +false    # => false + +# Operadores booleanos. +!true     # => false +!false    # => true +1 == 1    # => true +2 == 1    # => false +1 != 1    # => false +2 != 1    # => true +1 < 10    # => true +1 > 10    # => false +2 <= 2    # => true +2 >= 2    # => true +  # ¡Las comparaciones pueden ser concatenadas! -1 < 2 < 3 # => true -2 < 3 < 2 # => false +1 < 2 < 3    # => true +2 < 3 < 2    # => false -# Strings se crean con "  -"Esto es un string." +# Los literales de cadenas (String) se crean con la comilla doble: " +"Esto es una cadena." -# Literales de caracteres se escriben con ' +# Los literales de caracteres (Char) se crean con la comilla simple: '  'a' -# Una string puede ser indexado como una array de caracteres -"Esto es un string."[1] # => 'E' # Índices en Julia empiezen del 1 -# Sin embargo, esto no va a funcionar bien para strings UTF8,  +# Una cadena puede ser indexada como una arreglo de caracteres. +"Esto es un string."[1]    # => 'E'    # Los índices en Julia comienzan en: 1 + +# Sin embargo, esto no va a funcionar bien para las cadenas UTF8 (UTF8String),  # Lo que se recomienda es la iteración (map, for, etc). -# $ puede ser utilizado para la interpolación de strings: -"2 + 2 = $(2 + 2)" # => "2 + 2 = 4" -# Se puede poner cualquier expresión de Julia dentro los paréntesis. +# $ puede ser utilizado para la interpolación de cadenas, se puede poner +# cualquier expresión de Julia dentro los paréntesis. +"2 + 2 = $(2 + 2)"    # => "2 + 2 = 4" + +# Otra forma para formatear cadenas es usando el macro printf. +@printf "%d es menor de %f\n" 4.5 5.3    # 5 es menor de 5.300000 -# Otro forma de formatear strings es el macro printf -@printf "%d es menor de %f" 4.5 5.3 # 5 es menor de 5.300000 +# ¡Imprimir es muy fácil! +println("¡Hola Julia!")    # ¡Hola Julia! -# Imprimir es muy fácil -println("Soy Julia. ¡Encantado de conocerte!") -#################################################### -## 2. Variables y Colecciones -#################################################### +############################## +# 2. Variables y Colecciones # +##############################  # No hay necesidad de declarar las variables antes de asignarlas. -una_variable = 5 # => 5 -una_variable # => 5 +una_variable = 5    # => 5 +una_variable        # => 5 -# Acceder a variables no asignadas previamente es una excepción. +# Acceder a una variable no asignada previamente es una excepción.  try -    otra_variable # => ERROR: some_other_var not defined +    otra_variable    # ERROR: otra_variable not defined  catch e -    println(e) +    println(e)       # UndefVarError(:otra_variable)  end -# Los nombres de variables comienzan con una letra. -# Después de eso, puedes utilizar letras, dígitos, guiones y signos de +# Los nombres de variables comienzan con una letra o guion bajo: _. +# Después de eso, puedes utilizar letras, dígitos, guiones bajos y signos de  # exclamación. -OtraVariable123! = 6 # => 6 +otraVariable_123! = 6    # => 6 + +# También puedes utilizar caracteres Unicode. +☃ = 8    # => 8 -# También puede utilizar caracteres unicode -☃ = 8 # => 8  # Estos son especialmente útiles para la notación matemática -2 * π # => 6.283185307179586 - -# Una nota sobre las convenciones de nomenclatura de Julia: -# -# * Los nombres de las variables aparecen en minúsculas, con separación de  -#   palabra indicado por underscore ('\ _').  -# -# * Los nombres de los tipos comienzan con una letra mayúscula y separación de -#   palabras se muestra con CamelCase en vez de underscore. -# -# * Los nombres de las funciones y los macros están en minúsculas, sin -#   underscore. -# -# * Funciones que modifican sus inputs tienen nombres que terminan en!. Estos  -#   funciones a veces se llaman mutating functions o in-place functions. - -# Los Arrays almacenan una secuencia de valores indexados entre 1 hasta n -a = Int64[] # => 0-element Int64 Array - -# Literales de arrays 1-dimensionales se pueden escribir con valores separados -# por comas. -b = [4, 5, 6] # => 3-element Int64 Array: [4, 5, 6] -b[1] # => 4 -b[end] # => 6 - -# Los arrays 2-dimensionales usan valores separados por espacios y filas -# separados por punto y coma. -matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4] - -# Añadir cosas a la final de una lista con push! y append! -push!(a,1)     # => [1] -push!(a,2)     # => [1,2] -push!(a,4)     # => [1,2,4] -push!(a,3)     # => [1,2,4,3] -append!(a,b) # => [1,2,4,3,4,5,6] - -# Eliminar de la final con pop -pop!(b)        # => 6 y b ahora es [4,5] - -# Vamos a ponerlo de nuevo  -push!(b, 6)   # b es ahora [4,5,6] de nuevo. - -a[1] # => 1 # recuerdan que los índices de Julia empiezan desde 1, no desde 0! - -# end es una abreviatura para el último índice. Se puede utilizar en cualquier  -# expresión  de indexación -a[end] # => 6 - -# tambien hay shift y unshift -shift!(a) # => 1 y a es ahora [2,4,3,4,5,6] -unshift!(a,7) # => [7,2,4,3,4,5,6] - -# Nombres de funciónes que terminan en exclamaciones indican que modifican  -# su argumento. -arr = [5,4,6] # => 3-element Int64 Array: [5,4,6] -sort(arr) # => [4,5,6]; arr es todavía [5,4,6] -sort!(arr) # => [4,5,6]; arr  es ahora [4,5,6] - -# Buscando fuera de límites es un BoundsError +# (multiplicación implicita). +2π    # => 6.283185307179586 + +#= +  Una nota sobre las convenciones de nomenclatura de Julia: + +  * Los nombres de las variables aparecen en minúsculas, con separación de +    palabra indicado por un guion bajo: + +    otra_variable + +  * Los nombres de los tipos comienzan con una letra mayúscula y separación de +    palabras se muestra con CamelCase en vez de guion bajo: + +    OtroTipo + +  * Los nombres de las funciones y los macros están en minúsculas, sin +    underscore: + +    otromacro + +  * Funciones que modifican sus entradas tienen nombres que terminan en: !. +    Estas funciones a veces se les llaman funciones transformadoras o +    funciones in situ: + +    otra_funcion! +=# + +# Los arreglos (Array) almacenan una secuencia de valores indexados de entre 1 hasta n. +a = Int64[]    # => 0-element Array{Int64,1} + +# Los literales de arregos unidimensionales se pueden escribir con valores +# separados por comas. +b = [4, 5, 6] +#= + => 3-element Array{Int64,1}: +     4 +     5 +     6 +=# +b[1]      # => 4 +b[end]    # => 6 + +# Los arreglos bidimensionales usan valores separados por espacios y filas +# separadas por punto y coma. +matrix = [1 2; 3 4] +#= + => 2x2 Array{Int64,2}: +     1  2 +     3  4 +=# + +# Añadir cosas a la final de un arreglo con push! y append!. +push!(a, 1)      # => [1] +push!(a, 2)      # => [1,2] +push!(a, 4)      # => [1,2,4] +push!(a, 3)      # => [1,2,4,3] +append!(a, b)    # => [1,2,4,3,4,5,6] + +# Eliminar del final con pop!. +pop!(b)    # => 6 y b ahora es: [4,5] + +# Vamos a ponerlo de nuevo. +push!(b, 6)    # b es ahora [4,5,6] de nuevo + +a[1]    # => 1    # recuerda, los índices de Julia empiezan desde 1, no desde 0! + +# end es una abreviatura para el último índice. Se puede utilizar en cualquier +# expresión  de indexación. +a[end]    # => 6 + +# También hay shift! y unshift!. +shift!(a)         # => 1 y a es ahora: [2,4,3,4,5,6] +unshift!(a, 7)    # => [7,2,4,3,4,5,6] + +# Los nombres de funciónes que terminan en exclamaciones indican que modifican +# su o sus argumentos de entrada. +arr = [5, 4, 6]    # => 3-element Array{Int64,1}: [5,4,6] +sort(arr)          # => [4,5,6] y arr es todavía: [5,4,6] +sort!(arr)         # => [4,5,6] y arr es ahora: [4,5,6] + +# Buscando fuera de límites es un BoundsError.  try -    a[0] # => ERROR: BoundsError() in getindex at array.jl:270 -    a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270 +    a[0]          # ERROR: BoundsError() in getindex at array.jl:270 +    a[end+1]      # ERROR: BoundsError() in getindex at array.jl:270  catch e -    println(e) +    println(e)    # BoundsError()  end -# Errors dan la línea y el archivo de su procedencia, aunque sea en el standard -# library. Si construyes Julia de source, puedes buscar en el source para -# encontrar estos archivos. +# Las excepciones y los errores dan la línea y el archivo de su procedencia, +# aunque provenga de la librería estándar. Si compilas Julia del código fuente, +# puedes buscar en el código para encontrar estos archivos. + +# Se puede inicializar un arreglo con un rango (Range). +a = [1:5]    # => 5-element Array{Int64,1}: [1,2,3,4,5] -# Se puede inicializar arrays de un range -a = [1:5] # => 5-element Int64 Array: [1,2,3,4,5] +# Puedes mirar en los rangos con la sintaxis de rebanada. +a[1:3]       # => [1,2,3] +a[2:end]     # => [2,3,4,5] -# Puedes mirar en ranges con sintaxis slice. -a[1:3] # => [1, 2, 3] -a[2:end] # => [2, 3, 4, 5] +# Eliminar elementos de un arreglo por índice con splice! +arr = [3, 4, 5] +splice!(arr, 2)    # => 4 y arr es ahora: [3,5] -# Eliminar elementos de una array por índice con splice! -arr = [3,4,5] -splice!(arr,2) # => 4 ; arr es ahora [3,5] +# Concatenar arreglos con append! +b = [1, 2, 3] +append!(a, b)    # a ahora es: [1,2,3,4,5,1,2,3] -# Concatenar listas con append! -b = [1,2,3] -append!(a,b) # ahroa a es [1, 2, 3, 4, 5, 1, 2, 3] +# Comprueba la existencia de un elemento en un arreglo con in. +in(1, a)    # => true -# Comprueba la existencia en una lista con in -in(1, a) # => true +# Examina la longitud con length. +length(a)    # => 8 -# Examina la longitud con length -length(a) # => 8 +# Las tuplas (Tuple) son inmutables. +tup = (1, 2, 3)    # => (1,2,3)    # una tupla tipo (Int64,Int64,Int64) +tup[1]             # => 1 -# Tuples son immutable. -tup = (1, 2, 3) # => (1,2,3) # un (Int64,Int64,Int64) tuple. -tup[1] # => 1  try: -    tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) +    tup[1] = 3     # ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64)  catch e -    println(e) +    println(e)     # MethodError(setindex!,(:tup,3,1))  end -# Muchas funciones de lista también trabajan en las tuples -length(tup) # => 3 -tup[1:2] # => (1,2) -in(2, tup) # => true +# Muchas funciones de arreglos también trabajan en con las tuplas. +length(tup)    # => 3 +tup[1:2]       # => (1,2) +in(2, tup)     # => true -# Se puede desempacar tuples en variables -a, b, c = (1, 2, 3) # => (1,2,3)  # a is now 1, b is now 2 and c is now 3 +# Se pueden desempacar las tuplas en variables individuales. +a, b, c = (1, 2, 3)    # => (1,2,3)    # ahora a es 1, b es 2 y c es 3 -# Los tuples se crean, incluso si se omite el paréntesis -d, e, f = 4, 5, 6 # => (4,5,6) +# Los tuplas se crean, incluso si se omiten los paréntesis. +d, e, f = 4, 5, 6    # => (4,5,6) -# Un tuple 1-elemento es distinto del valor que contiene -(1,) == 1 # => false -(1) == 1 # => true +# Una tupla de un elemento es distinta del valor que contiene. +(1,) == 1    # => false +(1) == 1     # => true -# Mira que fácil es cambiar dos valores -e, d = d, e  # => (5,4) # d is now 5 and e is now 4 +# Mira que fácil es cambiar dos valores! +e, d = d, e    # => (5,4)    # ahora d es 5 y e es 4 +# Los diccionarios (Dict) son arreglos asociativos. +dicc_vacio = Dict()    # => Dict{Any,Any} with 0 entries -# Dictionaries almanecan mapeos -dict_vacio = Dict() # => Dict{Any,Any}() +# Se puede crear un diccionario usando una literal. +dicc_lleno = ["uno" => 1, "dos" => 2, "tres" => 3] +#= + => Dict{ASCIIString,Int64} with 3 entries: +      "tres" => 3 +      "dos"  => 2 +      "uno"  => 1 +=# + +# Busca valores con: []. +dicc_lleno["uno"]    # => 1 + +# Obtén todas las claves con. +keys(dicc_lleno) +#= + => KeyIterator for a Dict{ASCIIString,Int64} with 3 entries. Keys: +      "tres" +      "dos" +      "uno" +=# -# Se puede crear un dictionary usando un literal -dict_lleno = ["one"=> 1, "two"=> 2, "three"=> 3] -# => Dict{ASCIIString,Int64} +# Nota: los elementos del diccionario no están ordenados y no se guarda el orden +# en que se insertan. -# Busca valores con [] -dict_lleno["one"] # => 1 +# Obtén todos los valores. +values(dicc_lleno) +#= + => ValueIterator for a Dict{ASCIIString,Int64} with 3 entries. Values: +      3 +      2 +      1 +=# -# Obtén todas las claves  -keys(dict_lleno) -# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) -# Nota - claves del dictionary no están ordenados ni en el orden en que se -# insertan. +# Nota: igual que el anterior en cuanto a ordenamiento de los elementos. -# Obtén todos los valores -values(dict_lleno) -# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) -# Nota - Igual que el anterior en cuanto a ordenamiento de claves. +# Comprueba si una clave existe en un diccionario con in y haskey. +in(("uno", 1), dicc_lleno)     # => true +in(("tres", 3), dicc_lleno)    # => false -# Compruebe si hay existencia de claves en un dictionary con in y haskey -in(("uno", 1), dict_lleno) # => true -in(("tres", 3), dict_lleno) # => false -haskey(dict_lleno, "one") # => true -haskey(dict_lleno, 1) # => false +haskey(dicc_lleno, "uno")      # => true +haskey(dicc_lleno, 1)          # => false -# Tratando de buscar una clave que no existe producirá un error +# Tratar de obtener un valor con una clave que no existe producirá un error.  try -    dict_lleno["dos"] # => ERROR: key not found: dos in getindex at dict.jl:489 +    # ERROR: key not found: cuatro in getindex at dict.jl:489 +    dicc_lleno["cuatro"]  catch e -    println(e) +    println(e)    # KeyError("cuatro")  end -# Utilice el método get para evitar ese error proporcionando un valor -# predeterminado -# get(dictionary,key,default_value) -get(dict_lleno,"one",4) # => 1 -get(dict_lleno,"four",4) # => 4 +# Utiliza el método get para evitar este error proporcionando un valor +# predeterminado: get(diccionario, clave, valor_predeterminado). +get(dicc_lleno, "uno", 4)       # => 1 +get(dicc_lleno, "cuatro", 4)    # => 4 + +# Usa conjuntos (Set) para representar colecciones de valores únicos, no +# ordenados. +conjunto_vacio = Set()    # => Set{Any}({}) -# Usa Sets para representar colecciones (conjuntos) de valores únicos, no -# ordenadas -conjunto_vacio = Set() # => Set{Any}() -# Iniciar una set de valores -conjunto_lleno = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4) +# Iniciar una conjunto de valores. +conjunto_lleno = Set(1, 2, 2, 3, 4)    # => Set{Int64}({4,2,3,1}) -# Añadir más valores a un conjunto -push!(conjunto_lleno,5) # => Set{Int64}(5,4,2,3,1) -push!(conjunto_lleno,5) # => Set{Int64}(5,4,2,3,1) +# Añadir más valores a un conjunto. +push!(conjunto_lleno, 5)    # => Set{Int64}({4,2,3,5,1}) +push!(conjunto_lleno, 5)    # => Set{Int64}({4,2,3,5,1}) -# Compruebe si los valores están en el conjunto -in(2, conjunto_lleno) # => true -in(10, conjunto_lleno) # => false +# Comprobar si los valores están en el conjunto. +in(2, conjunto_lleno)     # => true +in(10, conjunto_lleno)    # => false -# Hay funciones de intersección de conjuntos, la unión, y la diferencia. -conjunto_otro= Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3) -intersect(conjunto_lleno, conjunto_otro) # => Set{Int64}(3,4,5) -union(conjunto_lleno, conjunto_otro) # => Set{Int64}(1,2,3,4,5,6) -setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4) +# Hay funciones de intersección, unión y diferencia de conjuntos. +otro_conjunto = Set(3, 4, 5, 6)             # => Set{Int64}({6,4,5,3}) +intersect(conjunto_lleno, otro_conjunto)    # => Set{Int64}({3,4,5}) +union(conjunto_lleno, otro_conjunto)        # => Set{Int64}({1,2,3,4,5,6}) +setdiff(Set(1, 2, 3, 4), Set(2, 3, 5))      # => Set{Int64}({1,4}) -#################################################### -## 3. Control de Flujo -#################################################### +####################### +# 3. Control de Flujo # +####################### -# Hagamos una variable +# Hagamos una variable.  una_variable = 5 -# Aquí está una declaración de un 'if'. La indentación no es significativa en -# Julia +# Aquí está la declaración de un if. La indentación no es significativa en +# Julia.  if una_variable > 10 -    println("una_variable es completamente mas grande que 10.") -elseif una_variable < 10    # Este condición 'elseif' es opcional. -    println("una_variable es mas chica que 10.") -else                    # Esto también es opcional. -    println("una_variable es de hecho 10.") +    println("una_variable es completamente mayor que 10.") +elseif una_variable < 10                     # esta condición elseif es opcional +    println("una_variable es menor que 10.") +else                                         # esto también es opcional +    println("De echo una_variable es 10.")  end -# => imprime "una_variable es mas chica que 10." +# imprime: una_variable es menor que 10. -# For itera sobre tipos iterables -# Tipos iterables incluyen Range, Array, Set, Dict, y String. -for animal=["perro", "gato", "raton"] -    println("$animal es un mamifero") -    # Se puede usar $ para interpolar variables o expresiónes en strings +# El bucle for itera sobre tipos iterables, ie. Range, Array, Set, +# Dict y String. +for animal in ["perro", "gato", "ratón"] +    # Se puede usar $ para interpolar variables o expresiones en ls cadenas. +    println("$animal es un mamífero.")  end -# imprime: -#    perro es un mamifero -#    gato es un mamifero -#    raton es un mamifero +#= + imprime: +   perro es un mamífero. +   gato es un mamífero. +   ratón es un mamífero. +=# -for a in ["perro"=>"mamifero","gato"=>"mamifero","raton"=>"mamifero"] -    println("$(a[1]) es un $(a[2])") +for a in ["perro" => "mamífero", "gato" => "mamífero", "ratón" => "mamífero"] +    println("$(a[1]) es un $(a[2]).")  end -# imprime: -#    perro es un mamifero -#    gato es un mamifero -#    raton es un mamifero +#= + imprime: +   perro es un mamífero. +   gato es un mamífero. +   ratón es un mamífero. +=# -for (k,v) in ["perro"=>"mamifero", "gato"=>"mamifero", "raton"=>"mamifero"] -    println("$k es un $v") +for (k,v) in ["perro"=>"mamífero", "gato"=>"mamífero", "ratón"=>"mamífero"] +    println("$k es un $v.")  end -# imprime: -#    perro es un mamifero -#    gato es un mamifero -#    raton es un mamifero +#= + imprime: +   perro es un mamífero. +   gato es un mamífero. +   ratón es un mamífero. +=# -# While itera hasta que una condición no se cumple. +# El bucle while itera hasta que una condición se deje de cumplir.  x = 0  while x < 4      println(x) -    x += 1  # versión corta de x = x + 1 +    x += 1    # versión corta de: x = x + 1  end -# imprime: -#   0 -#   1 -#   2 -#   3 +#= +imprime: +  0 +  1 +  2 +  3 +=# -# Maneja excepciones con un bloque try/catch -try -   error("ayuda") +# Maneja excepciones con un bloque try/catch. +try    # intentar +   error("Ooops!")  catch e -   println("capturando $e") +   println("capturando: $e")    # capturando: ErrorException("Ooops!")  end -# => capturando ErrorException("ayuda") -#################################################### -## 4. Funciones -#################################################### +################ +# 4. Funciones # +################ -# Usa 'function' para crear nuevas funciones +# Usa function para crear nuevas funciones. -#function nombre(arglist) -#  cuerpo... -#end +#= +    function nombre(arglist) +        cuerpo... +    end +=#  function suma(x, y)      println("x es $x e y es $y") -    # Las funciones devuelven el valor de su última declaración +    # las funciones devuelven el valor de su última expresión      x + y  end +# => suma (generic function with 1 method) -suma(5, 6) # => 11 # después de imprimir "x es 5 e y es de 6" +suma(5, 6)    # => 11    # después de imprimir: x es 5 e y es 6 + +# También puedes usar esta otra sintaxis para definir funciones! +resta(x, y) = x - y    # => resta (generic function with 1 method)  # Puedes definir funciones que toman un número variable de -# argumentos posicionales +# argumentos posicionales (el ... se llama un splat).  function varargs(args...) +    # Usa la palabra clave return para regresar desde cualquier +    # lugar de la función.      return args -    # Usa la palabra clave return para devolver en cualquier lugar de la función  end  # => varargs (generic function with 1 method) -varargs(1,2,3) # => (1,2,3) +varargs(1, 2, 3)      # => (1,2,3) +varargs([1, 2, 3])    # => ([1,2,3],) -# El ... se llama un splat. -# Acabamos de utilizar lo en una definición de función. -# También se puede utilizar en una llamada de función, -# donde va splat un Array o el contenido de un Tuple en la lista de argumentos. -Set([1,2,3])    # => Set{Array{Int64,1}}([1,2,3]) # Produce un Set de Arrays -Set([1,2,3]...) # => Set{Int64}(1,2,3) # esto es equivalente a Set(1,2,3) +# Acabamos de utilizar el splat (...) en la definición de una función. También +# se puede utilizar al llamar a una función, donde se esparce un arreglo, tupla +# o en general una secuencia iterable en la tupla de argumentos. +varargs([1, 2, 3]...)    # => (1,2,3)    # igual que: varargs(1, 2, 3) -x = (1,2,3)     # => (1,2,3) -Set(x)          # => Set{(Int64,Int64,Int64)}((1,2,3)) # un Set de Tuples -Set(x...)       # => Set{Int64}(2,3,1) +x = (1, 2, 3)    # => (1,2,3) +varargs(x)       # => ((1,2,3),) +varargs(x...)    # => (1,2,3) +varargs("abc"...)    # => ('a','b','c') -# Puede definir funciones con argumentos posicionales opcionales -function defaults(a,b,x=5,y=6) +# Puedes definir funciones con argumentos posicionales opcionales. +function defaults(a, b, x=5, y=6)      return "$a $b y $x $y"  end +# => defaults (generic function with 3 methods) + +defaults('h', 'g')              # => "h g y 5 6" +defaults('h', 'g', 'j')         # => "h g y j 6" +defaults('h', 'g', 'j', 'k')    # => "h g y j k" -defaults('h','g') # => "h g y 5 6" -defaults('h','g','j') # => "h g y j 6" -defaults('h','g','j','k') # => "h g y j k"  try -    defaults('h') # => ERROR: no method defaults(Char,) -    defaults() # => ERROR: no methods defaults() +    defaults('h')    # ERROR: `defaults` has no method matching defaults(::Char) +    defaults()       # ERROR: `defaults` has no method matching defaults()  catch e -    println(e) +    println(e)       # MethodError(defaults,('h',))  end -# Puedes definir funciones que toman argumentos de palabra clave -function args_clave(;k1=4,nombre2="hola") # note the ; -    return ["k1"=>k1,"nombre2"=>nombre2] +# Puedes definir funciones que tomen argumentos de palabras clave. +function args_clave(;k1=4, nombre2="hola")    # nota el punto y coma: ; +    return ["k1" => k1, "nombre2" => nombre2]  end +# => args_clave (generic function with 1 method) -args_clave(nombre2="ness") # => ["nombre2"=>"ness","k1"=>4] -args_clave(k1="mine") # => ["k1"=>"mine","nombre2"=>"hola"] -args_clave() # => ["nombre2"=>"hola","k1"=>4] +args_clave(nombre2="ness")    # => ["nombre2"=>"ness","k1"=>4] +args_clave(k1="mine")         # => ["k1"=>"mine","nombre2"=>"hola"] +args_clave()                  # => ["nombre2"=>"hola","k1"=>4] -# Puedes combinar todo tipo de argumentos en la misma función -function todos_los_args(arg_normal, arg_posicional_opcional=2; arg_clave="foo") -    println("argumento normal: $arg_normal") -    println("argumento optional: $arg_posicional_opcional") -    println("argumento de clave: $arg_clave") +# Puedes combinar todo tipo de argumentos en la misma función. +function todos_los_args(arg_posicional, arg_opcional=2; arg_clave="foo") +    println("argumento posicional: $arg_posicional") +    println("  argumento opcional: $arg_opcional") +    println("     argumento clave: $arg_clave")  end +# => todos_los_args (generic function with 2 methods) +# No se necesita punto y coma ; al llamar la función usando un argumento clave, +# esto solo es necesario en la definición de la función.  todos_los_args(1, 3, arg_clave=4) -# imprime: -#   argumento normal: 1 -#   argumento optional: 3 -#   argumento de clave: 4 +#= + imprime: +   argumento posicional: 1 +     argumento opcional: 3 +        argumento clave: 4 +=# -# Julia tiene funciones de primera clase +# Julia tiene funciones de primera clase.  function crear_suma(x) -    suma = function (y) +    suma = function (y)    # función anónima          return x + y      end      return suma  end +# => crear_suma (generic function with 1 method) -# Esta es el sintaxis "stabby lambda" para crear funciones anónimas -(x -> x > 2)(3) # => true +# Esta es otra sintaxis (estilo cálculo lambda), para crear funciones anónimas. +(x -> x > 2)(3)    # => true  # Esta función es idéntica a la crear_suma implementación anterior. -function crear_suma(x) -    y -> x + y -end +crear_suma(x) = y -> x + y -# También puedes nombrar la función interna, si quieres +# También puedes nombrar la función interna, si quieres.  function crear_suma(x)      function suma(y)          x + y      end      suma  end +# => crear_suma (generic function with 1 method) -suma_10 = crear_suma(10) -suma_10(3) # => 13 +suma_10 = crear_suma(10)    # => suma (generic function with 1 method) +suma_10(3)                  # => 13 +# Hay funciones integradas de orden superior. +map(suma_10, [1, 2, 3])                # => [11,12,13] +filter(x -> x > 5, [3, 4, 5, 6, 7])    # => [6,7] -# Hay funciones integradas de orden superior -map(suma_10, [1,2,3]) # => [11, 12, 13] -filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7] +# Se puede pasar un bloque a las funciones cuyo primer argumento posicional +# es otra función, como en map y filter. +map([1, 2, 3]) do arr +    suma_10(arr) +end +#= + => 3-element Array{Int64,1}: +     11 +     12 +     13 +=# + +filter([3, 4, 5, 6, 7]) do arr +    (x -> x > 5)(arr) +end +#= + => 2-element Array{Int64,1}: +     6 +     7 +=# -# Podemos usar listas por comprensión para mapeos -[suma_10(i) for i=[1, 2, 3]] # => [11, 12, 13] -[suma_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +# Podemos usar comprensiones de listas multidimensionales. +[suma_10(i) for i = [1, 2, 3]]     # => [11, 12, 13]    # 1D +[suma_10(i) for i in [1, 2, 3]]    # => [11, 12, 13] -#################################################### -## 5. Tipos -#################################################### +[i*j for i = [1:3], j in [1:3]]    # 2D +#= + => 3x3 Array{Int64,2}: +     1  2  3 +     2  4  6 +     3  6  9 +=# + +[i*j/k for i = [1:3], j = [1:3], k in [1:3]]    # 3D +#= + => 3x3x3 Array{Float64,3}: +     [:, :, 1] = +      1.0  2.0  3.0 +      2.0  4.0  6.0 +      3.0  6.0  9.0 + +     [:, :, 2] = +      0.5  1.0  1.5 +      1.0  2.0  3.0 +      1.5  3.0  4.5 + +     [:, :, 3] = +      0.333333  0.666667  1.0 +      0.666667  1.33333   2.0 +      1.0       2.0       3.0 +=# + + +############ +# 5. Tipos # +############ -# Julia tiene sistema de tipos.  # Cada valor tiene un tipo y las variables no tienen propios tipos. -# Se puede utilizar la función `typeof` para obtener el tipo de un valor. -typeof(5) # => Int64 +# Se puede utilizar la función typeof para obtener el tipo de un valor. +typeof(5)    # => Int64    # en un sistema de 64 bits, de lo contrario: Int32 -# Los tipos son valores de primera clase -typeof(Int64) # => DataType -typeof(DataType) # => DataType -# DataType es el tipo que representa los tipos, incluyéndose a sí mismo. +# Los tipos son valores de primera clase, DataType es el tipo que representa a +# los tipos, incluyéndose a sí mismo. +typeof(Int64)       # => DataType +typeof(DataType)    # => DataType -# Los tipos se usan para la documentación, optimizaciones, y envio. -# No están comprobados estáticamente. +# Los tipos se usan para la documentación, para optimizaciones +# y el despacho múltiple. No están comprobados estáticamente. -# Los usuarios pueden definir tipos  -# Son como registros o estructuras en otros idiomas.  -# Nuevos tipos se definen utilizado la palabra clave `type`. +# Los usuarios pueden definir sus propios tipos. +# Son como registros o estructuras en otros idiomas. +# Un nuevo tipos se define utilizado la palabra clave type.  # type Nombre -#   field::OptionalType +#   atributo::UnTipo    # las anotaciones de tipos son opcionales  #   ...  # end  type Tigre -  longituddecola::Float64 -  colordelpelaje # no incluyendo una anotación de tipo es el mismo que `::Any` +    longitud_cola::Float64 +    color_pelaje            # sin una anotación de tipo, es lo mismo que `::Any`  end -# Los argumentos del constructor por default son las propiedades  -# del tipo, en el orden en que están listados en la definición -tigger = Tigre(3.5,"anaranjado") # => Tiger(3.5,"anaranjado") +# Los argumentos del constructor por defecto son los atributos +# del tipo, en el orden en que están listados en la definición. +tigre = Tigre(3.5, "anaranjado")    # => Tigre(3.5,"anaranjado") -# El tipo funciona como la función constructora de valores de ese tipo -sherekhan = typeof(tigger)(5.6,"fuego") # => Tiger(5.6,"fuego") +# El tipo funciona como método constructor para los valores de ese tipo. +sherekhan = typeof(tigre)(5.6, "fuego")    # => Tigre(5.6,"fuego") -# Este estilo de tipos son llamados tipos concrete  -# Se pueden crear instancias, pero no pueden tener subtipos.  -# La otra clase de tipos es tipos abstractos (abstract types). +# Este estilo de tipos son llamados tipos concretos. +# Se pueden crear instancias de estos, pero no pueden tener subtipos. +# La otra clase de tipos son los tipos abstractos.  # abstract Nombre -abstract Gato # sólo un nombre y un punto en la jerarquía de tipos - -# De los tipos Abstract no se pueden crear instancias, pero pueden tener -# subtipos.  Por ejemplo, Number es un tipo abstracto. -subtypes(Number) # => 6-element Array{Any,1}: -                 #     Complex{Float16} -                 #     Complex{Float32} -                 #     Complex{Float64} -                 #     Complex{T<:Real} -                 #     Real -subtypes(Gato) # => 0-element Array{Any,1} - -# Cada tipo tiene un supertipo, utilice la función `súper` para conseguirlo. -typeof(5) # => Int64 -super(Int64) # => Signed -super(Signed) # => Real -super(Real) # => Number -super(Number) # => Any -super(super(Signed)) # => Number -super(Any) # => Any -# Todo de estos tipos, a excepción de Int64, son abstractos. - -# <: es el operador de subtipos -type Leon <: Gato # Leon es un subtipo de Gato -  color_de_crin -  rugido::String -end +abstract Gato    # sólo un nombre y un punto en la jerarquía de tipos + +# No se pueden crear instancias de los tipos abstractos, pero pueden tener +# subtipos. Por ejemplo, Number es un tipo abstracto. +subtypes(Number) +#= + => 2-element Array{Any,1}: +     Complex{T<:Real} +     Real +=# + +subtypes(Gato)    # => 0-element Array{Any,1} + +# Cada tipo tiene un supertipo, utiliza la función súper para conseguirlo. +typeof(5)               # => Int64 +super(Int64)            # => Signed +super(Signed)           # => Integer +super(Integer)          # => Real +super(Real)             # => Number +super(Number)           # => Any +super(super(Signed))    # => Real +super(Any)              # => Any -# Se puede definir más constructores para su tipo. -# Sólo defina una función del mismo nombre que el tipo -# y llame a un constructor existente para obtener un valor del tipo correcto -Leon(rugido::String) = Leon("verde",rugido) -# Este es un constructor externo porque es fuera de la definición del tipo - -type Pantera <: Gato # Pantera tambien es un a subtipo de Cat -  color_de_ojos -  Pantera() = new("verde") -    # Panteras sólo tendrán este constructor, y ningún constructor -    # predeterminado. +# Todos estos tipos, a excepción de Int64, son abstractos. + +# <: es el operador de subtipos. +type Leon <: Gato    # Leon es un subtipo de Gato +    color_crin +    rugido::String  end -# Utilizar constructores internos, como Panther hace, te da control sobre cómo -# se pueden crear valores del tipo.  Cuando sea posible, debes utilizar -# constructores exteriores en lugar de los internos. -#################################################### -## 6.  Envio múltiple -#################################################### +# Se pueden definir más constructores para un tipo. +# Sólo define una función del mismo nombre que el tipo y llama al constructor +# existente para obtener un valor del tipo correcto. -# En Julia, todas las funciones nombradas son funciones genéricas. -# Esto significa que se construyen a partir de muchos métodos pequeños  -# Cada constructor de Leon es un método de la función genérica Leon. +# Este es un constructor externo porque es fuera de la definición del tipo. +Leon(rugido::String) = Leon("verde", rugido) -# Por ejemplo, vamos a hacer un maullar función: +type Pantera <: Gato    # Pantera también es un a subtipo de Gato +    color_ojos -# Definiciones para Leon, Pantera, y Tigre -function maullar(animal::Leon) -  animal.rugido # acceso utilizando notación de puntos +    # Pantera sólo tendrá este constructor, y ningún constructor predeterminado. +    Pantera() = new("verde")  end -function maullar(animal::Pantera) -  "grrr" -end +# Utilizar constructores internos, como se hace en Pantera, te da control sobre +# cómo se pueden crear valores de este tipo. Cuando sea posible, debes utilizar +# constructores externos en lugar de internos. -function maullar(animal::Tigre) -  "rawwwr" -end -# Prueba de la función maullar -maullar(tigger) # => "rawwr" -maullar(Leon("cafe","ROAAR")) # => "ROAAR" -maullar(Pantera()) # => "grrr" +######################## +# 6. Despacho Múltiple # +######################## -# Revisar la jerarquía de tipos locales -issubtype(Tigre,Gato) # => false -issubtype(Leon,Gato) # => true -issubtype(Pantera,Gato) # => true +# En Julia, todas las funciones nombradas son funciones genéricas. +# Esto significa que se construyen a partir de muchos métodosmás pequeños. +# Cada constructor de Leon es un método de la función genérica Leon. -# Definición de una función que toma Gatos -function mascota(gato::Gato) -  println("El gato dice $(maullar(gato))") -end +# Por ejemplo, vamos a hacer métodos para para Leon, Pantera, y Tigre de una +# función genérica maullar: + +# acceso utilizando notación de puntos +maullar(animal::Leon) = animal.rugido +# => maullar (generic function with 1 method) +maullar(animal::Pantera) = "grrr" +# => maullar (generic function with 2 methods) +maullar(animal::Tigre) = "rawwwr" +# => maullar (generic function with 3 methods) + +# Se puede obtener una lista de métodos con la función methods. +methods(maullar) +#= +  # 3 methods for generic function "maullar": +  maullar(animal::Leon) at none:1 +  maullar(animal::Pantera) at none:1 +  maullar(animal::Tigre) at none:1 +=# + +# Prueba de la función maullar. +maullar(tigre)                    # => "rawwwr" +maullar(Leon("cafe", "ROAAR"))    # => "ROAAR" +maullar(Pantera())                # => "grrr" + +# Revisar la jerarquía de tipos locales. +issubtype(Tigre, Gato)      # => false    # igual que: Tigre <: Gato +issubtype(Leon, Gato)       # => true     # igual que: Leon <: Gato +issubtype(Pantera, Gato)    # => true + +# Definición de una función que acepta argumentos de tipo Gato. +mascota(gato::Gato) = println("El gato dice $(maullar(gato))") + +mascota(Leon("42"))    # El gato dice 42 -mascota(Leon("42")) # => imprime "El gato dice 42"  try -    mascota(tigger) # => ERROR: no method mascota(Tigre)) +    mascota(tigre)    # ERROR: `mascota` has no method matching mascota(::Tigre)  catch e -    println(e) +    println(e)        # MethodError(mascota,(Tigre(3.5,"anaranjado"),))  end -# En los lenguajes orientados a objetos, expedición única es común. Esto -# significa que el método se recogió basándose en el tipo del primer argumento. -# En Julia, todos los tipos de argumentos contribuyen a seleccionar el mejor -# método. +# En los lenguajes orientados a objetos, el despacho simple es común. Esto +# significa que la implementación del método a llamar se selecciona en base +# al tipo del primer argumento. + +# En Julia, los tipos de todos los argumentos contribuyen a seleccionar método +# más específico.  # Vamos a definir una función con más argumentos, para que podamos ver la  # diferencia -function pelear(t::Tigre,c::Gato) -  println("¡El tigre $(t.colordelpelaje) gana!") -end +pelear(t::Tigre, c::Gato) = println("¡El tigre $(t.color_pelaje) gana!")  # => pelear (generic function with 1 method) -pelear(tigger,Pantera()) # => imprime ¡El tigre anaranjado gana! -pelear(tigger,Leon("ROAR")) # => ¡El tigre anaranjado gana! +pelear(tigre, Pantera())       # ¡El tigre anaranjado gana! +pelear(tigre, Leon("ROAR"))    # ¡El tigre anaranjado gana! -# Vamos a cambiar el comportamiento cuando el Gato es específicamente un Leon -pelear(t::Tigre,l::Leon) = println("El león con melena $(l.color_de_crin) gana") +# Vamos a cambiar el comportamiento cuando el Gato sea específicamente un Leon. +pelear(t::Tigre, l::Leon) = println("El león con melena $(l.color_crin) gana.")  # => pelear (generic function with 2 methods) -pelear(tigger,Pantera()) # => imprime ¡El tigre anaranjado gana! -pelear(tigger,Leon("ROAR")) # => imprime El león con melena verde gana +pelear(tigre, Pantera())       # ¡El tigre anaranjado gana! +pelear(tigre, Leon("ROAR"))    # El león con melena verde gana. -# No necesitamos un tigre para poder luchar -pelear(l::Leon,c::Gato) = println("El gato victorioso dice $(maullar(c))") -# => fight (generic function with 3 methods) +# No necesitamos un tigre para poder luchar. +pelear(l::Leon, c::Gato) = println("El gato victorioso dice $(maullar(c)).") +# => pelear (generic function with 3 methods) + +methods(pelear) +#= +  # 3 methods for generic function "pelear": +  pelear(t::Tigre,l::Leon) at none:2 +  pelear(t::Tigre,c::Gato) at none:1 +  pelear(l::Leon,c::Gato) at none:2 +=# -pelear(Leon("balooga!"),Pantera()) # => imprime El gato victorioso dice grrr +pelear(Leon("balooga!"), Pantera())    # El gato victorioso dice grrr.  try -  pelear(Pantera(),Leon("RAWR")) # => ERROR: no method pelear(Pantera, Leon)) -catch +    # ERROR: `pelear` has no method matching pelear(::Pantera, ::Leon) +    pelear(Pantera(),Leon("RAWR")) +catch    # no hacer nada con la excepción atrapada  end -# Un metodo con el gato primero +# Un metodo con el tipo Gato primero.  pelear(c::Gato,l::Leon) = println("El gato le gana al León") -# Warning: New definition -#     pelear(Gato,Leon) at none:1 -# is ambiguous with: -#     pelear(Leon,Gato) at none:1. -# To fix, define -#     pelear(Leon,Leon) -# before the new definition. -# pelear (generic function with 4 methods) - -# Esta advertencia se debe a que no está claro que metodo de pelear será llamado -# en: -pelear(Leon("RAR"),Leon("cafe","rar")) # => imprime El gato victorioso dice rar -# El resultado puede ser diferente en otras versiones de Julia +#= +  Warning: New definition +      pelear(Gato,Leon) at none:1 +  is ambiguous with: +      pelear(Leon,Gato) at none:1. +  To fix, define +      pelear(Leon,Leon) +  before the new definition. +  pelear (generic function with 4 methods) +=# + +# Esta advertencia se debe a que no está claro que método de pelear +# será llamado en: +pelear(Leon("RAR"),Leon("cafe","rar"))    # El gato victorioso dice rar. +# El resultado puede ser diferente en otras versiones de Julia  pelear(l::Leon,l2::Leon) = println("Los leones llegan a un empate") -pelear(Leon("GR"),Leon("cafe","rar")) # => imprime Los leones llegan a un empate - - -# Un vistazo al nivel bajo -# Se puede echar un vistazo a la LLVM y el código ensamblador generado. - -area_cuadrada(l) = l * l      # area_cuadrada (generic function with 1 method) - -area_cuadrada(5) # => 25 - -# ¿Qué sucede cuando damos area_cuadrada diferentes argumentos? -code_native(area_cuadrada, (Int32,))   -	#	    .section    __TEXT,__text,regular,pure_instructions -	#	Filename: none -	#	Source line: 1              # Prologue -	#	    push    RBP -	#	    mov RBP, RSP -	#	Source line: 1 -	#	    movsxd  RAX, EDI        # Fetch l from memory? -	#	    imul    RAX, RAX        # Square l and store the result in RAX -	#	    pop RBP                 # Restore old base pointer -	#	    ret                     # Result will still be in RAX - -code_native(area_cuadrada, (Float32,)) -	#	    .section    __TEXT,__text,regular,pure_instructions -	#	Filename: none -	#	Source line: 1 -	#	    push    RBP -	#	    mov RBP, RSP -	#	Source line: 1 -	#	    vmulss  XMM0, XMM0, XMM0  # Scalar single precision multiply (AVX) -	#	    pop RBP -	#	    ret - -code_native(area_cuadrada, (Float64,)) -	#	    .section    __TEXT,__text,regular,pure_instructions -	#	Filename: none -	#	Source line: 1 -	#	    push    RBP -	#	    mov RBP, RSP -	#	Source line: 1 -	#	    vmulsd  XMM0, XMM0, XMM0 # Scalar double precision multiply (AVX) -	#	    pop RBP -	#	    ret -	#	 - -# Ten en cuenta que Julia usará instrucciones de "floating point" si alguno de -# los argumentos son "floats" -# Vamos a calcular el área de un círculo -area_circulo(r) = pi * r * r     # circle_area (generic function with 1 method) -area_circulo(5)                  # 78.53981633974483 + +pelear(Leon("GR"),Leon("cafe","rar"))    # Los leones llegan a un empate + + +################################ +# 7. Un vistazo de bajo nivel. # +################################ + +# Se puede echar un vistazo al código IR de LLVM y al código +# ensamblador generado. +area_cuadrado(l) = l * l    # => area_cuadrado (generic function with 1 method) + +area_cuadrado(5)    # => 25 + +# ¿Qué sucede cuando damos area_cuadrada diferentes tipos de argumentos? +code_native(area_cuadrado, (Int32,)) +#= +    .section  __TEXT,__text,regular,pure_instructions +  Filename: none +  Source line: 1      # prólogo +    push  RBP +    mov RBP, RSP +  Source line: 1 +    imul  RDI, RDI    # elevar l al cuadrado +    mov RAX, RDI      # almacenar el resultado en RAX +    pop RBP           # restaurar el puntero base anterior +    ret               # el resultado estará en RAX +=# + +code_native(area_cuadrado, (Float32,)) +#= +    .section  __TEXT,__text,regular,pure_instructions +  Filename: none +  Source line: 1 +    push  RBP +    mov RBP, RSP +  Source line: 1 +    mulss XMM0, XMM0    # multiplicación escalar de presición simple (AVX) +    pop RBP +    ret +=# + +code_native(area_cuadrado, (Float64,)) +#= +    .section  __TEXT,__text,regular,pure_instructions +  Filename: none +  Source line: 1 +    push  RBP +    mov RBP, RSP +  Source line: 1 +    mulsd XMM0, XMM0    # multiplicación escalar de presición doble (AVX) +    pop RBP +    ret +=# + +# Ten en cuenta que Julia usará instrucciones de punto flotante si el tipo de +# alguno de los argumentos es flotante. + +# Vamos a calcular el área de un círculo. +area_circulo(r) = π * r * r    # area_circulo (generic function with 1 method) +area_circulo(5)                # 78.53981633974483  code_native(area_circulo, (Int32,)) -	#	    .section    __TEXT,__text,regular,pure_instructions -	#	Filename: none -	#	Source line: 1 -	#	    push    RBP -	#	    mov RBP, RSP -	#	Source line: 1 -	#	    vcvtsi2sd   XMM0, XMM0, EDI          # Load integer (r) from memory -	#	    movabs  RAX, 4593140240              # Load pi -	#	    vmulsd  XMM1, XMM0, QWORD PTR [RAX]  # pi * r -	#	    vmulsd  XMM0, XMM0, XMM1             # (pi * r) * r -	#	    pop RBP -	#	    ret -	# +#= +    .section  __TEXT,__text,regular,pure_instructions +  Filename: none +  Source line: 1 +    push  RBP +    mov RBP, RSP +  Source line: 1 +    cvtsi2sd  XMM1, EDI            # cargar entero r de la memoria +    movabs  RAX, 4477117456        # cargar constante matemática π +    movsd XMM0, QWORD PTR [RAX] +    mulsd XMM0, XMM1               # π * r +    mulsd XMM0, XMM1               # (π * r) * r +    pop RBP +    ret +=#  code_native(area_circulo, (Float64,)) -	#	    .section    __TEXT,__text,regular,pure_instructions -	#	Filename: none -	#	Source line: 1 -	#	    push    RBP -	#	    mov RBP, RSP -	#	    movabs  RAX, 4593140496 -	#	Source line: 1 -	#	    vmulsd  XMM1, XMM0, QWORD PTR [RAX] -	#	    vmulsd  XMM0, XMM1, XMM0 -	#	    pop RBP -	#	    ret -	#	 +#= +    .section  __TEXT,__text,regular,pure_instructions +  Filename: none +  Source line: 1 +    push  RBP +    mov RBP, RSP +    movabs  RAX, 4477120336 +    movsd XMM1, QWORD PTR [RAX] +  Source line: 1 +    mulsd XMM1, XMM0 +    mulsd XMM1, XMM0 +    movaps  XMM0, XMM1 +    pop RBP +    ret +=#  ``` -## ¿Listo para más? + -Puedes obtener muchos más detalles en [The Julia Manual](http://docs.julialang.org/en/latest/manual/) +## ¿Listo para más? -El mejor lugar para obtener ayuda con Julia es el (muy amable) [lista de correos](https://groups.google.com/forum/#!forum/julia-users). +Para más detalles, lee el [manual de Julia](http://docs.julialang.org/en/release-0.3). +El mejor lugar para obtener ayuda con Julia, es en su amigable [lista de correos](https://groups.google.com/forum/#!forum/julia-users). diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown index f7a0ec02..4930eebc 100644 --- a/es-es/python-es.html.markdown +++ b/es-es/python-es.html.markdown @@ -4,6 +4,7 @@ contributors:      - ["Louie Dinh", "http://ldinh.ca"]  translators:      - ["Camilo Garrido", "http://www.twitter.com/hirohope"] +    - ["Fabio Souto", "http://fabiosouto.me"]  lang: es-es  filename: learnpython-es.py  --- @@ -30,27 +31,47 @@ Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser apl  # Tienes números  3 #=> 3 -# Matemática es lo que esperarías -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 +# Evidentemente puedes realizar operaciones matemáticas +1 + 1  #=> 2 +8 - 1  #=> 7 +10 * 2  #=> 20 +35 / 5  #=> 7  # La división es un poco complicada. Es división entera y toma la parte entera  # de los resultados automáticamente. -5 / 2 #=> 2 +5 / 2  #=> 2  # Para arreglar la división necesitamos aprender sobre 'floats'  # (números de coma flotante).  2.0     # Esto es un 'float' -11.0 / 4.0 #=> 2.75 ahhh...mucho mejor +11.0 / 4.0  #=> 2.75 ahhh...mucho mejor + +# Resultado de la división de enteros truncada para positivos y negativos +5 // 3     # => 1 +5.0 // 3.0 # => 1.0 # funciona con números en coma flotante +-5 // 3  # => -2 +-5.0 // 3.0 # => -2.0 + +# El operador módulo devuelve el resto de una división entre enteros +7 % 3 # => 1 + +# Exponenciación (x elevado a y) +2**4 # => 16  # Refuerza la precedencia con paréntesis -(1 + 3) * 2 #=> 8 +(1 + 3) * 2  #=> 8 + +# Operadores booleanos +# Nota: "and" y "or" son sensibles a mayúsculas +True and False #=> False +False or True #=> True -# Valores 'boolean' (booleanos) son primitivos -True -False +# Podemos usar operadores booleanos con números enteros +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True  # Niega con 'not'  not True #=> False @@ -90,7 +111,7 @@ not False #=> True  # Una forma más reciente de formatear strings es el método 'format'.  # Este método es la forma preferida  "{0} pueden ser {1}".format("strings", "formateados") -# Puedes usar palabras claves si no quieres contar. +# Puedes usar palabras clave si no quieres contar.  "{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña")  # None es un objeto @@ -107,8 +128,8 @@ None is None  #=> True  # None, 0, y strings/listas vacíos(as) todas se evalúan como False.  # Todos los otros valores son True -0 == False  #=> True -"" == False #=> True +bool(0) #=> False +bool("") #=> False  #################################################### @@ -130,16 +151,16 @@ otra_variable  # Levanta un error de nombre  # 'if' puede ser usado como una expresión  "yahoo!" if 3 > 2 else 2 #=> "yahoo!" -# Listas almacenan secuencias +# Las listas almacenan secuencias  lista = []  # Puedes empezar con una lista prellenada  otra_lista = [4, 5, 6]  # Añadir cosas al final de una lista con 'append' -lista.append(1)    #lista ahora es [1] -lista.append(2)    #lista ahora es [1, 2] -lista.append(4)    #lista ahora es [1, 2, 4] -lista.append(3)    #lista ahora es [1, 2, 4, 3] +lista.append(1)    # lista ahora es [1] +lista.append(2)    # lista ahora es [1, 2] +lista.append(4)    # lista ahora es [1, 2, 4] +lista.append(3)    # lista ahora es [1, 2, 4, 3]  # Remueve del final de la lista con 'pop'  lista.pop()        #=> 3 y lista ahora es [1, 2, 4]  # Pongámoslo de vuelta @@ -173,11 +194,11 @@ lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6]  # Chequea la existencia en una lista con  1 in lista #=> True -# Examina el largo de una lista con 'len' +# Examina el tamaño de una lista con 'len'  len(lista) #=> 6 -# Tuplas son como listas pero son inmutables. +# Las tuplas son como las listas, pero son inmutables.  tupla = (1, 2, 3)  tupla[0] #=> 1  tupla[0] = 3  # Levanta un error TypeError @@ -266,7 +287,7 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6}  # Hagamos sólo una variable  una_variable = 5 -# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python! +# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python!  # imprime "una_variable es menor que 10"  if una_variable > 10:      print "una_variable es completamente mas grande que 10." @@ -400,12 +421,12 @@ class Humano(object):      # Un atributo de clase es compartido por todas las instancias de esta clase      especie = "H. sapiens" -    # Constructor basico +    # Constructor básico, se llama al instanciar la clase.      def __init__(self, nombre):          # Asigna el argumento al atributo nombre de la instancia          self.nombre = nombre -    # Un metodo de instancia. Todos los metodos toman self como primer argumento +    # Un método de instancia. Todos los metodos toman self como primer argumento      def decir(self, msg):         return "%s: %s" % (self.nombre, msg) @@ -470,6 +491,56 @@ import math  dir(math) +#################################################### +## 7. Avanzado +#################################################### + +# Los generadores permiten evaluación perezosa +def duplicar_numeros(iterable): +    for i in iterable: +        yield i + i + +# Un generador crea valores sobre la marcha +# En vez de generar y devolver todos los valores de una vez, crea un valor +# en cada iteración. En este ejemplo los valores mayores que 15 no serán  +# procesados en duplicar_numeros. +# Nota: xrange es un generador que hace lo mismo que range. +# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio. +# xrange crea un generador, mientras que range crea toda la lista. +# Añadimos un guion bajo a los nombres de variable que coinciden con palabras  +# reservadas de python. +xrange_ = xrange(1, 900000000) + +# duplica todos los números hasta que encuentra un resultado >= 30 +for i in duplicar_numeros(xrange_): +    print i +    if i >= 30: +        break + +# Decoradores +# en este ejemplo pedir rodea a hablar +# Si por_favor es True se cambiará el mensaje. +from functools import wraps + + +def pedir(target_function): +    @wraps(target_function) +    def wrapper(*args, **kwargs): +        msg, por_favor = target_function(*args, **kwargs) +        if por_favor: +            return "{} {}".format(msg, "¡Por favor! Soy pobre :(") +        return msg + +    return wrapper + + +@pedir +def hablar(por_favor=False): +    msg = "¿Me puedes comprar una cerveza?" +    return msg, por_favor + +print hablar()  # ¿Me puedes comprar una cerveza? +print hablar(por_favor=True)  # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :(  ```  ## ¿Listo para más? @@ -481,6 +552,7 @@ dir(math)  * [The Official Docs](http://docs.python.org/2.6/)  * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)  * [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)  ### Encuadernados | 
