diff options
Diffstat (limited to 'es-es')
-rw-r--r-- | es-es/c++-es.html.markdown | 829 | ||||
-rw-r--r-- | es-es/git-es.html.markdown | 64 | ||||
-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 |
6 files changed, 2057 insertions, 851 deletions
diff --git a/es-es/c++-es.html.markdown b/es-es/c++-es.html.markdown new file mode 100644 index 00000000..bcc775e5 --- /dev/null +++ b/es-es/c++-es.html.markdown @@ -0,0 +1,829 @@ +--- +language: c++ +filename: learncpp.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] + - ["Geoff Liu", "http://geoffliu.me"] + - ["Connor Waters", "http://github.com/connorwaters"] +translators: + - ["Gerson Lázaro", "https://gersonlazaro.com"] +lang: es-es +--- + +C++ es un lenguaje de programación de sistemas que, +[de acuerdo a su inventor Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), +fue diseñado para + +- ser un "mejor C" +- soportar abstracción de datos +- soportar programación orientada a objetos +- soportar programación genérica + +Aunque su sintaxis puede ser más difícil o compleja que los nuevos lenguajes, +es ampliamente utilizado, ya que compila instrucciones nativas que pueden ser +directamente ejecutadas por el procesador y ofrece un estricto control sobre +el hardware (como C), mientras ofrece características de alto nivel como +genericidad, excepciones, y clases. Esta combinación de velocidad y +funcionalidad hace de C ++ uno de los lenguajes de programación más utilizados. + +```c++ +//////////////////// +// Comparación con C +//////////////////// + +// C ++ es _casi_ un superconjunto de C y comparte su sintaxis básica para las +// declaraciones de variables, tipos primitivos y funciones. + +// Al igual que en C, el punto de entrada de tu programa es una función llamada +// main con un retorno de tipo entero. +// Este valor sirve como código de salida del programa. +// Mira http://en.wikipedia.org/wiki/Exit_status para mayor información. +int main(int argc, char** argv) +{ + // Los argumentos de la línea de comandos se pasan por argc y argv de la + // misma manera que en C. + // argc indica el número de argumentos, + // y argv es un arreglo de strings de estilo C (char*) + // representando los argumentos. + // El primer argumento es el nombre con el que el programa es llamado. + // argc y argv pueden omitirse si no te preocupan los argumentos, + // dejando la definición de la función como int main () + + // Un estado de salida 0 indica éxito. + return 0; +} + +// Sin embargo, C ++ varía en algunas de las siguientes maneras: + +// En C++, los caracteres literales son caracteres +sizeof('c') == sizeof(char) == 1 + +// En C, los caracteres literales son enteros +sizeof('c') == sizeof(int) + + +// C++ tiene prototipado estricto +void func(); // función que no acepta argumentos + +// En C +void func(); // función que puede aceptar cualquier número de argumentos + +// Use nullptr en lugar de NULL en C++ +int* ip = nullptr; + +// Las cabeceras (headers) estándar de C están disponibles en C ++, +// pero tienen el prefijo "c" y no tienen sufijo .h. +#include <cstdio> + +int main() +{ + printf("Hola mundo!\n"); + return 0; +} + +////////////////////////// +// Sobrecarga de funciones +////////////////////////// + +// C++ soporta sobrecarga de funciones +// siempre que cada función tenga diferentes parámetros. + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("Mi entero es %d", myInt); +} + +int main() +{ + print("Hello"); // Resolves to void print(const char*) + print(15); // Resolves to void print(int) +} + +//////////////////////////////////// +// Argumentos de función por defecto +//////////////////////////////////// + +// Puedes proporcionar argumentos por defecto para una función si no son +// proporcionados por quien la llama. + +void doSomethingWithInts(int a = 1, int b = 4) +{ + // Hacer algo con los enteros aqui +} + +int main() +{ + doSomethingWithInts(); // a = 1, b = 4 + doSomethingWithInts(20); // a = 20, b = 4 + doSomethingWithInts(20, 5); // a = 20, b = 5 +} + +// Los argumentos predeterminados deben estar al final de la lista de argumentos. + +void invalidDeclaration(int a = 1, int b) // Error! +{ +} + +///////////////////// +// Espacios de nombre +///////////////////// + +// Espacios de nombres proporcionan ámbitos separados para variable, función y +// otras declaraciones. +// Los espacios de nombres se pueden anidar. + +namespace First { + namespace Nested { + void foo() + { + printf("Esto es First::Nested::foo\n"); + } + } // fin del nombre de espacio Nested +} // fin del nombre de espacio First + +namespace Second { + void foo() + { + printf("Esto es Second::foo\n") + } +} + +void foo() +{ + printf("Este es global: foo\n"); +} + +int main() +{ + + // Incluye todos los símbolos del espacio de nombre Second en el ámbito + // actual. Tenga en cuenta que simplemente foo() no funciona, ya que ahora + // es ambigua si estamos llamando a foo en espacio de nombres Second o en + // el nivel superior. + using namespace Second; + + Second::foo(); // imprime "Esto es Second::foo" + First::Nested::foo(); // imprime "Esto es First::Nested::foo" + ::foo(); // imprime "Este es global: foo" +} + +///////////////// +// Entrada/Salida +///////////////// + +// La entrada y salida de C++ utiliza flujos (streams) +// cin, cout, y cerr representan a stdin, stdout, y stderr. +// << es el operador de inserción >> es el operador de extracción. + + +#include <iostream> // Incluir para el flujo de entrada/salida + +using namespace std; // Los streams estan en std namespace (libreria estandar) + +int main() +{ + int myInt; + + // Imprime a la stdout (o terminal/pantalla) + cout << "Ingresa tu número favorito:\n"; + // Toma una entrada + cin >> myInt; + + // cout puede también ser formateado + cout << "Tu número favorito es " << myInt << "\n"; + // imprime "Tu número favorito es <myInt>" + + cerr << "Usado para mensajes de error"; +} +//////////////////// +// Cadenas (Strings) +//////////////////// + +// Las cadenas en C++ son objetos y tienen muchas funciones +#include <string> + +using namespace std; // Strings también estan en namespace std + +string myString = "Hola"; +string myOtherString = " Mundo"; + +// + es usado para concatenar. +cout << myString + myOtherString; // "Hola Mundo" + +cout << myString + " Tu"; // "Hola Tu" + +// Las cadenas en C++ son mutables y tienen valor semántico. +myString.append(" Perro"); +cout << myString; // "Hola Perro" + + +////////////// +// Referencias +////////////// + +// Además de punteros como los de C, +// C++ tiene _references_. +// Estos tipos de puntero no pueden ser reasignados una vez establecidos +// Y no pueden ser nulos. +// También tienen la misma sintaxis que la propia variable: +// No es necesaria * para eliminar la referencia y +// & (dirección) no se utiliza para la asignación. + +using namespace std; + +string foo = "Yo soy foo"; +string bar = "Yo soy bar"; + +string& fooRef = foo; // Crea una referencia a foo. +fooRef += ". Hola!"; // Modifica foo través de la referencia +cout << fooRef; // Imprime "Yo soy foo. Hola!" + +// No trate de reasignar "fooRef". Esto es lo mismo que "foo = bar", y +// foo == "Yo soy bar" +// después de esta linea. +fooRef = bar; + +const string& barRef = bar; // Crea una referencia constante a bar. +// Como en C, los valores constantes (y punteros y referencias) no pueden ser +// modificados. +barRef += ". Hola!"; // Error, referencia constante no puede ser modificada. + +// Sidetrack: Antes de hablar más sobre referencias, hay que introducir un +// concepto llamado objeto temporal. Supongamos que tenemos el siguiente código: +string tempObjectFun() { ... } +string retVal = tempObjectFun(); + +// Lo que pasa en la segunda línea es en realidad: +// - Un objeto de cadena es retornado desde tempObjectFun +// - Una nueva cadena se construye con el objeto devuelto como argumento al +// constructor +// - El objeto devuelto es destruido +// El objeto devuelto se llama objeto temporal. Objetos temporales son +// creados cada vez que una función devuelve un objeto, y es destruido en el +// fin de la evaluación de la expresión que encierra (Bueno, esto es lo que la +// norma dice, pero los compiladores están autorizados a cambiar este +// comportamiento. Busca "return value optimization" para ver mas detalles). +// Así que en este código: +foo(bar(tempObjectFun())) + +// Suponiendo que foo y bar existen, el objeto retornado de tempObjectFun es +// pasado al bar, y se destruye antes de llamar foo. + +// Ahora, de vuelta a las referencias. La excepción a la regla "en el extremo +// de la expresión encerrada" es si un objeto temporal se une a una +// referencia constante, en cuyo caso su vida se extiende al ámbito actual: + +void constReferenceTempObjectFun() { + // ConstRef obtiene el objeto temporal, y es válido hasta el final de esta + // función. + const string& constRef = tempObjectFun(); + ... +} + +// Otro tipo de referencia introducida en C ++ 11 es específicamente para +// objetos temporales. No se puede tener una variable de este tipo, pero tiene +// prioridad en resolución de sobrecarga: + +void someFun(string& s) { ... } // Referencia regular +void someFun(string&& s) { ... } // Referencia a objeto temporal + +string foo; +someFun(foo); // Llama la función con referencia regular +someFun(tempObjectFun()); // Llama la versión con referencia temporal + +// Por ejemplo, puedes ver estas dos versiones de constructores para +// std::basic_string: +basic_string(const basic_string& other); +basic_string(basic_string&& other); + +// La idea es que si estamos construyendo una nueva cadena de un objeto temporal +// (que va a ser destruido pronto de todos modos), podemos tener un constructor +// mas eficiente que "rescata" partes de esa cadena temporal. Usted verá este +// Concepto denominado "movimiento semántico". + +//////////////////////////////////////////// +// Clases y programación orientada a objetos +//////////////////////////////////////////// + +// Primer ejemplo de clases +#include <iostream> + +// Declara una clase. +// Las clases son usualmente declaradas en archivos de cabeceras (.h o .hpp) +class Dog { + // Variables y funciones de la clase son privados por defecto. + std::string name; + int weight; + +// Todos los miembros siguientes de este son públicos +// Hasta que se encuentre "private" o "protected". +// All members following this are public +// until "private:" or "protected:" is found. +public: + + // Constructor por defecto + Dog(); + + // Declaraciones de funciones de la clase (implementaciones a seguir) + // Nota que usamos std::string aquí en lugar de colocar + // using namespace std; + // arriba. + // Nunca ponga una declaración "using namespace" en un encabezado. + void setName(const std::string& dogsName); + + void setWeight(int dogsWeight); + // Funciones que no modifican el estado del objeto + // Deben marcarse como const. + // Esto le permite llamarlas si se envia una referencia constante al objeto. + // También tenga en cuenta que las funciones deben ser declaradas + // explícitamente como _virtual_ para que sea reemplazada en las clases + // derivadas. + // Las funciones no son virtuales por defecto por razones de rendimiento. + virtual void print() const; + + // Las funciones también se pueden definir en el interior + // del cuerpo de la clase. + // Funciones definidas como tales están entre líneas automáticamente. + void bark() const { std::cout << name << " barks!\n"; } + + // Junto a los constructores, C++ proporciona destructores. + // Estos son llamados cuando un objeto se elimina o está fuera del ámbito. + // Esto permite paradigmas potentes como RAII + // (mira abajo) + // El destructor debe ser virtual si una clase es dervada desde el; + // Si no es virtual, entonces la clase derivada destructor + // No será llamada si el objeto se destruye a través de una referencia de + // la clase base o puntero. + virtual ~Dog(); + + + +}; // Un punto y coma debe seguir la definición de clase. + +// Las funciones de una clase son normalmente implementados en archivos .cpp. +Dog::Dog() +{ + std::cout << "Un perro ha sido construido\n"; +} + +// Objetos (tales como cadenas) deben ser pasados por referencia +// Si los estas modificando o referencia constante en caso contrario. +void Dog::setName(const std::string& dogsName) +{ + name = dogsName; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// Nota que "virtual" sólo se necesita en la declaración, no en la definición. +void Dog::print() const +{ + std::cout << "El perro es " << name << " y pesa " << weight << "kg\n"; +} + +Dog::~Dog() +{ + cout << "Adiós " << name << "\n"; +} + +int main() { + Dog myDog; // imprime "Un perro ha sido construido" + myDog.setName("Barkley"); + myDog.setWeight(10); + myDog.print(); // imprime "El perro es Barkley y pesa 10 kg" + return 0; +} // imprime "Adiós Barkley" + +// Herencia: + +// Esta clase hereda todo lo público y protegido de la clase Dog +class OwnedDog : public Dog { + + void setOwner(const std::string& dogsOwner); + + // Reemplaza el comportamiento de la función de impresión + // de todos los OwnedDogs. Mira + // http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping + // Para una introducción más general si no está familiarizado con el + // polimorfismo de subtipo. + // La palabra clave override es opcional, pero asegura que estás + // reemplazando el método de una clase base. + void print() const override; + +private: + std::string owner; +}; + +// Mientras tanto, en el archivo .cpp correspondiente: + +void OwnedDog::setOwner(const std::string& dogsOwner) +{ + owner = dogsOwner; +} + +void OwnedDog::print() const +{ + Dog::print(); // Llama a la función de impresión en la clase base Dog + std::cout << "El perro es de " << owner << "\n"; + // Imprime "El perro es <name> y pesa <weight>" + // "El perro es de <owner>" +} + +//////////////////////////////////////////// +// Inicialización y sobrecarga de operadores +//////////////////////////////////////////// + +// En C ++ se puede sobrecargar el comportamiento +// de los operadores como +, -, *, /, etc. +// Esto se hace mediante la definición de una función que es llamada +// cada vez que se utiliza el operador. + +#include <iostream> +using namespace std; + +class Point { +public: + // Las variables de la clase pueden dar valores por defecto de esta manera. + double x = 0; + double y = 0; + + // Define un constructor por defecto que no hace nada + // pero inicializa el punto al valor por defecto (0, 0) + Point() { }; + + // The following syntax is known as an initialization list + // and is the proper way to initialize class member values + Point (double a, double b) : + x(a), + y(b) + { /* No hace nada excepto inicializar los valores */ } + + // Sobrecarga el operador + + Point operator+(const Point& rhs) const; + + // Sobrecarga el operador += + Point& operator+=(const Point& rhs); + + // También tendría sentido añadir los operadores - y -=, + // Pero vamos a omitirlos por razones de brevedad. +}; + +Point Point::operator+(const Point& rhs) const +{ + // Crea un nuevo punto que es la suma de este y rhs. + return Point(x + rhs.x, y + rhs.y); +} + +Point& Point::operator+=(const Point& rhs) +{ + x += rhs.x; + y += rhs.y; + return *this; +} + +int main () { + Point up (0,1); + Point right (1,0); + // Llama al operador + de Point + // Point llama la función + con right como parámetro + Point result = up + right; + // Prints "Result is upright (1,1)" + cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; + return 0; +} + +///////////////////////// +// Plantillas (Templates) +///////////////////////// + +// Las plantillas en C++ se utilizan sobre todo en la programación genérica, +// a pesar de que son mucho más poderoso que los constructores genéricos +// en otros lenguajes. Ellos también soportan especialización explícita y +// parcial y clases de tipo estilo funcional; de hecho, son un lenguaje +// funcional Turing-completo incrustado en C ++! + +// Empezamos con el tipo de programación genérica que podría estar +// familiarizado. +// Para definir una clase o función que toma un parámetro de tipo: +template<class T> +class Box { +public: + // En este caso, T puede ser usado como cualquier otro tipo. + void insert(const T&) { ... } +}; + +// Durante la compilación, el compilador realmente genera copias de cada +// plantilla con parámetros sustituidos, por lo que la definición completa +// de la clase debe estar presente en cada invocación. +// Es por esto que usted verá clases de plantilla definidas +// Enteramente en archivos de cabecera. + +//Para crear una instancia de una clase de plantilla en la pila: +Box<int> intBox; + +y puedes utilizarlo como era de esperar: +intBox.insert(123); + +// Puedes, por supuesto, anidar plantillas: +Box<Box<int> > boxOfBox; +boxOfBox.insert(intBox); + +// Hasta C++11, había que colocar un espacio entre los dos '>'s, +// de lo contrario '>>' serían analizados como el operador de desplazamiento +// a la derecha. + + +// A veces verás +// template<typename T> +// en su lugar. La palabra clave "class" y las palabras clave "typename" son +// mayormente intercambiables en este caso. Para la explicación completa, mira +// http://en.wikipedia.org/wiki/Typename +// (sí, esa palabra clave tiene su propia página de Wikipedia). + +// Del mismo modo, una plantilla de función: +template<class T> +void barkThreeTimes(const T& input) +{ + input.bark(); + input.bark(); + input.bark(); +} + +// Observe que no se especifica nada acerca de los tipos de parámetros aquí. +// El compilador generará y comprobará cada invocación de la plantilla, +// por lo que la función anterior funciona con cualquier tipo "T" +// que tenga un método 'bark' constante! + + +Dog fluffy; +fluffy.setName("Fluffy") +barkThreeTimes(fluffy); // Imprime "Fluffy barks" 3 veces. + +Los parámetros de la plantilla no tienen que ser las clases: +template<int Y> +void printMessage() { + cout << "Aprende C++ en " << Y << " minutos!" << endl; +} + +// Y usted puede especializar explícitamente plantillas +// para código más eficiente. +// Por supuesto, la mayor parte del mundo real que utiliza una especialización +// no son tan triviales como esta. +// Tenga en cuenta que usted todavía tiene que declarar la función (o clase) +// como plantilla incluso si ha especificado de forma explícita todos +// los parámetros. + +template<> +void printMessage<10>() { + cout << "Aprende C++ rapido en solo 10 minutos!" << endl; +} + +printMessage<20>(); // Prints "Aprende C++ en 20 minutos!" +printMessage<10>(); // Prints "Aprende C++ rapido en solo 10 minutos!" + + +///////////////////// +// Manejador de excepciones +///////////////////// + +// La biblioteca estándar proporciona algunos tipos de excepción +// (mira http://en.cppreference.com/w/cpp/error/exception) +// pero cualquier tipo puede ser lanzado como una excepción +#include <exception> +#include <stdexcept> + +//Todas las excepciones lanzadas dentro del bloque _try_ pueden ser +// capturados por los siguientes manejadores _catch_. +try { + // No asignar excepciones en el heap usando _new_. + throw std::runtime_error("Ocurrió un problema"); +} + +// Captura excepciones por referencia const si son objetos +catch (const std::exception& ex) +{ + std::cout << ex.what(); +} +******************************************************************************** +// Captura cualquier excepción no capturada por bloques _catch_ anteriores +catch (...) +{ + std::cout << "Excepción desconocida capturada"; + throw; // Re-lanza la excepción +} + +/////// +// RAII +/////// + +// RAII significa "Resource Acquisition Is Initialization" +// (Adquisición de recursos es inicialización). +// A menudo se considera el paradigma más poderoso en C++ +// Y el concepto es simple: un constructor de un objeto +// Adquiere recursos de ese objeto y el destructor les libera. + +// Para entender cómo esto es útil, +// Considere una función que utiliza un identificador de archivo C: +void doSomethingWithAFile(const char* filename) +{ + // Para empezar, asuma que nada puede fallar. + + FILE* fh = fopen(filename, "r"); // Abre el archivo en modo lectura + + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + + fclose(fh); // Cierra el manejador de archivos +} + +// Por desgracia, las cosas se complican rápidamente por el control de errores. +// Supongamos que fopen puede fallar, y que doSomethingWithTheFile y +// DoSomethingElseWithIt retornan códigos de error si fallan. +// (Excepciones son la mejor forma de manejar los fallos, +// pero algunos programadores, especialmente los que tienen un fondo C, +// estan en desacuerdo sobre la utilidad de las excepciones). +// Ahora tenemos que comprobar cada llamado por fallos y cerrar el manejador +// del archivo si se ha producido un problema. +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // Abre el archivo en modo lectura + if (fh == nullptr) // El puntero retornado es nulo o falla. + return false; // Reporta el fallo a quien hizo el llamado. + + // Asume que cada función retorna falso si falla + if (!doSomethingWithTheFile(fh)) { + fclose(fh); // Cierre el manejador de archivo para que no se filtre. + return false; // Propaga el error. + } + if (!doSomethingElseWithIt(fh)) { + fclose(fh); // Cierre el manejador de archivo para que no se filtre. + return false; // Propaga el error. + } + + fclose(fh); // Cierre el archivo. + return true; // Indica que todo funcionó correctamente. +} + +// Programadores C suelen limpiar esto un poco usando goto: +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); + if (fh == nullptr) + return false; + + if (!doSomethingWithTheFile(fh)) + goto failure; + + if (!doSomethingElseWithIt(fh)) + goto failure; + + fclose(fh); // Cierre el archivo. + return true; // Indica que todo funcionó correctamente. + +failure: + fclose(fh); + return false; // Propagate el error +} + +// Si las funciones indican errores mediante excepciones, +// Las cosas son un poco más claras, pero pueden optimizarse mas. +void doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // Abrir el archivo en modo lectura + if (fh == nullptr) + throw std::runtime_error("No puede abrirse el archivo."); + + try { + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + } + catch (...) { + fclose(fh); // Asegúrese de cerrar el archivo si se produce un error. + throw; // Luego vuelve a lanzar la excepción. + } + + fclose(fh); // Cierra el archivo +} + +// Compare esto con el uso de la clase de flujo de archivos de C++ (fstream) +// fstream utiliza su destructor para cerrar el archivo. +// Los destructores son llamados automáticamente +// cuando un objeto queda fuera del ámbito. +void doSomethingWithAFile(const std::string& filename) +{ + // ifstream es la abreviatura de el input file stream + std::ifstream fh(filename); // Abre el archivo + + // Hacer algo con el archivo + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + +} // El archivo se cierra automáticamente aquí por el destructor + + +// Esto tiene ventajas _enormes_: +// 1. No importa lo que pase, +// El recurso (en este caso el manejador de archivo) será limpiado. +// Una vez que escribes el destructor correctamente, +// Es _imposible_ olvidar cerrar el identificador y permitir +// fugas del recurso. +// 2. Tenga en cuenta que el código es mucho más limpio. +// El destructor se encarga de cerrar el archivo detrás de cámaras +// Sin que tenga que preocuparse por ello. +// 3. El código es seguro. +// Una excepción puede ser lanzado en cualquier lugar de la función +// y la limpieza ocurrirá. + +// Todo el código idiomático C++ utiliza RAII ampliamente para todos los +// recursos. +// Otros ejemplos incluyen +// - Memoria usando unique_ptr y shared_ptr +// - Contenedores (Containers) - la biblioteca estándar linked list, +// vector (es decir, array con auto-cambio de tamaño), hash maps, etc. +// Destruimos todos sus contenidos de forma automática +// cuando quedan fuera del ámbito. +// - Mutex utilizando lock_guard y unique_lock + + +///////////////////// +// Cosas divertidas +///////////////////// + +// Aspectos de C ++ que pueden sorprender a los recién llegados +// (e incluso algunos veteranos). +// Esta sección es, por desgracia, salvajemente incompleta; +// C++ es uno de los lenguajes con los que mas facil te disparas en el pie. + +// Tu puedes sobreescribir métodos privados! +class Foo { + virtual void bar(); +}; +class FooSub : public Foo { + virtual void bar(); // Sobreescribe Foo::bar! +}; + + +// 0 == false == NULL (La mayoria de las veces)! +bool* pt = new bool; +*pt = 0; // Establece los puntos de valor de 'pt' en falso. +pt = 0; // Establece 'pt' al apuntador nulo. Ambas lineas compilan sin error. + +// nullptr se supone que arregla un poco de ese tema: +int* pt2 = new int; +*pt2 = nullptr; // No compila +pt2 = nullptr; // Establece pt2 como null. + +// Hay una excepción para los valores bool. +// Esto es para permitir poner a prueba punteros nulos con if (!ptr), +// pero como consecuencia se puede asignar nullptr a un bool directamente! +*pt = nullptr; // Esto todavía compila, a pesar de que '*pt' es un bool! + +// '=' != '=' != '='! +// Llama Foo::Foo(const Foo&) o alguna variante (mira movimientos semanticos) +// copia del constructor. +Foo f2; +Foo f1 = f2; + +// Llama Foo::Foo(const Foo&) o variante, pero solo copia el 'Foo' parte de +// 'fooSub'. Cualquier miembro extra de 'fooSub' se descarta. Este +// comportamiento horrible se llama "Corte de objetos." +FooSub fooSub; +Foo f1 = fooSub; + +// Llama a Foo::operator=(Foo&) o variantes. +Foo f1; +f1 = f2; + + +// Cómo borrar realmente un contenedor: +class Foo { ... }; +vector<Foo> v; +for (int i = 0; i < 10; ++i) + v.push_back(Foo()); +// La siguiente línea establece el tamaño de v en 0, +// pero los destructores no son llamados y los recursos no se liberan! + +v.empty(); +v.push_back(Foo()); // Nuevo valor se copia en el primer Foo que insertamos + +// En verdad destruye todos los valores en v. +// Consulta la sección acerca de los objetos temporales para la +// explicación de por qué esto funciona. +v.swap(vector<Foo>()); + +``` +Otras lecturas: + +Una referencia del lenguaje hasta a la fecha se puede encontrar en +<http://cppreference.com/w/cpp> + +Recursos adicionales se pueden encontrar en <http://cplusplus.com> diff --git a/es-es/git-es.html.markdown b/es-es/git-es.html.markdown index 73853a9d..51812447 100644 --- a/es-es/git-es.html.markdown +++ b/es-es/git-es.html.markdown @@ -11,15 +11,15 @@ lang: es-es --- Git es un sistema de control de versiones distribuido diseñado para manejar -cualquier tipo de proyecto ya sea largos o pequeños, con velocidad y eficiencia. +cualquier tipo de proyecto, ya sea largo o pequeño, con velocidad y eficiencia. Git realiza esto haciendo "snapshots" del proyecto, con ello permite versionar y administrar nuestro código fuente. ## Versionamiento, conceptos. -### Que es el control de versiones? -El control de versiones es un sistema que guarda todos los cambios realizados a +### Qué es el control de versiones? +El control de versiones es un sistema que guarda todos los cambios realizados en uno o varios archivos, a lo largo del tiempo. ### Versionamiento centralizado vs Versionamiento Distribuido. @@ -31,15 +31,15 @@ uno o varios archivos, a lo largo del tiempo. + El versionamiento distribuido no tiene una estructura definida, incluso se puede mantener el estilo de los repositorios SVN con git. -[Informacion adicional](http://git-scm.com/book/es/Empezando-Acerca-del-control-de-versiones) +[Información adicional](http://git-scm.com/book/es/Empezando-Acerca-del-control-de-versiones) -### Por que usar Git? +### Por qué usar Git? * Se puede trabajar sin conexion. * Colaborar con otros es sencillo!. -* Derivar, Crear ramas del proyecto (aka: Branching) es facil!. +* Derivar, Crear ramas del proyecto (aka: Branching) es fácil!. * Combinar (aka: Merging) -* Git es rapido. +* Git es rápido. * Git es flexible. ## Arquitectura de Git. @@ -48,10 +48,10 @@ uno o varios archivos, a lo largo del tiempo. Un repositorio es un conjunto de archivos, directorios, registros, cambios (aka: comits), y encabezados (aka: heads). Imagina que un repositorio es una clase, -y que sus atributos otorgan acceso al historial del elemento, ademas de otras +y que sus atributos otorgan acceso al historial del elemento, además de otras cosas. -Un repositorio esta compuesto por la carpeta .git y un "arbol de trabajo". +Un repositorio esta compuesto por la carpeta .git y un "árbol de trabajo". ### Directorio .git (componentes del repositorio) @@ -62,38 +62,38 @@ y mas. ### Directorio de trabajo (componentes del repositorio) -Es basicamente los directorios y archivos dentro del repositorio. La mayorioa de +Es basicamente los directorios y archivos dentro del repositorio. La mayoría de las veces se le llama "directorio de trabajo". -### Inidice (componentes del directorio .git) +### Índice (componentes del directorio .git) -El inidice es la area de inicio en git. Es basicamente la capa que separa el +El índice es el área de inicio en git. Es basicamente la capa que separa el directorio de trabajo, del repositorio en git. Esto otorga a los desarrolladores -mas poder sobre lo que envia y recibe en el repositorio. +mas poder sobre lo que envía y recibe en el repositorio. ### Commit (aka: cambios) Un commit es una captura de un conjunto de cambios, o modificaciones hechas en el directorio de trabajo. Por ejemplo, si se añaden 5 archivos, se remueven 2, -estos cambios se almacenaran en un commit (aka: captura). Este commit puede ser o +estos cambios se almacenarán en un commit (aka: captura). Este commit puede ser o no ser enviado (aka: "pusheado") hacia un repositorio. ### Branch (rama) -Un "branch", es escencialmente un apuntador hacia el ultimo commit (cambio -registrado) que se ha realizado. A medida que se realizan mas commits, este -apuntador se actualizara automaticamente hacia el ultimo commit. +Un "branch", es escencialmente un apuntador hacia el último commit (cambio +registrado) que se ha realizado. A medida que se realizan más commits, este +apuntador se actualizará automaticamente hacia el ultimo commit. ### "HEAD" y "head" (component of .git dir) "HEAD" es un apuntador hacia la rama (branch) que se esta utilizando. Un repositorio solo puede tener un HEAD activo. En cambio "head", es un apuntador a -cualquier commit realizado, un repositorio puede tener cualquier numero de +cualquier commit realizado, un repositorio puede tener cualquier número de "heads". ### conceptos - recursos. -* [Git para informaticos](http://eagain.net/articles/git-for-computer-scientists/) +* [Git para informáticos](http://eagain.net/articles/git-for-computer-scientists/) * [Git para diseñadores](http://hoth.entp.com/output/git_for_designers.html) @@ -102,8 +102,8 @@ cualquier commit realizado, un repositorio puede tener cualquier numero de ### init -Crear un repositorio de git vacio. Las configuraciones, informacion almacenada y -demas son almacenadas en el directorio ".git". +Crear un repositorio de git vacio. Las configuraciones, información almacenada y +demás son almacenadas en el directorio ".git". ```bash $ git init @@ -127,7 +127,7 @@ $ git config --global user.name "nombre" ### help -Otorga un accceso rapido a una guia extremadamente detallada de cada comando en +Otorga un accceso rápido a una guía extremadamente detallada de cada comando en git. O puede ser usada simplemente como un recordatorio de estos. ```bash @@ -146,7 +146,7 @@ $ git help init ### status -Muestra las diferencias entre el archivo indice y el commit al cual apunta el +Muestra las diferencias entre el archivo índice y el commit al cual apunta el HEAD actualmente. @@ -163,7 +163,7 @@ $ git help status Para añadir archivos al arbol (directorio, repositorio) de trabajo. Si no se utiliza `git add`, los nuevos archivos no se añadiran al arbol de trabajo, por -lo que no se incluiran en los commits (cambios). +lo que no se incluirán en los commits (cambios). ```bash # Añade un archivo en el directorio de trabajo actual. @@ -202,7 +202,7 @@ $ git branch master --edit-description ### checkout Actualiza todos los archivos en el directorio de trabajo para que sean igual que -las versiones almacenadas en el indice, o en un arbol de trabajo especificado. +las versiones almacenadas en el índice, o en un árbol de trabajo especificado. ```bash # Despachar un repositorio. - Por defecto la master branch. (la rama principal llamada 'master') @@ -215,8 +215,8 @@ $ git checkout -b jdei ### clone -Clona, o copia, una repo existente en un nuevo directorio. Tambien añada el -seguimiento hacia las ramas existentes del repo que ha sido clonada, lo que +Clona, o copia, un repositorio existente en un nuevo directorio. También añade el +seguimiento hacia las ramas existentes del repositorio que ha sido clonado, lo que permite subir (push) los archivos hacia una rama remota. ```bash @@ -226,8 +226,8 @@ $ git clone https://github.com/jquery/jquery.git ### commit -Almacena los cambios que almacenados en el indice en un nuevo "commit". Este -commit contiene los cambios hechos mas un resumen hecho por el desarrollador. +Almacena el contenido actual del índice en un nuevo "commit". Este +commit contiene los cambios hechos más un resumen proporcionado por el desarrollador. ```bash # commit with a message @@ -237,8 +237,8 @@ $ git commit -m "jedi anakin wil be - jedis.list" ### diff -Muestra las diferencias entre un archivo en el directorio de trabajo, el indice -y commits. +Muestra las diferencias entre un archivo en el directorio de trabajo, el índice +y los commits. ```bash # Muestra la diferencia entre un directorio de trabajo y el indice. @@ -253,7 +253,7 @@ $ git diff HEAD ### grep -Permite realizar una busqueda rapida en un repositorio. +Permite realizar una busqueda rápida en un repositorio. Configuracion opcionales: 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..e4181609 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. +![JuliaLang](http://s13.postimg.org/z89djuwyf/julia_small.png) -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. + +### ¡Prueba Julia ahora mismo! + +* [TryJupyter](https://try.jupyter.org) +* [JuliaBox](https://juliabox.org) +* [SageMathCloud](https://cloud.sagemath.com) + +### Resumen de Características: -# Comentarios de una línea comienzan con una almohadilla (o signo gato) +* [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`. + +```ruby +# Los comentarios de una línea comienzan con una almohadilla (o signo de gato). -#= Commentarios multilinea pueden escribirse - usando '#=' antes de el texto y '=#' - después del texto. También se pueden anidar. +#= + Los comentarios 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" -# 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 +# 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 -# Imprimir es muy fácil -println("Soy Julia. ¡Encantado de conocerte!") +# ¡Imprimir es muy fácil! +println("¡Hola Julia!") # ¡Hola Julia! -#################################################### -## 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 guión 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 al 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 funciones 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 arrays de un range -a = [1:5] # => 5-element Int64 Array: [1,2,3,4,5] +# Se puede inicializar un arreglo con un rango (Range). +a = [1:5] # => 5-element Array{Int64,1}: [1,2,3,4,5] -# Puedes mirar en ranges con sintaxis slice. -a[1:3] # => [1, 2, 3] -a[2:end] # => [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] -# Eliminar elementos de una array por índice con splice! -arr = [3,4,5] -splice!(arr,2) # => 4 ; arr es ahora [3,5] +# Eliminar elementos de un arreglo por índice con splice! +arr = [3, 4, 5] +splice!(arr, 2) # => 4 y arr es ahora: [3,5] -# Concatenar listas con append! -b = [1,2,3] -append!(a,b) # ahroa a es [1, 2, 3, 4, 5, 1, 2, 3] +# Concatenar arreglos con append! +b = [1, 2, 3] +append!(a, b) # a ahora es: [1,2,3,4,5,1,2,3] -# Comprueba la existencia en una lista con in -in(1, a) # => true +# Comprueba la existencia de un elemento en un arreglo 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 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 tuplas se crean, incluso si se omiten los paréntesis. +d, e, f = 4, 5, 6 # => (4,5,6) -# 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 +# Una tupla de un elemento es distinta del valor que contiene. +(1,) == 1 # => false +(1) == 1 # => true -# Los tuples se crean, incluso si se omite el paréntesis -d, e, f = 4, 5, 6 # => (4,5,6) +# Mira que fácil es cambiar dos valores! +e, d = d, e # => (5,4) # ahora d es 5 y e es 4 -# Un tuple 1-elemento es distinto del valor que contiene -(1,) == 1 # => false -(1) == 1 # => true +# Los diccionarios (Dict) son arreglos asociativos. +dicc_vacio = Dict() # => Dict{Any,Any} with 0 entries -# Mira que fácil es cambiar dos valores -e, d = d, e # => (5,4) # d is now 5 and e is now 4 +# 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 -# Dictionaries almanecan mapeos -dict_vacio = Dict() # => Dict{Any,Any}() +# 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 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) +# Usa conjuntos (Set) para representar colecciones de valores únicos, no +# ordenados. +conjunto_vacio = Set() # => Set{Any}({}) -# 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) +# Iniciar una conjunto de valores. +conjunto_lleno = Set(1, 2, 2, 3, 4) # => Set{Int64}({4,2,3,1}) -# Compruebe si los valores están en el conjunto -in(2, conjunto_lleno) # => true -in(10, conjunto_lleno) # => false +# 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}) -# 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) +# Comprobar si los valores están en el conjunto. +in(2, conjunto_lleno) # => true +in(10, conjunto_lleno) # => false +# 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 -#################################################### -# Hagamos una variable +####################### +# 3. Control de Flujo # +####################### + +# 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 6 -suma(5, 6) # => 11 # después de imprimir "x es 5 e y es de 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 +=# -# 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] +filter([3, 4, 5, 6, 7]) do arr + (x -> x > 5)(arr) +end +#= + => 2-element Array{Int64,1}: + 6 + 7 +=# -#################################################### -## 5. Tipos -#################################################### +# 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] + +[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} -# 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. +# 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 + +# 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 está 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étodos má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 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) -pelear(Leon("balooga!"),Pantera()) # => imprime El gato victorioso dice grrr +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()) # 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? +![Julia-tan](http://s27.postimg.org/x37ndhz0j/julia_tan_small.png) -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 |