1
0
mirror of https://github.com/adambard/learnxinyminutes-docs.git synced 2025-08-09 08:16:58 +02:00

Merge branch 'master' of github.com:greybird/learnxinyminutes-docs

This commit is contained in:
greybird
2013-08-07 11:21:22 +04:00
8 changed files with 2025 additions and 5 deletions

View File

@@ -70,7 +70,7 @@ double x_double = 0.0;
// Integral types may be unsigned. This means they can't be negative, but
// the maximum value of an unsigned variable is greater than the maximum
// value of the same size.
// signed value of the same size.
unsigned char ux_char;
unsigned short ux_short;
unsigned int ux_int;

425
es-es/c-es.html.markdown Normal file
View File

@@ -0,0 +1,425 @@
---
language: c
filename: learnc.c
contributors:
- ["Adam Bard", "http://adambard.com/"]
translators:
- ["Francisco García", "http://flaskbreaker.tumblr.com/"]
lang: es-es
---
¡Ah!, C. Aun hoy en día sigue siendo el lenguaje por excelencia de la
computación moderna de alto rendimiento.
C es el lenguaje de más bajo nivel que la mayoría de los programadores
llegarán a usar, pero lo compensa de sobra con pura velocidad. Solo
ten en cuenta el manejo manual de memoria y te llevará tan lejos como
necesites.
```c
// Los comentarios de una sola línea comienzan con //
/*
Los comentarios multilínea tienen este aspecto.
*/
// Importa cabeceras con #include
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Declara por adelantado las armaduras de las funciones en un archivo .h,
// o al principio de tu archivo .c .
void function_1();
void function_2();
// El punto de entrada de tu programa es una función llamada main con
// retorno de tipo entero (integer).
int main() {
// Muestra la salida usando printf, para el "formato print"
// %d es un entero, \n es una nueva línea
printf("%d\n", 0); // => Muestra 0
// Todas las sentencias deben terminar con un punto y coma.
///////////////////////////////////////
// Tipos
///////////////////////////////////////
// Tienes que declarar una variable antes de usarla. La declaración de una
// variable necesites que especifiques su tipo; el tipo de una variable
// determina su tamaño en bytes.
// 'ints' (enteros) son normalmente de 4 bytes
int x_int = 0;
// 'shorts' son normalmente de 2 bytes
short x_short = 0;
// 'chars' son fijo de 1 byte
char x_char = 0;
char y_char = 'y'; // Los caracteres literales se entrecomillan con ''
// 'longs' son a menudo de 4 a 8 bytes; 'long longs' son fijo de por lo
// menos 64 bits
long x_long = 0;
long long x_long_long = 0;
// 'floats' son normalmente números de coma flotante de 32 bits
float x_float = 0.0;
// 'doubles' son normalmente números de coma flotante de 64 bits
double x_double = 0.0;
// Todos los tipos enteros pueden ser 'unsigned'. Esto significa que no
// pueden ser negativos, pero el valor máximo de una variable 'unsigned'
// es mayor que el de una no 'unsigned' del mismo tamaño.
unsigned char ux_char;
unsigned short ux_short;
unsigned int ux_int;
unsigned long long ux_long_long;
// Todos menos 'char', que es siempre de 1 byte, varían el tamaño
// dependiendo de tu máquina. sizeof(T) te dice el tamaño de una variable
// de tipo T en bytes por lo que podemos expresar el tamaño de estos tipos
// portatilmente.
// Por ejemplo,
printf("%lu\n", sizeof(int)); // => 4 (en máquinas con 'words' de 4 bytes)
// Los arrays deben ser inicializados con un tamaño concreto.
char my_char_array[20]; // Este array ocupa 1 * 20 = 20 bytes
int my_int_array[20]; // Este array ocupa 4 * 20 = 80 bytes
// (suponiendo que tenemos 'words' de 4-byte)
// Puedes inicializar un array a 0 así:
char my_array[20] = {0};
// Indexar un array es como en otros lenguajes -o, más bien, otros
// lenguajes son como C-
my_array[0]; // => 0
// Los arrays varían; ¡son sólo memoria!
my_array[1] = 2;
printf("%d\n", my_array[1]); // => 2
// Las cadenas (strings) son sólo arrays de 'chars' (caracteres)
// terminados en un byte NUL (0x00), representado en las cadenas como el
// carácter especial '\0'.
// (No tenemos porqué añadir el byte nulo en cadenas literales; el
// compilador lo añade al final por nosotros.)
char a_string[20] = "Esto es una cadena";
printf("%s\n", a_string); // %s se sutituye por una cadena.
/*
Te habrás dado cuenta de que a_string es solo de 18 caracteres.
El 'char' #19 es el byte nulo.
El 'char' #20 es de valor indefinido.
*/
printf("%d\n", a_string[18]); // => 0
///////////////////////////////////////
// Operadores
///////////////////////////////////////
int i1 = 1, i2 = 2; // Forma corta de declaración múltiple
float f1 = 1.0, f2 = 2.0;
// La aritmética es sencilla
i1 + i2; // => 3
i2 - i1; // => 1
i2 * i1; // => 2
i1 / i2; // => 0 (0.5, pero es truncado tras el 0)
f1 / f2; // => 0.5, más o menos épsilon
// Módulo está también
11 % 3; // => 2
// Los operadores de comparación te resultaran familiares, pero no hay
// booleanos en C. Usamos enteros (ints) en su lugar. 0 es falso,
// cualquier otra cosa es verdadero. (Los operadores de comparación
// siempre devuelven 0 o 1)
3 == 2; // => 0 (Falso)
3 != 2; // => 1 (Verdadero)
3 > 2; // => 1
3 < 2; // => 0
2 <= 2; // => 1
2 >= 2; // => 1
// La lógica funiona en enteros
!3; // => 0 (not lógico)
!0; // => 1
1 && 1; // => 1 (and lógico)
0 && 1; // => 0
0 || 1; // => 1 (or lógico)
0 || 0; // => 0
// ¡Operadores de bits!
~0x0F; // => 0xF0 (Negación)
0x0F & 0xF0; // => 0x00 (AND)
0x0F | 0xF0; // => 0xFF (OR)
0x04 ^ 0x0F; // => 0x0B (XOR)
0x01 << 1; // => 0x02 (desplazar hacia la izquierda (por 1))
0x02 >> 1; // => 0x01 (desplazar hacia la derecha (por 1))
///////////////////////////////////////
// Estructuras de Control
///////////////////////////////////////
if (0) {
printf("Yo nunca ocurro\n");
} else if (0) {
printf("Yo tampoco ocurro nunca\n");
} else {
printf("Yo me muestro\n");
}
// Mientras el bucle exista
int ii = 0;
while (ii < 10) {
printf("%d, ", ii++); // ii++ incrementa ii en uno, después de usar su valor.
} // => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
int kk = 0;
do {
printf("%d, ", kk);
} while (++kk < 10); // ++kk incrementa kk en uno, antes de usar su valor.
// => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
// Bucles 'for' también
int jj;
for (jj=0; jj < 10; jj++) {
printf("%d, ", jj);
} // => muestra "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "
printf("\n");
///////////////////////////////////////
// Cambios de Tipo
///////////////////////////////////////
// Cada valor en C tiene un tipo, pero tu puedes ingresar un valor en
// otro tipo si quieres.
int x_hex = 0x01; // Puedes asignar hexadecimales a variables
// El cambio de tipos intentará mantener sus valores numéricos
printf("%d\n", x_hex); // => Muestra 1
printf("%d\n", (short) x_hex); // => Muestra 1
printf("%d\n", (char) x_hex); // => Muestra 1
// Los tipos se desbordan sin aviso
printf("%d\n", (char) 257); // => 1 (El valor máximo de un 'char' es 255)
// Los tipos enteros puden cambiarse a tipos de coma flotante, y viceversa
printf("%f\n", (float)100); // %f se sustituye por un 'float'
printf("%lf\n", (double)100); // %lf se sustituye por un 'double'
printf("%d\n", (char)100.0);
///////////////////////////////////////
// Punteros
///////////////////////////////////////
// Un puntero es una variable declarada para almacenar una dirección de
// memoria. Su declaración además nos dirá el tipo de dato al que apunta.
// Puedes obtener la dirección de memoria de tus variables, y después
// enlazarlas con ellos.
int x = 0;
printf("%p\n", &x); // Usa & para obtener la dirección de una variable.
// (%p se sustituye por un puntero)
// => Muestra alguna dirección de memoria;
// Los tipos de puntero terminan con * en su declaración
int* px; // px es un puntero a un 'int'
px = &x; // Almacena la dirección de x en px
printf("%p\n", px); // => Muestra alguna dirección de memoria
// Para obtener el valor de la dirección a la que apunta un puntero, pon
// * delante para desreferenciarle.
printf("%d\n", *px); // => Muestra 0, el valor de x y de la dirección a la
// que apunta px
// También puedes cambiar el valor al que está apuntando el puntero.
// Tenemos que meter la desreferencia entre paréntesis porque ++ tiene
// prioridad frente a *.
(*px)++; // Incrementa el valor al que apunta px en 1
printf("%d\n", *px); // => Muestra 1
printf("%d\n", x); // => Muestra 1
int x_array[20]; // Los arrays son una buena manera de distribuir bloques
int xx; // continuos de memoria.
for (xx=0; xx<20; xx++) {
x_array[xx] = 20 - xx;
} // Inicializa x_array a 20, 19, 18,... 2, 1
// Declara un puntero de tipo 'int' y lo inicializa para apuntar a x_array
int* x_ptr = x_array;
// x_ptr ahira apunta al primer elemento del 'array' (el entero 20).
// Esto funciona porque las 'arrays' actualmente son solo punteros a su
// primer elemento.
// Los 'arrays' son punteros a su primer elemento.
printf("%d\n", *(x_ptr)); // => Muestra 20
printf("%d\n", x_array[0]); // => Muestra 20
// Los punteros aumentan y disminuyen en función de su tipo.
printf("%d\n", *(x_ptr + 1)); // => Muestra 19
printf("%d\n", x_array[1]); // => Muestra 19
// Puedes también asigner dinamicamente bloques contiguos de memoria con
// la función malloc de la librería estándard, que toma un entero como
// argumento representando el número de bytes a asignar de la pila.
int* my_ptr = (int*) malloc(sizeof(int) * 20);
for (xx=0; xx<20; xx++) {
*(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx funcionaría también aquí
} // Inicializa la memoria a 20, 19, 18, 17... 2, 1 (como 'ints')
// Desreferenciando la memoria que no has asignado te dará resultados
// impredecibles
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what?
// Cuando hallas acabado con el bloque de memoría malloc, necesitas
// liberarlo o sino nadie más podrá usarlo hasta que tu programa se cierre
free(my_ptr);
// Las cadenas pueden ser 'arrays' de chars, pero normalmente se
// representan con punteros 'char':
char* my_str = "This is my very own string";
printf("%c\n", *my_str); // => 'T'
function_1();
} // fin de la función main
///////////////////////////////////////
// Funciones
///////////////////////////////////////
// Sintexis de la declaración de funciones:
// <tipo de retorno> <nombre>(<argumentos>)
int add_two_ints(int x1, int x2){
return x1 + x2; // Usa 'return' para dar una salida
}
/*
Las funciones son de paso por valor, pero puedes hacer tus propias
referencias con punteros de manera que las funciones puedan cambiar sus
valores.
Ejemplo: invertidor de cadenas in-situ
*/
// Una función 'void' no retorna valor
void str_reverse(char* str_in){
char tmp;
int ii=0, len = strlen(str_in); // Strlen es parte de la librería
for(ii=0; ii<len/2; ii++){ // estándard
tmp = str_in[ii];
str_in[ii] = str_in[len - ii - 1]; // ii-th último 'char'
str_in[len - ii - 1] = tmp;
}
}
/*
char c[] = "Esto es una prueba.";
str_reverse(c);
printf("%s\n", c); // => ".abeurp anu se otsE"
*/
///////////////////////////////////////
// Definición de tipos y estructuras
///////////////////////////////////////
// Los 'Typedefs' pueden ser utilizados para crear alias de tipos.
typedef int my_type;
my_type my_type_var = 0;
// Las estructuras son sólo grupos de datos.
struct rectangle {
int width;
int height;
};
void function_1(){
struct rectangle my_rec;
// Utiliza los miembros de una estructura con .
my_rec.width = 10;
my_rec.height = 20;
// Puedes declarar punteros a estructuras
struct rectangle* my_rec_ptr = &my_rec;
// Usa la desreferencia para modificar sus miembros...
(*my_rec_ptr).width = 30;
// ... o usa la abreviatura ->
my_rec_ptr->height = 10; // Lo mismo que (*my_rec_ptr).height = 10;
}
// Puedes aplicar un 'typedef' a una estructura por conveniencía.
typedef struct rectangle rect;
int area(rect r){
return r.width * r.height;
}
///////////////////////////////////////
// Punteros a Funciones
///////////////////////////////////////
/*
En tiempo de ejecución, las funciones se localizan en unas direcciones de
memoria concretas. Los punteros a funciones son como cualquier otro
puntero (almacenan una dirección de memoria), pero pueden ser usados para
utilizar funciones directamente, o para pasar 'handlers' (o funciones
'callback') por todos lados.
Sin embargo, la sintaxis de definición parecera confusa al principio.
Ejemplo: usar str_reverse desde un puntero
*/
void str_reverse_through_pointer(char * str_in) {
// Define un puntero a una función, llamado f.
void (*f)(char *);
// La armadura debe coincidir exactamente con al función objetivo.
// Assigna la dirección de la función (determinado en tiempo de ejecuión)
f = &str_reverse;
// Llamando la función desde el puntero
(*f)(str_in);
// Esta es una alternativa para llamarla pero con una sintaxis igual de válida.
// f(str_in);
}
/*
Tanto tiempo como las armaduras de las funciones coincidan, podrás asignar
cualquier función al mismo puntero.
Los punteros a funciones son normalmente envueltos en 'typedef' para
simplificar su legibilidad, como sigue:
*/
typedef void (*my_fnp_type)(char *);
// Es usado para declarar la variable puntero actual:
// ...
// my_fnp_type f;
```
## Otras lecturas
Lo mejor que puedes en contrar es una copia de [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)
Otro buen recurso es [Learn C the hard way](http://c.learncodethehardway.org/book/)
Aparte de eso, Google es tu amigo.

View File

@@ -0,0 +1,377 @@
---
language: elisp
contributors:
- ["Bastien Guerry", "http://bzg.fr"]
translators:
- ["Guillermo Vayá", "http://willyfrog.es"]
lang: es-es
filename: learn-emacs-lisp.el
---
```scheme
;; Introduccion a Emacs Lisp en 15 minutos (v0.2d)
;;
;; Autor: Bastien / @bzg2 / http://bzg.fr
;; Traducción: Guillermo Vayá
;;
;; Antes de nada, lee este texto de Peter Norvig:
;; http://norvig.com/21-days.html
;;
;; Ahora instala GNU Emacs 24.3:
;;
;; Debian: apt-get install emacs
;; (o sigue las instrucciones de tu distribución preferida)
;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
;;
;; Puedes encontrar información general sobre Emacs en:
;; http://www.gnu.org/software/emacs/#Obtaining
;; Aviso importante:
;;
;; Seguir este tutorial no provocará daños en tu ordenador a menos que
;; te enfades tanto que que acabes tirándolo al suelo. En tal caso
;; declino cualquier responsabilidad. ¡A divertirse!
;; "N. del. T.": Algunos términos comunes de la informática se han dejado
;; sin traducir ya que es mucho más probable que el lector los conozca en
;; su forma en inglés, siendo la versión en español de muy raro uso.
;; Además "sexps" se ha decidido traducir por sexpresión.
;; Por último, añadir que no se han traducido los ejemplos de código ya que no
;; es necesario entender qué dice el string para comprender el funcionamiento
;; y podría llevar a error.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Inicia Emacs.
;;
;; Pulsa la tecla `q' para pasar el mensaje de bienvenida.
;;
;; Mira a la línea gris en la parte inferior de la ventana:
;;
;; "*scratch*" es el nombre del espacio editable donde estás.
;; A este espacio editable se le llama "buffer".
;;
;; Scratch es el buffer por defecto cuando abres Emacs.
;; En Emacs nunca editas ficheros, sino que editas buffers que
;; posteriormente pueden grabarse a un fichero.
;; can save to a file.
;;
;; "Lisp interaction" indica el conjunto de ordenes disponibles.
;;
;; Emacs dispone de un set de comandos disponibles en cualquier buffer
;; ("built-ins") y aparte varios conjuntos de ordenes disponibles
;; según el modo específico que esté activo. En nuestro caso
;; estamos usando `lisp-interaction-mode', el cual incluye las
;; ordenes necesarias para evaluar y navegar código Elisp.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Un punto y coma comienza un comentario. Pueden ponerse en cualquier
;; posicion de la linea.
;;
;; Los programas en Elisp se componen de expresiones simbólicas
;; tambien llamadas "sexps":
(+ 2 2)
;; Esta expresión simbólica se lee tal que "Suma 2 y 2"
;; Las sexpresiones se rodean por paréntesis, y pueden anidarse:
(+ 2 (+ 1 1))
;; Una expresion simbólica está formada bien por átomos o bien por otras
;; expresiones simbólicas. En el ejemplo de arriba, 1 y 2 son átomos,
;; mientras que (+ 2 (+ 1 1)) y (+ 1 1) son expresiones simbólicas.
;; Gracias a `lisp-interaction-mode' puedes evaluar las sexpresiones.
;; Coloca el cursor justo despues del paréntesis de cierre y
;; mantén pulsada la tecla Control y la j (para abreviar usaremos "C-j").
(+ 3 (+ 1 2))
;; ^ pon aquí el cursor
;; `C-j' => 6
;; `C-j' añade el resultado de la evaluación al buffer.
;; `C-xC-e' muestra el mismo resultado pero en la linea inferior
;; la cual se llama "minibuffer". Este será el metodo que usaremos
;; normalmente para no llenar el buffer con texto inútil.
;; `setq' guarda un valor en una variable:
(setq my-name "Bastien")
;; `C-xC-e' => "Bastien" (aparece en el mini-buffer)
;; `insert' añade "Hello!" en el punto donde esté tu cursor:
(insert "Hello!")
;; `C-xC-e' => "Hello!"
;; Aunque hemos usado `insert' con solo un parámetro "Hello!", se
;; pueden pasar más. Por ejemplo, en esta otra sexpresión usamos dos:
(insert "Hello" " world!")
;; `C-xC-e' => "Hello world!"
;; Se pueden usar variables en lugar de strings:
(insert "Hello, I am " my-name)
;; `C-xC-e' => "Hello, I am Bastien"
;; Puedes combinar sexpresiones en funciones:
(defun hello () (insert "Hello, I am " my-name))
;; `C-xC-e' => hello
;; Evaluemos la funcion:
(hello)
;; `C-xC-e' => Hello, I am Bastien
;; Los parentesis vacios en la definicion de una funcion indican
;; que no acepta parámetros. En cualquier caso, usar `my-name' siempre
;; es aburrido, asi que vamos a hacer que la función accepte un parámetro
;; (en este caso el parametro se llama "name"):
(defun hello (name) (insert "Hello " name))
;; `C-xC-e' => hello
;; Ahora vamos a llamar a la funcion con el string "you" como valor para
;; el único parámetro que posee.
(hello "you")
;; `C-xC-e' => "Hello you"
;; ¡Genial!
;; Descansa un poco y respira.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Ahora cambiaremos al nuevo buffer, llamado "*test*", en una nueva ventana.
(switch-to-buffer-other-window "*test*")
;; `C-xC-e'
;; => [La pantalla ahora tiene dos ventanas y el cursor está en el buffer *test*]
;; Mueve el ratón sobre la ventana superior y pulsa el boton izdo. para volver.
;; Otra forma es usando `C-xo' (pulsa simultaneamente control y x y luego la o)
;; para ir a la otra ventana.
;; Se pueden combinar varias sexpresiones mediante `progn':
(progn
(switch-to-buffer-other-window "*test*")
(hello "you"))
;; `C-xC-e'
;; => [De las dos ventanas de la pantalla, el cursor está en la marcada como *test*]
;; A partir de ahora, si no te importa, dejaremos de decir que pulses `C-xC-e':
;; tendrás que hacerlo para ejecutar cada sexpresión que siga.
;; También tendrás que volver al buffer *scratch* bien con el ratón o con `C-xo'.
;; En ocasiones será util limpiar el buffer:
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "there"))
;; O volver a la ventana anterior:
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "you")
(other-window 1))
;; Puedes enlazar un valor a una variable local con `let':
(let ((local-name "you"))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello local-name)
(other-window 1))
;; En este caso, no hace falta añadir `progn' ya que `let' permite combinar
;; varias sexpresiones.
;; Vamos a darle formato a un string:
(format "Hello %s!\n" "visitor")
;; Cada %s indica la posicion donde irá un string, el cual será reemplazado
;; por "visitor". "\n" es el caracter de nueva línea.
;; Mejoremos nuestra funcion usando `format':
(defun hello (name)
(insert (format "Hello %s!\n" name)))
(hello "you")
;; Creemos una nueva funcion que utililce `let':
(defun greeting (name)
(let ((your-name "Bastien"))
(insert (format "Hello %s!\n\nI am %s."
name ; the argument of the function
your-name ; the let-bound variable "Bastien"
))))
;; Y ahora la evaluamos:
(greeting "you")
;; Algunas funciones son interactivas:
(read-from-minibuffer "Enter your name: ")
;; Al evaluar esta función, ésta devuelve lo que hayas introducido.
;; Ahora hagamos nuestra función `greeting' preguntar por tu nombre:
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(insert (format "Hello!\n\nI am %s and you are %s."
from-name ; the argument of the function
your-name ; the let-bound var, entered at prompt
))))
(greeting "Bastien")
;; Y ahora la completamos mostrando el resultado en la otra ventana:
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(insert (format "Hello %s!\n\nI am %s." your-name from-name))
(other-window 1)))
;; Probémosla:
(greeting "Bastien")
;; Descansa un poco y respira.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Creemos una lista de nombres:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
;; Para coger el primer elemento de la lista usaremos `car':
(car list-of-names)
;; Para coger todos menos el primer elemento de la lista
;; usaremos `cdr':
(cdr list-of-names)
;; Para añadir un elemento al comienzo de la lista utilizamos `push':
(push "Stephanie" list-of-names)
;; OJO: `car' y `cdr' no modifican la lista, mientras que `push' sí.
;; ¡Es una diferencia importante! Algunas funciones no tienen efectos
;; colaterales (como `car') mientras que otras sí (como `push').
;; "N. del T.": estos efectos colaterales se les llama `side-effects' en
;; las distintas variantes de lisp.
;; Llamemos a `hello' con cada elemento de `list-of-names':
(mapcar 'hello list-of-names)
;; Retocamos `greeting' para que salude a todos los que estén en `list-of-names':
(defun greeting ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(mapcar 'hello list-of-names)
(other-window 1))
(greeting)
;; ¿Te acuerdas de la función `hello' definida un poco más arriba?
;; Recibía un parámetro: `name'. Así que `mapcar' llama a `hello' con cada
;; elemento de `list-of-names' como parámetro de `hello'.
;; Ahora ordenaremos un poco lo que tenemos en el buffer:
(defun replace-hello-by-bonjour ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (search-forward "Hello")
(replace-match "Bonjour"))
(other-window 1))
;; (goto-char (point-min)) mueve el cursor al principio del buffer.
;; (search-forward "Hello") busca un string "Hello".
;; (while x y) evalua la/s sexpresion/es y mientras que x devuelva
;; alguna cosa.
;; En el momento que x devuelva `nil' (es decir nada), sale del
;; bucle `while'.
(replace-hello-by-bonjour)
;; Observamos que todas las veces que teníamos la palabra "Hello" en el buffer *test*
;; han sido reemplazadas por "Bonjour".
;; Y además, hemos obtenido un error: "Search failed: Hello".
;;
;; Para evitar este error, hay que decirle a `search-forward' si debería dejar de
;; buscar en el buffer en algún momento y si debería fallar sin quejarse cuando
;; no encuentra nada.
;; (search-forward "Hello" nil t) justo hace eso:
;; El argumento `nil' significa que la busqueda no está ligada a ninguna posición.
;; Y el argumento `t' le pide que no diga nada si no encuentra el string.
;; Usaremos esta sexpresión en la función siguiente, la cual ya
;; no muestra ningún error:
(defun hello-to-bonjour ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
;; Say hello to names in `list-of-names'
(mapcar 'hello list-of-names)
(goto-char (point-min))
;; Replace "Hello" by "Bonjour"
(while (search-forward "Hello" nil t)
(replace-match "Bonjour"))
(other-window 1))
(hello-to-bonjour)
;; Añadamos algo de color a los nombres:
(defun boldify-names ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (re-search-forward "Bonjour \\(.+\\)!" nil t)
(add-text-properties (match-beginning 1)
(match-end 1)
(list 'face 'bold)))
(other-window 1))
;; Esta función nos presenta `re-search-forward': en vez de
;; buscar el string "Bonjour" exacto, se busca por un patrón
;; usando una "expresión regular" (lo cual se muestra abreviado
;; en el prefijo "re-" del inglés "Regular Expression").
;; La expresión regular a utilizar es "Bonjour \\(.+\\)!" y se traduce como:
;; el string "Bonjour ", seguido de
;; un grupo de | representado por \\( ... \\)
;; cualquier caracter | representado por .
;; al menos una vez | representado por +
;; y el string "!".
;; ¿Preparado? ¡Probemoslo!
(boldify-names)
;; `add-text-properties' añade propiedades al texto, como una fuente.
;; ¡Hale! ¡Ya lo tenemos! ¡Feliz hacking!
;; Si quieres saber más sobre una función o una variable:
;;
;; C-h v la-variable RET
;; C-h f la-funcion RET
;;
;; Si quieres leer el manual de Emacs Lisp desde dentro de Emacs:
;;
;; C-h i m elisp RET
;;
;; Para leer una introducción en linea de Emacs Lisp:
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
;; Me gustaría agradecer a las siguientes personas su feedback y sugerencias:
;; - Wes Hardaker
;; - notbob
;; - Kevin Montuori
;; - Arne Babenhauserheide
;; - Alan Schmitt
;; - LinXitoW
;; - Aaron Meurer
```

View File

@@ -232,7 +232,7 @@ filled_dict.setdefault("five", 6) #filled_dict["five"] is still 5
# Sets store ... well sets
empty_set = set()
# Initialize a set with a bunch of values
some_set = set([1,2,2,3,4]) # filled_set is now set([1, 2, 3, 4])
some_set = set([1,2,2,3,4]) # some_set is now set([1, 2, 3, 4])
# Since Python 2.7, {} can be used to declare a set
filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
@@ -470,12 +470,19 @@ dir(math)
```
## Further Reading
## Ready For More?
Still up for more? Try:
### Free Online
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
* [Dive Into Python](http://www.diveintopython.net/)
* [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/)
### Dead Tree
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)

View File

@@ -120,7 +120,7 @@ $ git help
$ git help -a
# 在文档当中查找特定的命令
$ git help <命令>
# git help <命令>
$ git help add
$ git help commit
$ git help init

407
zh-cn/haskell-cn.html.markdown Executable file
View File

@@ -0,0 +1,407 @@
---
language: haskell
filename: learn-haskell.hs
contributors:
- ["Adit Bhargava", "http://adit.io"]
translators:
- ["Peiyong Lin", ""]
lang: zh-cn
---
Haskell 被设计成一种实用的纯函数式编程语言。它因为 monads 及其类型系统而出名但是我回归到它本身因为。Haskell 使得编程对于我而言是一种真正的快乐。
```haskell
-- 单行注释以两个破折号开头
{- 多行注释像这样
被一个闭合的块包围
-}
----------------------------------------------------
-- 1. 简单的数据类型和操作符
----------------------------------------------------
-- 你有数字
3 -- 3
-- 数学计算就像你所期待的那样
1 + 1 -- 2
8 - 1 -- 7
10 * 2 -- 20
35 / 5 -- 7.0
-- 默认除法不是整除
35 / 4 -- 8.75
-- 整除
35 `div` 4 -- 8
-- 布尔值也简单
True
False
-- 布尔操作
not True -- False
not False -- True
1 == 1 -- True
1 /= 1 -- False
1 < 10 -- True
-- 在上述的例子中,`not` 是一个接受一个值的函数。
-- Haskell 不需要括号来调用函数。。。所有的参数
-- 都只是在函数名之后列出来。因此,通常的函数调用模式是:
-- func arg1 arg2 arg3...
-- 查看关于函数的章节以获得如何写你自己的函数的相关信息。
-- 字符串和字符
"This is a string."
'a' -- 字符
'对于字符串你不能使用单引号。' -- 错误!
-- 连结字符串
"Hello " ++ "world!" -- "Hello world!"
-- 一个字符串是一系列字符
"This is a string" !! 0 -- 'T'
----------------------------------------------------
-- 列表和元组
----------------------------------------------------
-- 一个列表中的每一个元素都必须是相同的类型
-- 下面两个列表一样
[1, 2, 3, 4, 5]
[1..5]
-- 在 Haskell 你可以拥有含有无限元素的列表
[1..] -- 一个含有所有自然数的列表
-- 因为 Haskell 有“懒惰计算”,所以无限元素的列表可以正常运作。这意味着
-- Haskell 可以只在它需要的时候计算。所以你可以请求
-- 列表中的第1000个元素Haskell 会返回给你
[1..] !! 999 -- 1000
-- Haskell 计算了列表中 1 - 1000 个元素。。。但是
-- 这个无限元素的列表中剩下的元素还不存在! Haskell 不会
-- 真正地计算它们知道它需要。
<FS>- 连接两个列表
[1..5] ++ [6..10]
-- 往列表头增加元素
0:[1..5] -- [0, 1, 2, 3, 4, 5]
-- 列表中的下标
[0..] !! 5 -- 5
-- 更多列表操作
head [1..5] -- 1
tail [1..5] -- [2, 3, 4, 5]
init [1..5] -- [1, 2, 3, 4]
last [1..5] -- 5
-- 列表推导
[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
-- 附带条件
[x*2 | x <-[1..5], x*2 > 4] -- [6, 8, 10]
-- 元组中的每一个元素可以是不同类型的,但是一个元组
-- 的长度是固定的
-- 一个元组
("haskell", 1)
-- 获取元组中的元素
fst ("haskell", 1) -- "haskell"
snd ("haskell", 1) -- 1
----------------------------------------------------
-- 3. 函数
----------------------------------------------------
-- 一个接受两个变量的简单函数
add a b = a + b
-- 注意,如果你使用 ghci (Hakell 解释器)
-- 你将需要使用 `let`,也就是
-- let add a b = a + b
-- 使用函数
add 1 2 -- 3
-- 你也可以把函数放置在两个参数之间
-- 附带倒引号:
1 `add` 2 -- 3
-- 你也可以定义不带字符的函数!这使得
-- 你定义自己的操作符!这里有一个操作符
-- 来做整除
(//) a b = a `div` b
35 // 4 -- 8
-- 守卫:一个简单的方法在函数里做分支
fib x
| x < 2 = x
| otherwise = fib (x - 1) + fib (x - 2)
-- 模式匹配是类型的。这里有三种不同的 fib
-- 定义。Haskell 将自动调用第一个
-- 匹配值的模式的函数。
fib 1 = 1
fib 2 = 2
fib x = fib (x - 1) + fib (x - 2)
-- 元组的模式匹配:
foo (x, y) = (x + 1, y + 2)
-- 列表的模式匹配。这里 `x` 是列表中第一个元素,
-- 并且 `xs` 是列表剩余的部分。我们可以写
-- 自己的 map 函数:
myMap func [] = []
myMap func (x:xs) = func x:(myMap func xs)
-- 编写出来的匿名函数带有一个反斜杠,后面跟着
-- 所有的参数。
myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
-- 使用 fold (在一些语言称为`inject`)随着一个匿名的
-- 函数。foldl1 意味着左折叠(fold left), 并且使用列表中第一个值
-- 作为累加器的初始化值。
foldl1 (\acc x -> acc + x) [1..5] -- 15
----------------------------------------------------
-- 4. 更多的函数
----------------------------------------------------
-- 柯里化(currying):如果你不传递函数中所有的参数,
-- 它就变成“柯里化的”。这意味着,它返回一个接受剩余参数的函数。
add a b = a + b
foo = add 10 -- foo 现在是一个接受一个数并对其加 10 的函数
foo 5 -- 15
-- 另外一种方式去做同样的事
foo = (+10)
foo 5 -- 15
-- 函数组合
-- (.) 函数把其它函数链接到一起
-- 举个列子,这里 foo 是一个接受一个值的函数。它对接受的值加 10
-- 并对结果乘以 5之后返回最后的值。
foo = (*5) . (+10)
-- (5 + 10) * 5 = 75
foo 5 -- 75
-- 修复优先级
-- Haskell 有另外一个函数称为 `$`。它改变优先级
-- 使得其左侧的每一个操作先计算然后应用到
-- 右侧的每一个操作。你可以使用 `.` 和 `$` 来除去很多
-- 括号:
-- before
(even (fib 7)) -- true
-- after
even . fib $ 7 -- true
----------------------------------------------------
-- 5. 类型签名
----------------------------------------------------
-- Haskell 有一个非常强壮的类型系统,一切都有一个类型签名。
-- 一些基本的类型:
5 :: Integer
"hello" :: String
True :: Bool
-- 函数也有类型。
-- `not` 接受一个布尔型返回一个布尔型:
-- not :: Bool -> Bool
-- 这是接受两个参数的函数:
-- add :: Integer -> Integer -> Integer
-- 当你定义一个值,在其上写明它的类型是一个好实践:
double :: Integer -> Integer
double x = x * 2
----------------------------------------------------
-- 6. 控制流和 If 语句
----------------------------------------------------
-- if 语句
haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
-- if 语句也可以有多行,缩进是很重要的
haskell = if 1 == 1
then "awesome"
else "awful"
-- case 语句:这里是你可以怎样去解析命令行参数
case args of
"help" -> printHelp
"start" -> startProgram
_ -> putStrLn "bad args"
-- Haskell 没有循环因为它使用递归取代之。
-- map 应用一个函数到一个数组中的每一个元素
map (*2) [1..5] -- [2, 4, 6, 8, 10]
-- 你可以使用 map 来编写 for 函数
for array func = map func array
-- 然后使用它
for [0..5] $ \i -> show i
-- 我们也可以像这样写:
for [0..5] show
-- 你可以使用 foldl 或者 foldr 来分解列表
-- foldl <fn> <initial value> <list>
foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43
-- 这和下面是一样的
(2 * (2 * (2 * 4 + 1) + 2) + 3)
-- foldl 是左手边的foldr 是右手边的-
foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16
-- 这和下面是一样的
(2 * 3 + (2 * 2 + (2 * 1 + 4)))
----------------------------------------------------
-- 7. 数据类型
----------------------------------------------------
-- 这里展示在 Haskell 中你怎样编写自己的数据类型
data Color = Red | Blue | Green
-- 现在你可以在函数中使用它:
say :: Color -> String
say Red = "You are Red!"
say Blue = "You are Blue!"
say Green = "You are Green!"
-- 你的数据类型也可以有参数:
data Maybe a = Nothing | Just a
-- 类型 Maybe 的所有
Just "hello" -- of type `Maybe String`
Just 1 -- of type `Maybe Int`
Nothing -- of type `Maybe a` for any `a`
----------------------------------------------------
-- 8. Haskell IO
----------------------------------------------------
-- 虽然在没有解释 monads 的情况下 IO不能被完全地解释
-- 着手解释到位并不难。
-- 当一个 Haskell 程序被执行,函数 `main` 就被调用。
-- 它必须返回一个类型 `IO ()` 的值。举个列子:
main :: IO ()
main = putStrLn $ "Hello, sky! " ++ (say Blue)
-- putStrLn has type String -> IO ()
-- 如果你能实现你的程序依照函数从 String 到 String那样编写 IO 是最简单的。
-- 函数
-- interact :: (String -> String) -> IO ()
-- 输入一些文本,在其上运行一个函数,并打印出输出
countLines :: String -> String
countLines = show . length . lines
main' = interact countLines
-- 你可以考虑一个 `IO()` 类型的值,当做一系列计算机所完成的动作的代表,
-- 就像一个以命令式语言编写的计算机程序。我们可以使用 `do` 符号来把动作链接到一起。
-- 举个列子:
sayHello :: IO ()
sayHello = do
putStrLn "What is your name?"
name <- getLine -- this gets a line and gives it the name "input"
putStrLn $ "Hello, " ++ name
-- 练习:编写只读取一行输入的 `interact`
-- 然而,`sayHello` 中的代码将不会被执行。唯一被执行的动作是 `main` 的值。
-- 为了运行 `sayHello`,注释上面 `main` 的定义,并代替它:
-- main = sayHello
-- 让我们来更好地理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是:
-- getLine :: IO String
-- 你可以考虑一个 `IO a` 类型的值,代表一个当被执行的时候
-- 将产生一个 `a` 类型的值的计算机程序(除了它所做的任何事之外)。我们可以保存和重用这个值通过 `<-`。
-- 我们也可以写自己的 `IO String` 类型的动作:
action :: IO String
action = do
putStrLn "This is a line. Duh"
input1 <- getLine
input2 <- getLine
-- The type of the `do` statement is that of its last line.
-- `return` is not a keyword, but merely a function
return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
-- 我们可以使用这个动作就像我们使用 `getLine`:
main'' = do
putStrLn "I will echo two lines!"
result <- action
putStrLn result
putStrLn "This was all, folks!"
-- `IO` 类型是一个 "monad" 的例子。Haskell 使用一个 monad 来做 IO的方式允许它是一门纯函数式语言。
-- 任何与外界交互的函数(也就是 IO) 都在它的类型签名处做一个 `IO` 标志
-- 着让我们推出 什么样的函数是“纯洁的”(不与外界交互,不修改状态) 和 什么样的函数不是 “纯洁的”
-- 这是一个强有力的特征因为并发地运行纯函数是简单的因此Haskell 中并发是非常简单的。
----------------------------------------------------
-- 9. The Haskell REPL
----------------------------------------------------
-- 键入 `ghci` 开始 repl。
-- 现在你可以键入 Haskell 代码。
-- 任何新值都需要通过 `let` 来创建:
let foo = 5
-- 你可以查看任何值的类型,通过命令 `:t`
>:t foo
foo :: Integer
-- 你也可以运行任何 `IO ()`类型的动作
> sayHello
What is your name?
Friend!
Hello, Friend!
```
还有很多关于 Haskell包括类型类和 monads。这些是使得编码 Haskell 是如此有趣的主意。我用一个最后的 Haskell 例子来结束:一个 Haskell 的快排实现:
```haskell
qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
where lesser = filter (< p) xs
greater = filter (>= p) xs
```
安装 Haskell 是简单的。你可以从[这里](http://www.haskell.org/platform/)获得它。
你可以从优秀的
[Learn you a Haskell](http://learnyouahaskell.com/) 或者
[Real World Haskell](http://book.realworldhaskell.org/)
找到优雅不少的入门介绍。

475
zh-cn/python-cn.html.markdown Executable file
View File

@@ -0,0 +1,475 @@
---
language: python
contributors:
- ["Louie Dinh", "http://ldinh.ca"]
translators:
- ["Chenbo Li", "http://binarythink.net"]
filename: learnpython.py
lang: zh-cn
---
Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语言之一
我喜爱python是因为它有极为清晰的语法甚至可以说它就是可以执行的伪代码
很欢迎来自您的反馈,你可以在[@louiedinh](http://twitter.com/louiedinh) 和 louiedinh [at] [google's email service] 这里找到我
注意: 这篇文章针对的版本是Python 2.7但大多也可使用于其他Python 2的版本
如果是Python 3请在网络上寻找其他教程
```python
# 单行注释
""" 多行字符串可以用
三个引号包裹,不过这也可以被当做
多行注释
"""
####################################################
## 1. 原始数据类型和操作符
####################################################
# 数字类型
3 #=> 3
# 简单的算数
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
# 整数的除法会自动取整
5 / 2 #=> 2
# 要做精确的除法,我们需要引入浮点数
2.0 # 浮点数
11.0 / 4.0 #=> 2.75 好多了
# 括号具有最高优先级
(1 + 3) * 2 #=> 8
# 布尔值也是原始数据类型
True
False
# 用not来取非
not True #=> False
not 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
# 比较运算可以连起来写!
1 < 2 < 3 #=> True
2 < 3 < 2 #=> False
# 字符串通过"或'括起来
"This is a string."
'This is also a string.'
# 字符串通过加号拼接
"Hello " + "world!" #=> "Hello world!"
# 字符串可以被视为字符的列表
"This is a string"[0] #=> 'T'
# % 可以用来格式化字符串
"%s can be %s" % ("strings", "interpolated")
# 也可以用format方法来格式化字符串
# 推荐使用这个方法
"{0} can be {1}".format("strings", "formatted")
# 也可以用变量名代替数字
"{name} wants to eat {food}".format(name="Bob", food="lasagna")
# None 是对象
None #=> None
# 不要用相等 `==` 符号来和None进行比较
# 要用 `is`
"etc" is None #=> False
None is None #=> True
# 'is' 可以用来比较对象的相等性
# 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少
# None, 0, 和空字符串都被算作False
# 其他的均为True
0 == False #=> True
"" == False #=> True
####################################################
## 2. 变量和集合
####################################################
# 很方便的输出
print "I'm Python. Nice to meet you!"
# 给变量赋值前不需要事先生命
some_var = 5 # 规范用小写字母和下划线来做为变量名
some_var #=> 5
# 访问之前为赋值的变量会抛出异常
# 查看控制流程一节来了解异常处理
some_other_var # 抛出命名异常
# if语句可以作为表达式来使用
"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
# 列表用来保存序列
li = []
# 可以直接初始化列表
other_li = [4, 5, 6]
# 在列表末尾添加元素
li.append(1) #li 现在是 [1]
li.append(2) #li 现在是 [1, 2]
li.append(4) #li 现在是 [1, 2, 4]
li.append(3) #li 现在是 [1, 2, 4, 3]
# 移除列表末尾元素
li.pop() #=> 3 and li is now [1, 2, 4]
# 放回来
li.append(3) # li is now [1, 2, 4, 3] again.
# 像其他语言访问数组一样访问列表
li[0] #=> 1
# 访问最后一个元素
li[-1] #=> 3
# 越界会抛出异常
li[4] # 抛出越界异常
# 切片语法需要用到列表的索引访问
# 可以看做数学之中左闭右开区间
li[1:3] #=> [2, 4]
# 省略开头的元素
li[2:] #=> [4, 3]
# 省略末尾的元素
li[:3] #=> [1, 2, 4]
# 删除特定元素
del li[2] # li 现在是 [1, 2, 3]
# 合并列表
li + other_li #=> [1, 2, 3, 4, 5, 6] - 不改变这两个列表
# 通过拼接合并列表
li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6]
# 用in来返回元素是否在列表中
1 in li #=> True
# 返回列表长度
len(li) #=> 6
# 元组类似于列表,但是他是不可改变的
tup = (1, 2, 3)
tup[0] #=> 1
tup[0] = 3 # 类型错误
# 对于大多数的列表操作,也适用于元组
len(tup) #=> 3
tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
tup[:2] #=> (1, 2)
2 in tup #=> True
# 你可以将元组解包赋给多个变量
a, b, c = (1, 2, 3) # a是1b是2c是3
# 如果不加括号,那么会自动视为元组
d, e, f = 4, 5, 6
# 现在我们可以看看交换两个数字是多么容易的事
e, d = d, e # d是5e是4
# 字典用来储存映射关系
empty_dict = {}
# 字典初始化
filled_dict = {"one": 1, "two": 2, "three": 3}
# 字典也用中括号访问元素
filled_dict["one"] #=> 1
# 把所有的键保存在列表中
filled_dict.keys() #=> ["three", "two", "one"]
# 键的顺序并不是唯一的,得到的不一定是这个顺序
# 把所有的值保存在列表中
filled_dict.values() #=> [3, 2, 1]
# 和键的顺序相同
# 判断一个键是否存在
"one" in filled_dict #=> True
1 in filled_dict #=> False
# 查询一个不存在的键会抛出键异常
filled_dict["four"] # 键异常
# 用get方法来避免键异常
filled_dict.get("one") #=> 1
filled_dict.get("four") #=> None
# get方法支持在不存在的时候返回一个默认值
filled_dict.get("one", 4) #=> 1
filled_dict.get("four", 4) #=> 4
# Setdefault是一个更安全的添加字典元素的方法
filled_dict.setdefault("five", 5) #filled_dict["five"] 的值为 5
filled_dict.setdefault("five", 6) #filled_dict["five"] 的值仍然是 5
# 集合储存无顺序的元素
empty_set = set()
# 出事话一个集合
some_set = set([1,2,2,3,4]) # filled_set 现在是 set([1, 2, 3, 4])
# Python 2.7 之后,大括号可以用来表示集合
filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
# 为集合添加元素
filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5}
# 用&来实现集合的交
other_set = {3, 4, 5, 6}
filled_set & other_set #=> {3, 4, 5}
# 用|来实现集合的并
filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
# 用-来实现集合的差
{1,2,3,4} - {2,3,5} #=> {1, 4}
# 用in来判断元素是否存在于集合中
2 in filled_set #=> True
10 in filled_set #=> False
####################################################
## 3. 控制流程
####################################################
# 新建一个变量
some_var = 5
# 这是个if语句在python中缩进是很重要的。
# 会输出 "some var is smaller than 10"
if some_var > 10:
print "some_var is totally bigger than 10."
elif some_var < 10: # 这个 elif 语句是不必须的
print "some_var is smaller than 10."
else: # 也不是必须的
print "some_var is indeed 10."
"""
用for循环遍历列表
输出:
dog is a mammal
cat is a mammal
mouse is a mammal
"""
for animal in ["dog", "cat", "mouse"]:
# 你可以用 % 来格式化字符串
print "%s is a mammal" % animal
"""
`range(number)` 返回从0到给定数字的列表
输出:
0
1
2
3
"""
for i in range(4):
print i
"""
While循环
输出:
0
1
2
3
"""
x = 0
while x < 4:
print x
x += 1 # Shorthand for x = x + 1
# 用 try/except块来处理异常
# Python 2.6 及以上适用:
try:
# 用raise来抛出异常
raise IndexError("This is an index error")
except IndexError as e:
pass # Pass就是什么都不做不过通常这里会做一些恢复工作
####################################################
## 4. 函数
####################################################
# 用def来新建函数
def add(x, y):
print "x is %s and y is %s" % (x, y)
return x + y # Return values with a return statement
# 调用带参数的函数
add(5, 6) #=> 输出 "x is 5 and y is 6" 返回 11
# 通过关键字赋值来调用函数
add(y=6, x=5) # 顺序是无所谓的
# 我们也可以定义接受多个变量的函数,这些变量是按照顺序排列的
def varargs(*args):
return args
varargs(1, 2, 3) #=> (1,2,3)
# 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的
def keyword_args(**kwargs):
return kwargs
# 实际效果:
keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
# 你也可以同时将一个函数定义成两种形式
def all_the_args(*args, **kwargs):
print args
print kwargs
"""
all_the_args(1, 2, a=3, b=4) prints:
(1, 2)
{"a": 3, "b": 4}
"""
# 当调用函数的时候,我们也可以和之前所做的相反,把元组和字典展开为参数
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
all_the_args(*args) # equivalent to foo(1, 2, 3, 4)
all_the_args(**kwargs) # equivalent to foo(a=3, b=4)
all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4)
# Python 有一等函数:
def create_adder(x):
def adder(y):
return x + y
return adder
add_10 = create_adder(10)
add_10(3) #=> 13
# 匿名函数
(lambda x: x > 2)(3) #=> True
# 内置高阶函数
map(add_10, [1,2,3]) #=> [11, 12, 13]
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
# 可以用列表方法来对高阶函数进行更巧妙的引用
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
####################################################
## 5. 类
####################################################
# 我们新建的类是从object类中继承的
class Human(object):
# 类属性,由所有类的对象共享
species = "H. sapiens"
# 基本构造函数
def __init__(self, name):
# 将参数赋给对象成员属性
self.name = name
# 成员方法参数要有self
def say(self, msg):
return "%s: %s" % (self.name, msg)
# 类方法由所有类的对象共享
# 这类方法在调用时,会把类本身传给第一个参数
@classmethod
def get_species(cls):
return cls.species
# 静态方法是不需要类和对象的引用就可以调用的方法
@staticmethod
def grunt():
return "*grunt*"
# 实例化一个类
i = Human(name="Ian")
print i.say("hi") # 输出 "Ian: hi"
j = Human("Joel")
print j.say("hello") # 输出 "Joel: hello"
# 访问类的方法
i.get_species() #=> "H. sapiens"
# 改变共享属性
Human.species = "H. neanderthalensis"
i.get_species() #=> "H. neanderthalensis"
j.get_species() #=> "H. neanderthalensis"
# 访问静态变量
Human.grunt() #=> "*grunt*"
####################################################
## 6. 模块
####################################################
# 我们可以导入其他模块
import math
print math.sqrt(16) #=> 4
# 我们也可以从一个模块中特定的函数
from math import ceil, floor
print ceil(3.7) #=> 4.0
print floor(3.7) #=> 3.0
# 从模块中导入所有的函数
# 警告:不推荐使用
from math import *
# 简写模块名
import math as m
math.sqrt(16) == m.sqrt(16) #=> True
# Python的模块其实只是普通的python文件
# 你也可以创建自己的模块,并且导入它们
# 模块的名字就和文件的名字相同
# 以可以通过下面的信息找找要成为模块需要什么属性或方法
import math
dir(math)
```
## 更多阅读
希望学到更多?试试下面的链接:
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
* [Dive Into Python](http://www.diveintopython.net/)
* [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/)

329
zh-cn/ruby-cn.html.markdown Normal file
View File

@@ -0,0 +1,329 @@
---
language: ruby
filename: learnruby.rb
contributors:
- ["David Underwood", "http://theflyingdeveloper.com"]
- ["Joel Walden", "http://joelwalden.net"]
- ["Luke Holder", "http://twitter.com/lukeholder"]
translators:
- ["Lin Xiangyu", "https://github.com/oa414"]
---
```ruby
# 这是单行注释
=begin
这是多行注释
没人用这个
你也不该用
=end
# 首先,也是最重要的,所有东西都是对象
# 数字是对象
3.class #=> Fixnum
3.to_s #=> "3"
# 一些基本的算术符号
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
# 算术符号只是语法糖而已
# 实际上是调用对象的方法
1.+(3) #=> 4
10.* 5 #=> 50
# 特殊的只也是对象
nil # 空
true # 真
false # 假
nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass
# 相等运算符
1 == 1 #=> true
2 == 1 #=> false
# 不等运算符
1 != 1 #=> false
2 != 1 #=> true
!true #=> false
!false #=> true
# 除了false自己nil是唯一的值为false的对象
!nil #=> true
!false #=> true
!0 #=> false
# 更多比较
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true
# 字符串是对象
'I am a string'.class #=> String
"I am a string too".class #=> String
placeholder = "use string interpolation"
"I can #{placeholder} when using double quoted strings"
#=> "I can use string interpolation when using double quoted strings"
# 输出值
puts "I'm printing!"
# 变量
x = 25 #=> 25
x #=> 25
# 注意赋值语句返回了赋的值
# 这意味着你可以用多重赋值语句
x = y = 10 #=> 10
x #=> 10
y #=> 10
# 按照惯例用snake_case 作为变量名
snake_case = true
# 使用具有描述性的运算符
path_to_project_root = '/good/name/'
path = '/bad/name/'
# 符号Symbols也是对象)
# 符号是不可变的,内部用整数类型表示的可重用的值。通常用它代替字符串来有效地表达有意义的值
:pending.class #=> Symbol
status = :pending
status == :pending #=> true
status == 'pending' #=> false
status == :approved #=> false
# 数组
# 这是一个数组
[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# 数组可以包含不同类型的元素
array = [1, "hello", false] #=> => [1, "hello", false]
# 数组可以被索引
# 从前面开始
array[0] #=> 1
array[12] #=> nil
# 像运算符一样,[var]形式的访问
# 也就是一个语法糖
# 实际上是调用对象的[] 方法
array.[] 0 #=> 1
array.[] 12 #=> nil
# 从尾部开始
array[-1] #=> 5
# 同时指定开始的位置和结束的位置
array[2, 4] #=> [3, 4, 5]
# 或者指定一个范围
array[1..3] #=> [2, 3, 4]
# 像这样往数组增加一个元素
array << 6 #=> [1, 2, 3, 4, 5, 6]
# 哈希表是Ruby的键值对的基本数据结构
# 哈希表由大括号定义
hash = {'color' => 'green', 'number' => 5}
hash.keys #=> ['color', 'number']
# 哈希表可以通过键快速地查询
hash['color'] #=> 'green'
hash['number'] #=> 5
# 查询一个不存在地键将会返回nil
hash['nothing here'] #=> nil
# 用 #each 方法来枚举哈希表:
hash.each do |k, v|
puts "#{k} is #{v}"
end
# 从Ruby 1.9开始, 用符号作为键的时候有特别的记号表示:
new_hash = { defcon: 3, action: true}
new_hash.keys #=> [:defcon, :action]
# 小贴士:数组和哈希表都是可枚举的
# 它们可以共享一些有用的方法比如each, map, count, 和more
# 控制流
if true
"if statement"
elsif false
"else if, optional"
else
"else, also optional"
end
for counter in 1..5
puts "iteration #{counter}"
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
# 然而
# 没人用for循环
# 用`each`来代替,就像这样
(1..5).each do |counter|
puts "iteration #{counter}"
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
counter = 1
while counter <= 5 do
puts "iteration #{counter}"
counter += 1
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
grade = 'B'
case grade
when 'A'
puts "Way to go kiddo"
when 'B'
puts "Better luck next time"
when 'C'
puts "You can do better"
when 'D'
puts "Scraping through"
when 'F'
puts "You failed!"
else
puts "Alternative grading system, eh?"
end
# 函数
def double(x)
x * 2
end
# 函数 (以及所有的方法块) 隐式地返回了最后语句的值
double(2) #=> 4
# 当不存在歧义的时候括号是可有可无的
double 3 #=> 6
double double 3 #=> 12
def sum(x,y)
x + y
end
# 方法的参数通过逗号分隔
sum 3, 4 #=> 7
sum sum(3,4), 5 #=> 12
# yield
# 所有的方法都有一个隐式的块参数
# 可以用yield参数调用
def surround
puts "{"
yield
puts "}"
end
surround { puts 'hello world' }
# {
# hello world
# }
# 用class关键字定义一个类
class Human
# 一个类变量,它被这个类地所有实例变量共享
@@species = "H. sapiens"
# 构造函数
def initialize(name, age=0)
# 将参数name的值赋给实例变量@name
@name = name
# 如果没有给出age, 那么会采用参数列表中地默认地值
@age = age
end
# 基本的 setter 方法
def name=(name)
@name = name
end
# 基本地 getter 方法
def name
@name
end
# 一个类方法以self.开头
# 它可以被类调用,但不能被类的实例调用
def self.say(msg)
puts "#{msg}"
end
def species
@@species
end
end
# 类的例子
jim = Human.new("Jim Halpert")
dwight = Human.new("Dwight K. Schrute")
# 让我们来调用一些方法
jim.species #=> "H. sapiens"
jim.name #=> "Jim Halpert"
jim.name = "Jim Halpert II" #=> "Jim Halpert II"
jim.name #=> "Jim Halpert II"
dwight.species #=> "H. sapiens"
dwight.name #=> "Dwight K. Schrute"
# 调用对象的方法
Human.say("Hi") #=> "Hi"
```