diff options
| -rw-r--r-- | c.html.markdown | 679 | ||||
| -rw-r--r-- | es-es/c-es.html.markdown | 2 | ||||
| -rw-r--r-- | es-es/coffeescript-es.html.markdown | 3 | ||||
| -rw-r--r-- | fr-fr/ruby-fr.html.markdown | 407 | ||||
| -rw-r--r-- | java.html.markdown | 4 | ||||
| -rw-r--r-- | javascript.html.markdown | 246 | ||||
| -rw-r--r-- | ko-kr/java-kr.html.markdown | 406 | ||||
| -rw-r--r-- | objective-c.html.markdown | 4 | ||||
| -rw-r--r-- | pt-br/ruby-pt.html.markdown | 384 | ||||
| -rw-r--r-- | ru-ru/clojure-ru.html.markdown | 426 | ||||
| -rw-r--r-- | ru-ru/php-ru.html.markdown | 658 | ||||
| -rw-r--r-- | ru-ru/python-ru.html.markdown | 486 | ||||
| -rw-r--r-- | ruby-ecosystem.html.markdown | 2 | ||||
| -rw-r--r-- | ruby.html.markdown | 6 | ||||
| -rw-r--r-- | zh-cn/go-zh.html.markdown | 279 | 
15 files changed, 3579 insertions, 413 deletions
| diff --git a/c.html.markdown b/c.html.markdown index d243b19d..00b13cb0 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,23 +1,25 @@  --- -name: c -category: language -language: c -filename: learnc.c -contributors: -    - ["Adam Bard", "http://adambard.com/"] +- name: c +- category: language +- language: c +- filename: learnc.c +- contributors: + - [Adam Bard](http://adambard.com/) + - [Árpád Goretity](http://twitter.com/H2CO3_iOS) +  --- -Ah, C. Still the language of modern high-performance computing. +Ah, C. Still **the** language of modern high-performance computing.  C is the lowest-level language most programmers will ever use, but  it more than makes up for it with raw speed. Just be aware of its manual  memory management and C will take you as far as you need to go.  ```c -// Single-line comments start with // +// Single-line comments start with // - only available in C99 and later.  /* -Multi-line comments look like this. +Multi-line comments look like this. They work in C89 as well.  */  // Import headers with #include @@ -25,6 +27,17 @@ Multi-line comments look like this.  #include <stdio.h>  #include <string.h> +// file names between <angle brackets> are headers from the C standard library. +// They are searched for by the preprocessor in the system include paths +// (usually /usr/lib on Unices, can be controlled with the -I<dir> option if you are using GCC or clang.) +// For your own headers, use double quotes instead of angle brackets: +#include "my_header.h" + +// The C preprocessor introduces an almost fully-featured macro language. It's useful, but +// it can be confusing (and what's even worse, it can be misused). Read the +// Wikipedia article on the C preprocessor for further information: +// http://en.wikipedia.org/wiki/C_preprocessor +  // Declare function signatures in advance in a .h file, or at the top of  // your .c file.  void function_1(); @@ -33,261 +46,347 @@ void function_2();  // Your program's entry point is a function called  // main with an integer return type.  int main() { - -// print output using printf, for "print formatted" -// %d is an integer, \n is a newline -printf("%d\n", 0); // => Prints 0 -// All statements must end with a semicolon - -/////////////////////////////////////// -// Types -/////////////////////////////////////// - -// You have to declare variables before using them. A variable declaration -// requires you to specify its type; a variable's type determines its size -// in bytes. - -// ints are usually 4 bytes  -int x_int = 0; - -// shorts are usually 2 bytes -short x_short = 0; - -// chars are guaranteed to be 1 byte -char x_char = 0; -char y_char = 'y'; // Char literals are quoted with '' - -// longs are often 4 to 8 bytes; long longs are guaranteed to be at least -// 64 bits -long x_long = 0; -long long x_long_long = 0;  - -// floats are usually 32-bit floating point numbers -float x_float = 0.0; - -// doubles are usually 64-bit floating-point numbers -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 -// signed value of the same size. -unsigned char ux_char; -unsigned short ux_short; -unsigned int ux_int; -unsigned long long ux_long_long; - -// Other than char, which is always 1 byte, these types vary in size depending -// on your machine. sizeof(T) gives you the size of a variable with type T in  -// bytes so you can express the size of these types in a portable way. -// For example, -printf("%lu\n", sizeof(int)); // => 4 (on machines with 4-byte words) - -// Arrays must be initialized with a concrete size. -char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes -int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes -                      // (assuming 4-byte words) - - -// You can initialize an array to 0 thusly: -char my_array[20] = {0}; - -// Indexing an array is like other languages -- or, -// rather, other languages are like C -my_array[0]; // => 0 - -// Arrays are mutable; it's just memory! -my_array[1] = 2; -printf("%d\n", my_array[1]); // => 2 - -// Strings are just arrays of chars terminated by a NUL (0x00) byte, -// represented in strings as the special character '\0'. -// (We don't have to include the NUL byte in string literals; the compiler -//  inserts it at the end of the array for us.) -char a_string[20] = "This is a string"; -printf("%s\n", a_string); // %s formats a string - -/* -You may have noticed that a_string is only 16 chars long. -Char #17 is the NUL byte.  -Chars #18, 19 and 20 have undefined values. -*/ - -printf("%d\n", a_string[16]); // => 0 - -/////////////////////////////////////// -// Operators -/////////////////////////////////////// - -int i1 = 1, i2 = 2; // Shorthand for multiple declaration -float f1 = 1.0, f2 = 2.0; - -// Arithmetic is straightforward -i1 + i2; // => 3 -i2 - i1; // => 1 -i2 * i1; // => 2 -i1 / i2; // => 0 (0.5, but truncated towards 0) - -f1 / f2; // => 0.5, plus or minus epsilon - -// Modulo is there as well -11 % 3; // => 2 - -// Comparison operators are probably familiar, but -// there is no boolean type in c. We use ints instead. -// 0 is false, anything else is true. (The comparison  -// operators always return 0 or 1.) -3 == 2; // => 0 (false) -3 != 2; // => 1 (true) -3 > 2; // => 1 -3 < 2; // => 0 -2 <= 2; // => 1 -2 >= 2; // => 1 - -// Logic works on ints -!3; // => 0 (Logical not) -!0; // => 1 -1 && 1; // => 1 (Logical and) -0 && 1; // => 0 -0 || 1; // => 1 (Logical or) -0 || 0; // => 0 - -// Bitwise operators! -~0x0F; // => 0xF0 (bitwise negation) -0x0F & 0xF0; // => 0x00 (bitwise AND) -0x0F | 0xF0; // => 0xFF (bitwise OR) -0x04 ^ 0x0F; // => 0x0B (bitwise XOR) -0x01 << 1; // => 0x02 (bitwise left shift (by 1)) -0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) - -/////////////////////////////////////// -// Control Structures -/////////////////////////////////////// - -if (0) { -  printf("I am never run\n"); -} else if (0) { -  printf("I am also never run\n"); -} else { -  printf("I print\n"); -} - -// While loops exist -int ii = 0; -while (ii < 10) { -    printf("%d, ", ii++); // ii++ increments ii in-place, after using its value. -} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - -printf("\n"); - -int kk = 0; -do { -    printf("%d, ", kk); -} while (++kk < 10); // ++kk increments kk in-place, before using its value -// => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - -printf("\n"); - -// For loops too -int jj; -for (jj=0; jj < 10; jj++) { -    printf("%d, ", jj); -} // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " - -printf("\n"); - -/////////////////////////////////////// -// Typecasting -/////////////////////////////////////// - -// Every value in C has a type, but you can cast one value into another type -// if you want. - -int x_hex = 0x01; // You can assign vars with hex literals - -// Casting between types will attempt to preserve their numeric values -printf("%d\n", x_hex); // => Prints 1 -printf("%d\n", (short) x_hex); // => Prints 1 -printf("%d\n", (char) x_hex); // => Prints 1 - -// Types will overflow without warning -printf("%d\n", (char) 257); // => 1 (Max char = 255) - -// Integral types can be cast to floating-point types, and vice-versa. -printf("%f\n", (float)100); // %f formats a float -printf("%lf\n", (double)100); // %lf formats a double -printf("%d\n", (char)100.0); - -/////////////////////////////////////// -// Pointers -/////////////////////////////////////// - -// A pointer is a variable declared to store a memory address. Its declaration will -// also tell you the type of data it points to. You can retrieve the memory address  -// of your variables, then mess with them. - -int x = 0; -printf("%p\n", &x); // Use & to retrieve the address of a variable -// (%p formats a pointer) -// => Prints some address in memory; - -// Pointer types end with * in their declaration -int* px; // px is a pointer to an int -px = &x; // Stores the address of x in px -printf("%p\n", px); // => Prints some address in memory - -// To retreive the value at the address a pointer is pointing to, -// put * in front to de-reference it. -printf("%d\n", *px); // => Prints 0, the value of x, which is what px is pointing to the address of - -// You can also change the value the pointer is pointing to. -// We'll have to wrap the de-reference in parenthesis because -// ++ has a higher precedence than *. -(*px)++; // Increment the value px is pointing to by 1 -printf("%d\n", *px); // => Prints 1 -printf("%d\n", x); // => Prints 1 - -int x_array[20]; // Arrays are a good way to allocate a contiguous block of memory -int xx; -for (xx=0; xx<20; xx++) { -    x_array[xx] = 20 - xx; -} // Initialize x_array to 20, 19, 18,... 2, 1 - -// Declare a pointer of type int and initialize it to point to x_array -int* x_ptr = x_array; -// x_ptr now points to the first element in the array (the integer 20).  -// This works because arrays are actually just pointers to their first element. - -// Arrays are pointers to their first element -printf("%d\n", *(x_ptr)); // => Prints 20 -printf("%d\n", x_array[0]); // => Prints 20 - -// Pointers are incremented and decremented based on their type -printf("%d\n", *(x_ptr + 1)); // => Prints 19 -printf("%d\n", x_array[1]); // => Prints 19 - -// You can also dynamically allocate contiguous blocks of memory with the -// standard library function malloc, which takes one integer argument  -// representing the number of bytes to allocate from the heap. -int* my_ptr = (int*) malloc(sizeof(int) * 20); -for (xx=0; xx<20; xx++) { -    *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx would also work here -} // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) - -// Dereferencing memory that you haven't allocated gives -// unpredictable results -printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? - -// When you're done with a malloc'd block of memory, you need to free it,  -// or else no one else can use it until your program terminates -free(my_ptr); - -// Strings can be char arrays, but are usually represented as char -// pointers: -char* my_str = "This is my very own string"; - -printf("%c\n", *my_str); // => 'T' - -function_1(); +    // print output using printf, for "print formatted" +    // %d is an integer, \n is a newline +    printf("%d\n", 0); // => Prints 0 +    // All statements must end with a semicolon +     +    /////////////////////////////////////// +    // Types +    /////////////////////////////////////// +     +    // You have to declare variables before using them. A variable declaration +    // requires you to specify its type; a variable's type determines its size +    // in bytes. +     +    // ints are usually 4 bytes  +    int x_int = 0; +     +    // shorts are usually 2 bytes +    short x_short = 0; +     +    // chars are guaranteed to be 1 byte +    char x_char = 0; +    char y_char = 'y'; // Char literals are quoted with '' +     +    // longs are often 4 to 8 bytes; long longs are guaranteed to be at least +    // 64 bits +    long x_long = 0; +    long long x_long_long = 0;  +     +    // floats are usually 32-bit floating point numbers +    float x_float = 0.0; +     +    // doubles are usually 64-bit floating-point numbers +    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 +    // signed value of the same size. +    unsigned char ux_char; +    unsigned short ux_short; +    unsigned int ux_int; +    unsigned long long ux_long_long; +     +    // Other than char, which is always 1 byte (but not necessarily 8 bits!), +    // these types vary in size depending on your machine and compiler. +    // sizeof(T) gives you the size of a variable with type T in  +    // bytes so you can express the size of these types in a portable way. +    // sizeof(obj) yields the size of an actual expression (variable, literal, etc.). +    // For example, +    printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words) +     +     +    // It's worth noting that if the argument of the `sizeof` operator is not a type but an expression, +    // then its argument is not evaluated except VLAs (see below). Also, `sizeof()` is an operator, not a function, +    // furthermore, the value it yields is a compile-time constant (except when used on VLAs, again.) +    int a = 1; +    size_t size = sizeof(a++); // a++ is not evaluated +    printf("sizeof(a++) = %zu where a = %d\n", size, a); +    // the above code prints "sizeof(a++) = 4 where a = 1" (on a usual 32-bit architecture) +     +    // Arrays must be initialized with a concrete size. +    char my_char_array[20]; // This array occupies 1 * 20 = 20 bytes +    int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes +                          // (assuming 4-byte words) +     +     +    // You can initialize an array to 0 thusly: +    char my_array[20] = {0}; +     +    // Indexing an array is like other languages -- or, +    // rather, other languages are like C +    my_array[0]; // => 0 +     +    // Arrays are mutable; it's just memory! +    my_array[1] = 2; +    printf("%d\n", my_array[1]); // => 2 +     +    // In C99 (and as an optional feature in C11), variable-length arrays (VLAs) can be declared as well. +    // The size of such an array need not be a compile time constant: +    printf("Enter the array size: "); // ask the user for an array size +    char buf[0x100]; +    fgets(buf, sizeof buf, stdin); +    size_t size = strtoul(buf, NULL, 10); // strtoul parses a string to an unsigned integer +    int var_length_array[size]; // declare the VLA +    printf("sizeof array = %zu\n", sizeof var_length_array); +     +    // A possible outcome of this program may be: +    Enter the array size: 10 +    sizeof array = 40 +     +    // Strings are just arrays of chars terminated by a NUL (0x00) byte, +    // represented in strings as the special character '\0'. +    // (We don't have to include the NUL byte in string literals; the compiler +    //  inserts it at the end of the array for us.) +    char a_string[20] = "This is a string"; +    printf("%s\n", a_string); // %s formats a string +     +    /* +     You may have noticed that a_string is only 16 chars long. +     Char #17 is the NUL byte.  +     Chars #18, 19 and 20 are 0 as well - if an initializer list (in this case, the string literal) +     has less elements than the array it is initializing, then excess array elements are implicitly +     initialized to zero. This is why int ar[10] = { 0 } works as expected intuitively. +    */ +     +    printf("%d\n", a_string[16]); // => 0 +     +    // So string literals are strings enclosed within double quotes, but if we have characters +    // between single quotes, that's a character literal. +    // It's of type `int`, and *not* `char` (for historical reasons). +    int cha = 'a'; // fine +    char chb = 'a'; // fine too (implicit conversion from int to char - truncation) +     +    /////////////////////////////////////// +    // Operators +    /////////////////////////////////////// +     +    int i1 = 1, i2 = 2; // Shorthand for multiple declaration +    float f1 = 1.0, f2 = 2.0; +     +    // Arithmetic is straightforward +    i1 + i2; // => 3 +    i2 - i1; // => 1 +    i2 * i1; // => 2 +    i1 / i2; // => 0 (0.5, but truncated towards 0) +     +    f1 / f2; // => 0.5, plus or minus epsilon - floating-point numbers and calculations are not exact +     +    // Modulo is there as well +    11 % 3; // => 2 +     +    // Comparison operators are probably familiar, but +    // there is no boolean type in c. We use ints instead. +    // (Or _Bool or bool in C99.) +    // 0 is false, anything else is true. (The comparison  +    // operators always yield 0 or 1.) +    3 == 2; // => 0 (false) +    3 != 2; // => 1 (true) +    3 > 2; // => 1 +    3 < 2; // => 0 +    2 <= 2; // => 1 +    2 >= 2; // => 1 +     +    // C is not Python - comparisons don't chain. +    int a = 1; +    // WRONG: +    int between_0_and_2 = 0 < a < 2; +    // Correct: +    int between_0_and_2 = 0 < a && a < 2; +     +    // Logic works on ints +    !3; // => 0 (Logical not) +    !0; // => 1 +    1 && 1; // => 1 (Logical and) +    0 && 1; // => 0 +    0 || 1; // => 1 (Logical or) +    0 || 0; // => 0 +     +    // Bitwise operators! +    ~0x0F; // => 0xF0 (bitwise negation, "1's complement") +    0x0F & 0xF0; // => 0x00 (bitwise AND) +    0x0F | 0xF0; // => 0xFF (bitwise OR) +    0x04 ^ 0x0F; // => 0x0B (bitwise XOR) +    0x01 << 1; // => 0x02 (bitwise left shift (by 1)) +    0x02 >> 1; // => 0x01 (bitwise right shift (by 1)) +     +    // Be careful when shifting signed integers - the following are all undefined behavior: +    // - shifting into the sign bit of a signed integer (int a = 1 << 32) +    // - left-shifting a negative number (int a = -1 << 2) +    // - shifting by an offset which is more than or equal to the width of the type of the LHS: +    //   int a = 1 << 32; // UB if int is 32 bits wide +     +    /////////////////////////////////////// +    // Control Structures +    /////////////////////////////////////// +     +    if (0) { +      printf("I am never run\n"); +    } else if (0) { +      printf("I am also never run\n"); +    } else { +      printf("I print\n"); +    } +     +    // While loops exist +    int ii = 0; +    while (ii < 10) { +        printf("%d, ", ii++); // ii++ increments ii in-place, after yielding its value ("postincrement"). +    } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " +     +    printf("\n"); +     +    int kk = 0; +    do { +        printf("%d, ", kk); +    } while (++kk < 10); // ++kk increments kk in-place, and yields the already incremented value ("preincrement") +    // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " +     +    printf("\n"); +     +    // For loops too +    int jj; +    for (jj=0; jj < 10; jj++) { +        printf("%d, ", jj); +    } // => prints "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " +     +    printf("\n"); +     +    // branching with multiple choices: switch() +    switch (some_integral_expression) { +    case 0: // labels need to be integral *constant* epxressions +        do_stuff(); +        break; // if you don't break, control flow falls over labels - you usually don't want that. +    case 1: +        do_something_else(); +        break; +    default: +        // if `some_integral_expression` didn't match any of the labels +        fputs("error!\n", stderr); +        exit(-1); +        break; +    } +         +     +    /////////////////////////////////////// +    // Typecasting +    /////////////////////////////////////// +     +    // Every value in C has a type, but you can cast one value into another type +    // if you want (with some constraints). +     +    int x_hex = 0x01; // You can assign vars with hex literals +     +    // Casting between types will attempt to preserve their numeric values +    printf("%d\n", x_hex); // => Prints 1 +    printf("%d\n", (short) x_hex); // => Prints 1 +    printf("%d\n", (char) x_hex); // => Prints 1 +     +    // Types will overflow without warning +    printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) +    // printf("%d\n", (unsigned char) 257); would be undefined behavior - `char' is usually signed +    // on most modern systems, and signed integer overflow invokes UB. +    // Also, for determining the maximal value of a `char`, a `signed char` and an `unisigned char`, +    // respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from <limits.h> +     +    // Integral types can be cast to floating-point types, and vice-versa. +    printf("%f\n", (float)100); // %f formats a float +    printf("%lf\n", (double)100); // %lf formats a double +    printf("%d\n", (char)100.0); +     +    /////////////////////////////////////// +    // Pointers +    /////////////////////////////////////// +     +    // A pointer is a variable declared to store a memory address. Its declaration will +    // also tell you the type of data it points to. You can retrieve the memory address  +    // of your variables, then mess with them. +     +    int x = 0; +    printf("%p\n", (void *)&x); // Use & to retrieve the address of a variable +    // (%p formats an object pointer of type void *) +    // => Prints some address in memory; +     +     +    // Pointers start with * in their declaration +    int *px, not_a_pointer; // px is a pointer to an int +    px = &x; // Stores the address of x in px +    printf("%p\n", (void *)px); // => Prints some address in memory +    printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); +    // => Prints "8, 4" on a typical 64-bit system +     +    // To retreive the value at the address a pointer is pointing to, +    // put * in front to de-reference it. +    // Note: yes, it may be confusing that '*' is used for _both_ declaring a pointer and dereferencing it. +    printf("%d\n", *px); // => Prints 0, the value of x, which is what px is pointing to the address of +     +    // You can also change the value the pointer is pointing to. +    // We'll have to wrap the de-reference in parenthesis because +    // ++ has a higher precedence than *. +    (*px)++; // Increment the value px is pointing to by 1 +    printf("%d\n", *px); // => Prints 1 +    printf("%d\n", x); // => Prints 1 +     +    int x_array[20]; // Arrays are a good way to allocate a contiguous block of memory +    int xx; +    for (xx = 0; xx < 20; xx++) { +        x_array[xx] = 20 - xx; +    } // Initialize x_array to 20, 19, 18,... 2, 1 +     +    // Declare a pointer of type int and initialize it to point to x_array +    int* x_ptr = x_array; +    // x_ptr now points to the first element in the array (the integer 20).  +    // This works because arrays often decay into pointers to their first element. +    // For example, when an array is passed to a function or is assigned to a pointer, +    // it decays into (implicitly converted to) a pointer. +    // Exceptions: when the array is the argument of the `&` (address-od) operator: +    int arr[10]; +    int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`! It's of type "pointer to array" (of ten `int`s). +    // or when the array is a string literal used for initializing a char array: +    char arr[] = "foobarbazquirk"; +    // or when it's the argument of the `sizeof` or `alignof` operator: +    int arr[10]; +    int *ptr = arr; // equivalent with int *ptr = &arr[0]; +    printf("%zu %zu\n", sizeof arr, sizeof ptr); // probably prints "40, 4" or "40, 8" +     + +    // Pointers are incremented and decremented based on their type +    // (this is called pointer arithmetic) +    printf("%d\n", *(x_ptr + 1)); // => Prints 19 +    printf("%d\n", x_array[1]); // => Prints 19 +     +    // You can also dynamically allocate contiguous blocks of memory with the +    // standard library function malloc, which takes one argument of type size_t +    // representing the number of bytes to allocate (usually from the heap, although this +    // may not be true on e. g. embedded systems - the C standard says nothing about it). +    int *my_ptr = malloc(sizeof(*my_ptr) * 20); +    for (xx = 0; xx < 20; xx++) { +        *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx would also work here, and it's also more readable +    } // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints) +     +    // Dereferencing memory that you haven't allocated gives +    // "unpredictable results" - the program is said to invoke "undefined behavior" +    printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? It may even crash. +     +    // When you're done with a malloc'd block of memory, you need to free it,  +    // or else no one else can use it until your program terminates +    // (this is called a "memory leak"): +    free(my_ptr); +     +    // Strings are arrays of char, but they are usually represented as a +    // pointer-to-char (which is a pointer to the first element of the array). +    // It's good practice to use `const char *' when referring to a string literal, +    // since string literals shall not be modified (i. e. "foo"[0] = 'a' is ILLEGAL.) +    const char *my_str = "This is my very own string literal"; +    printf("%c\n", *my_str); // => 'T' +     +    // This is not the case if the string is an array (potentially initialized with a string literal) +    // that resides in writable memory, as in: +    char foo[] = "foo"; +    foo[0] = 'a'; // this is legal, foo now contains "aoo" +     +    function_1();  } // end main function  /////////////////////////////////////// @@ -297,7 +396,8 @@ function_1();  // Function declaration syntax:  // <return type> <function name>(<args>) -int add_two_ints(int x1, int x2){ +int add_two_ints(int x1, int x2) +{      return x1 + x2; // Use return to return a value  } @@ -309,10 +409,12 @@ Example: in-place string reversal  */  // A void function returns no value -void str_reverse(char* str_in){ +void str_reverse(char *str_in) +{      char tmp; -    int ii=0, len = strlen(str_in); // Strlen is part of the c standard library -    for(ii=0; ii<len/2; ii++){ +    int ii = 0; +    size_t len = strlen(str_in); // `strlen()` is part of the c standard library +    for (ii = 0; ii < len / 2; ii++) {          tmp = str_in[ii];          str_in[ii] = str_in[len - ii - 1]; // ii-th char from end          str_in[len - ii - 1] = tmp; @@ -333,15 +435,20 @@ printf("%s\n", c); // => ".tset a si sihT"  typedef int my_type;  my_type my_type_var = 0; -// Structs are just collections of data +// Structs are just collections of data, the members are allocated sequentially, in the order they are written:  struct rectangle {      int width;      int height;  }; +// it's generally not true that sizeof(struct rectangle) == sizeof(int) + sizeof(int) due to +// potential padding between the structure members (this is for alignment reasons. Probably won't +// happen if all members are of the same type, but watch out! +// See http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member +// for further information. -void function_1(){ - +void function_1() +{      struct rectangle my_rec;      // Access struct members with . @@ -349,37 +456,45 @@ void function_1(){      my_rec.height = 20;      // You can declare pointers to structs -    struct rectangle* my_rec_ptr = &my_rec; +    struct rectangle *my_rec_ptr = &my_rec;      // Use dereferencing to set struct pointer members...      (*my_rec_ptr).width = 30; -    // ... or use the -> shorthand +    // ... or even better: prefer the -> shorthand for the sake of readability      my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10;  }  // You can apply a typedef to a struct for convenience  typedef struct rectangle rect; -int area(rect r){ +int area(rect r) +{      return r.width * r.height;  } +// if you have large structs, you can pass them "by pointer" to avoid copying the whole struct: +int area(const rect *r) +{ +    return r->width * r->height; +} +  ///////////////////////////////////////  // Function pointers   ///////////////////////////////////////  /*  At runtime, functions are located at known memory addresses. Function pointers are -much likely any other pointer (they just store a memory address), but can be used  +much like any other pointer (they just store a memory address), but can be used   to invoke functions directly, and to pass handlers (or callback functions) around.  However, definition syntax may be initially confusing.  Example: use str_reverse from a pointer  */ -void str_reverse_through_pointer(char * str_in) { +void str_reverse_through_pointer(char *str_in) {      // Define a function pointer variable, named f.       void (*f)(char *); // Signature should exactly match the target function.      f = &str_reverse; // Assign the address for the actual function (determined at runtime) +    // f = str_reverse; would work as well - functions decay into pointers, similar to arrays      (*f)(str_in); // Just calling the function through the pointer      // f(str_in); // That's an alternative but equally valid syntax for calling it.  } @@ -391,7 +506,7 @@ Function pointers are usually typedef'd for simplicity and readability, as follo  typedef void (*my_fnp_type)(char *); -// The used when declaring the actual pointer variable: +// Then used when declaring the actual pointer variable:  // ...  // my_fnp_type f;  @@ -400,7 +515,15 @@ typedef void (*my_fnp_type)(char *);  ## Further Reading  Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language) +It is *the* book about C, written by the creators of C. Be careful, though - it's ancient and it contains some +inaccuracies (well, ideas that are not considered good anymore) or now-changed practices. + +Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/). + +If you have a question, read the [compl.lang.c Frequently Asked Questions](http://c-faq.com). -Another good resource is [Learn C the hard way](http://c.learncodethehardway.org/book/) +It's very important to use proper spacing, indentation and to be consistent with your coding style in general. +Readable code is better than clever code and fast code. For a good, sane coding style to adopt, see the +[Linux kernel coding stlye](https://www.kernel.org/doc/Documentation/CodingStyle).  Other than that, Google is your friend. diff --git a/es-es/c-es.html.markdown b/es-es/c-es.html.markdown index b109f761..5d3aae0c 100644 --- a/es-es/c-es.html.markdown +++ b/es-es/c-es.html.markdown @@ -284,7 +284,7 @@ for (xx=0; xx<20; xx++) {  // impredecibles  printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? -// Cuando hallas acabado con el bloque de memoría malloc, necesitas  +// Cuando hayas 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); diff --git a/es-es/coffeescript-es.html.markdown b/es-es/coffeescript-es.html.markdown index a58c0d07..78bb9be5 100644 --- a/es-es/coffeescript-es.html.markdown +++ b/es-es/coffeescript-es.html.markdown @@ -14,7 +14,8 @@ filename: coffeescript-es.coffee  # Los comentarios son como en Ruby y Python, usan almohadillas.  ### -Los comentarios en bloque son como estos, y se traducen directamente a '/*' y '*/' para el código JavaScript resultante. +Los comentarios en bloque son como estos, y se traducen directamente a '/*' y '*/' +para el código JavaScript resultante.  Deberías entender la mayor parte de la semántica de JavaScript antes de continuar.  ### diff --git a/fr-fr/ruby-fr.html.markdown b/fr-fr/ruby-fr.html.markdown new file mode 100644 index 00000000..5efb2f3c --- /dev/null +++ b/fr-fr/ruby-fr.html.markdown @@ -0,0 +1,407 @@ +--- +language: ruby +filename: learnruby-fr.rb +contributors: +  - ["David Underwood", "http://theflyingdeveloper.com"] +  - ["Joel Walden", "http://joelwalden.net"] +  - ["Luke Holder", "http://twitter.com/lukeholder"] +  - ["Tristan Hume", "http://thume.ca/"] +  - ["Nick LaMuro", "https://github.com/NickLaMuro"] +translators: +  - ["Geoffrey Roguelon", "https://github.com/GRoguelon"] +  - ["Nami-Doc", "https://github.com/Nami-Doc"] +lang: fr-fr +--- + +```ruby +# Ceci est un commentaire + +=begin +Ceci est un commentaire multiligne +Personne ne les utilise +Vous devriez en faire de même +=end + +# Tout d'abord : Tout est un objet. + +# Les nombres sont des objets + +3.class #=> Fixnum + +3.to_s #=> "3" + +# Les opérateurs de base +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# Les opérateurs sont juste des raccourcis +# pour appeler une méthode sur un objet +1.+(3) #=> 4 +10.* 5 #=> 50 + +# Les valeurs spéciales sont des objets +nil # Nul +true # Vrai +false # Faux + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# Égalité +1 == 1 #=> true +2 == 1 #=> false + +# Inégalité +1 != 1 #=> false +2 != 1 #=> true +!true  #=> false +!false #=> true + +# à part false lui-même, nil est la seule autre valeur 'false' + +!nil   #=> true +!false #=> true +!0     #=> false + +# Plus de comparaisons +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# Les chaînes de caractères sont des objets + +'Je suis une chaîne de caractères'.class #=> String +"Je suis également une chaîne de caractères".class #=> String + +placeholder = "utiliser l'interpolation de chaîne de caractères" +"Je peux #{placeholder} quand j'utilise les guillemets" +#=> "Je peux utiliser l'interpolation de chaîne de caractères quand j'utilise les guillemets" + +# Affichez un message +puts "J'affiche à l'écran!" + +# Variables +x = 25 #=> 25 +x #=> 25 + +# Notez que l'affectation retourne la valeur affectée. +# Cela signifie que vous pouvez affecter plusieurs fois de suite : + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# Par convention, utilisez la notation underscore +# pour nommer les variables +snake_case = true + +# Utilisez des noms de variable explicites +path_to_project_root = '/nom/correct/' +path = '/mauvais/nom/' + +# Symboles (aussi des objets) +# Les symboles sont immuables, constants, +# réutilisables et représentés en interne +# par une valeur entière. Ils sont souvent +# utilisés à la place des chaînes de caractères +# pour transmettre efficacement des valeurs +# spécifiques ou significatives + +:pending.class #=> Symbol + +status = :pending + +status == :pending #=> true + +status == 'pending' #=> false + +status == :approved #=> false + +# Tableaux + +# Ceci est un tableau +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# Les tableaux contiennent différents types d'élément. + +[1, "hello", false] #=> [1, "hello", false] + +# Les tableaux peuvent être indexés +# Du début +array[0] #=> 1 +array[12] #=> nil + +# Comme les opérateurs, la syntaxe [var] est juste un raccourci +# pour appeler la méthode [] d'un objet +array.[] 0 #=> 1 +array.[] 12 #=> nil + +# Depuis la fin +array[-1] #=> 5 + +# Avec un index de début et de fin +array[2, 4] #=> [3, 4, 5] + +# Ou avec un intervalle +array[1..3] #=> [2, 3, 4] + +# Ajoutez un élément au tableau comme ceci +array << 6 #=> [1, 2, 3, 4, 5, 6] + +# Les Hash sont des dictionnaires Ruby contenant des paires de clé/valeur. +# Les Hash sont délimitées par des accolades : +hash = {'color' => 'green', 'number' => 5} + +hash.keys #=> ['color', 'number'] + +# Les Hash retournent la valeur +# en utilisant la clé associée à la valeur : +hash['color'] #=> 'green' +hash['number'] #=> 5 + +# Recherchez une clé inexistante dans une Hash retourne nil : +hash['nothing here'] #=> nil + +# Depuis Ruby 1.9, Une syntaxe spécifique est apparue en utilisant les symboles comme clés : + +new_hash = { defcon: 3, action: true} + +new_hash.keys #=> [:defcon, :action] + +# Astuce : Les tableaux et les Hash sont dénombrables +# Ils partagent un certain nombre de méthodes pratiques +# telle que each, map, count, etc... + +# Structures de contrôle + +if true +  "si instruction" +elsif false +  "autrement si, facultatif" +else +  "autrement, également facultatif" +end + +for compteur in 1..5 +  puts "itération #{compteur}" +end +#=> itération 1 +#=> itération 2 +#=> itération 3 +#=> itération 4 +#=> itération 5 + +# CEPENDANT, l'usage de la boucle for est très rare. +# À la place, utilisez la méthode "each" +# et passez lui un bloc de code. +# Un bloc de code est un ensemble d'instructions que vous pouvez passer à une methode comme "each". +# Les blocs sont similaires aux lambdas, les fonctions anonymes ou les closures dans d'autres langages. +# +# La méthode "each" exécute le bloc de code pour chaque élément de l'intervalle d'éléments. +# Le bloc de code passe un paramètre compteur. +# Appelez la méthode "each" avec un bloc de code comme ceci : + +(1..5).each do |compteur| +  puts "itération #{compteur}" +end +#=> itération 1 +#=> itération 2 +#=> itération 3 +#=> itération 4 +#=> itération 5 + +# Vous pouvez également mettre un bloc de code entre accolades : +(1..5).each {|compteur| puts "itération #{compteur}"} + +# Le contenu des structures de données peut être parcouru +# en utilisant la méthode each. +array.each do |element| +  puts "#{element} est une partie du tableau" +end +hash.each do |cle, valeur| +  puts "#{cle} est #{valeur}" +end + +compteur = 1 +while compteur <= 5 do +  puts "itération #{compteur}" +  compteur += 1 +end +#=> itération 1 +#=> itération 2 +#=> itération 3 +#=> itération 4 +#=> itération 5 + +grade = 'B' + +case grade +when 'A' +  puts "Excellent" +when 'B' +  puts "Plus de chance la prochaine fois" +when 'C' +  puts "Vous pouvez faire mieux" +when 'D' +  puts "C'est pas terrible" +when 'F' +  puts "Vous avez échoué!" +else +  puts "Sytème de notation alternatif" +end + +# Fonctions + +def double(x) +  x * 2 +end + +# Les fonctions (et tous les blocs de code) retournent +# implicitement la valeur de la dernière instruction évaluée +double(2) #=> 4 + +# Les paranthèses sont facultative +# lorsqu'il n'y a pas d'ambiguïté sur le résultat +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x,y) +  x + y +end + +# Les paramètres de méthode sont séparés par des virgules +sum 3, 4 #=> 7 + +sum sum(3,4), 5 #=> 12 + +# yield +# Toutes les méthodes ont un argument facultatif et implicite +# de type bloc de code +# il peut être appelé avec le mot clé 'yield' + +def surround +  puts "{" +  yield +  puts "}" +end + +surround { puts 'Bonjour tout le monde' } + +# { +# Bonjour tout le monde +# } + + +# Définissez une classe avec le mot clé 'class' +class Humain + +  # Une variable de classe +  # est partagée par toutes les instances de cette classe. +  @@espece = "H. sapiens" + +  # Constructeur de classe +  def initialize(nom, age = 0) +    # Affectez l'argument à la variable d'instance 'nom' +    # pour la durée de vie de l'instance de cette classe +    @nom = nom +    # Si le paramètre 'age' est absent, +    # la valeur par défaut définie dans la liste des arguments sera utilisée. +    @age = age +  end + +  # Une simple méthode setter +  def nom=(nom) +    @nom = nom +  end + +  # Une simple méthode getter +  def nom +    @nom +  end + +  # Une méthode de classe utilise le mot clé 'self' +  # pour se distinguer de la méthode d'instance. +  # La méthode sera alors accessible à partir de la classe +  # et non pas de l'instance. +  def self.say(msg) +    puts "#{msg}" +  end + +  def species +    @@species +  end + +end + + +# Instanciez une classe +jim = Humain.new("Jim Halpert") + +dwight = Humain.new("Dwight K. Schrute") + +# Appelez quelques méthodes +jim.espece #=> "H. sapiens" +jim.nom #=> "Jim Halpert" +jim.nom = "Jim Halpert II" #=> "Jim Halpert II" +jim.nom #=> "Jim Halpert II" +dwight.espece #=> "H. sapiens" +dwight.nom #=> "Dwight K. Schrute" + +# Appelez la méthode de classe +Humain.say("Hi") #=> "Hi" + +# Les classes sont également des objets en Ruby. +# Par conséquent, les classes peuvent avoir des variables d'instance. +# Les variables de classe sont partagées parmi +# la classe et ses descendants. + +# Classe parente +class Humain +  @@foo = 0 + +  def self.foo +    @@foo +  end + +  def self.foo=(valeur) +    @@foo = valeur +  end +end + +# Classe fille +class Travailleur < Humain +end + +Humain.foo # 0 +Travailleur.foo # 0 + +Humain.foo = 2 # 2 +Travailleur.foo # 2 + +# Les variables d'instance de classe ne sont pas partagées +# avec les classes héritées. + +class Humain +  @bar = 0 + +  def self.bar +    @bar +  end + +  def self.bar=(valeur) +    @bar = valeur +  end +end + +class Docteur < Humain +end + +Humain.bar # 0 +Docteur.bar # nil + +``` diff --git a/java.html.markdown b/java.html.markdown index b4531635..cdcf620c 100644 --- a/java.html.markdown +++ b/java.html.markdown @@ -405,3 +405,7 @@ Other Topics To Research:  * [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html)  * [Java Code Conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html) + +Books: + +* [Head First Java] (http://www.headfirstlabs.com/books/hfjava/) diff --git a/javascript.html.markdown b/javascript.html.markdown index cc279b9a..fb79949e 100644 --- a/javascript.html.markdown +++ b/javascript.html.markdown @@ -30,83 +30,84 @@ doStuff();  // wherever there's a newline, except in certain cases.  doStuff() -// We'll leave semicolons off here; whether you do or not will depend on your -// personal preference or your project's style guide. +// So that we don't have to worry about those certain cases (for now), we'll +// leave them on.  ///////////////////////////////////  // 1. Numbers, Strings and Operators  // Javascript has one number type (which is a 64-bit IEEE 754 double). -3 // = 3 -1.5 // = 1.5 +3; // = 3 +1.5; // = 1.5  // All the basic arithmetic works as you'd expect. -1 + 1 // = 2 -8 - 1 // = 7 -10 * 2 // = 20 -35 / 5 // = 7 +1 + 1; // = 2 +8 - 1; // = 7 +10 * 2; // = 20 +35 / 5; // = 7  // Including uneven division. -5 / 2 // = 2.5 +5 / 2; // = 2.5  // Bitwise operations also work; when you perform a bitwise operation your float  // is converted to a signed int *up to* 32 bits. -1 << 2 // = 4 +1 << 2; // = 4  // Precedence is enforced with parentheses. -(1 + 3) * 2 // = 8 +(1 + 3) * 2; // = 8  // There are three special not-a-real-number values: -Infinity // result of e.g. 1/0 --Infinity // result of e.g. -1/0 -NaN // result of e.g. 0/0 +Infinity; // result of e.g. 1/0 +-Infinity; // result of e.g. -1/0 +NaN; // result of e.g. 0/0  // There's also a boolean type. -true -false +true; +false;  // Strings are created with ' or ". -'abc' -"Hello, world" +'abc'; +"Hello, world";  // Negation uses the ! symbol -!true // = false -!false // = true +!true; // = false +!false; // = true  // Equality is == -1 == 1 // = true -2 == 1 // = false +1 == 1; // = true +2 == 1; // = false  // Inequality is != -1 != 1 // = false -2 != 1 // = true +1 != 1; // = false +2 != 1; // = true  // More comparisons -1 < 10 // = true -1 > 10 // = false -2 <= 2 // = true -2 >= 2 // = true +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true  // Strings are concatenated with + -"Hello " + "world!" // = "Hello world!" +"Hello " + "world!"; // = "Hello world!"  // and are compared with < and > -"a" < "b" // = true +"a" < "b"; // = true  // Type coercion is performed for comparisons... -"5" == 5 // = true +"5" == 5; // = true  // ...unless you use === -"5" === 5 // = false +"5" === 5; // = false  // You can access characters in a string with charAt -"This is a string".charAt(0) +"This is a string".charAt(0);  // There's also null and undefined -null // used to indicate a deliberate non-value -undefined // used to indicate a value that hasn't been set yet +null; // used to indicate a deliberate non-value +undefined; // used to indicate a value is not currently present (although undefined +           // is actually a value itself) -// null, undefined, NaN, 0 and "" are falsy, and everything else is truthy. +// false, null, undefined, NaN, 0 and "" are falsy, and everything else is truthy.  // Note that 0 is falsy and "0" is truthy, even though 0 == "0".  /////////////////////////////////// @@ -114,57 +115,57 @@ undefined // used to indicate a value that hasn't been set yet  // Variables are declared with the var keyword. Javascript is dynamically typed,  // so you don't need to specify type. Assignment uses a single = character. -var someVar = 5 +var someVar = 5;  // if you leave the var keyword off, you won't get an error... -someOtherVar = 10 +someOtherVar = 10;  // ...but your variable will be created in the global scope, not in the scope  // you defined it in.  // Variables declared without being assigned to are set to undefined. -var someThirdVar // = undefined +var someThirdVar; // = undefined  // There's shorthand for performing math operations on variables: -someVar += 5 // equivalent to someVar = someVar + 5; someVar is 10 now -someVar *= 10 // now someVar is 100 +someVar += 5; // equivalent to someVar = someVar + 5; someVar is 10 now +someVar *= 10; // now someVar is 100  // and an even-shorter-hand for adding or subtracting 1 -someVar++ // now someVar is 101 -someVar-- // back to 100 +someVar++; // now someVar is 101 +someVar--; // back to 100  // Arrays are ordered lists of values, of any type. -var myArray = ["Hello", 45, true] +var myArray = ["Hello", 45, true];  // Their members can be accessed using the square-brackets subscript syntax.  // Array indices start at zero. -myArray[1] // = 45 +myArray[1]; // = 45  // JavaScript's objects are equivalent to 'dictionaries' or 'maps' in other  // languages: an unordered collection of key-value pairs. -{key1: "Hello", key2: "World"} +var myObj = {key1: "Hello", key2: "World"};  // Keys are strings, but quotes aren't required if they're a valid  // JavaScript identifier. Values can be any type. -var myObj = {myKey: "myValue", "my other key": 4} +var myObj = {myKey: "myValue", "my other key": 4};  // Object attributes can also be accessed using the subscript syntax, -myObj["my other key"] // = 4 +myObj["my other key"]; // = 4  // ... or using the dot syntax, provided the key is a valid identifier. -myObj.myKey // = "myValue" +myObj.myKey; // = "myValue"  // Objects are mutable; values can be changed and new keys added. -myObj.myThirdKey = true +myObj.myThirdKey = true;  // If you try to access a value that's not yet set, you'll get undefined. -myObj.myFourthKey // = undefined +myObj.myFourthKey; // = undefined  ///////////////////////////////////  // 3. Logic and Control Structures  // The if structure works as you'd expect. -var count = 1 +var count = 1;  if (count == 3){      // evaluated if count is 3  } else if (count == 4) { @@ -181,10 +182,10 @@ while (true) {  // Do-while loops are like while loops, except they always run at least once.  var input  do { -    input = getInput() +    input = getInput();  } while (!isValid(input)) -// the for loop is the same as C and Java:  +// the for loop is the same as C and Java:  // initialisation; continue condition; iteration.  for (var i = 0; i < 5; i++){      // will run 5 times @@ -192,29 +193,23 @@ for (var i = 0; i < 5; i++){  // && is logical and, || is logical or  if (house.size == "big" && house.colour == "blue"){ -    house.contains = "bear" +    house.contains = "bear";  }  if (colour == "red" || colour == "blue"){      // colour is either red or blue  }  // && and || "short circuit", which is useful for setting default values. -var name = otherName || "default" +var name = otherName || "default";  ///////////////////////////////////  // 4. Functions, Scope and Closures  // JavaScript functions are declared with the function keyword.  function myFunction(thing){ -    return thing.toUpperCase() +    return thing.toUpperCase();  } -myFunction("foo") // = "FOO" - -// Functions can also be defined "anonymously" - without a name: -function(thing){ -    return thing.toLowerCase() -} -// (we can't call our function, since we don't have a name to refer to it with) +myFunction("foo"); // = "FOO"  // JavaScript functions are first class objects, so they can be reassigned to  // different variable names and passed to other functions as arguments - for @@ -222,52 +217,49 @@ function(thing){  function myFunction(){      // this code will be called in 5 seconds' time  } -setTimeout(myFunction, 5000) - -// You can even write the function statement directly in the call to the other -// function. +setTimeout(myFunction, 5000); -setTimeout(function myFunction(){ +// Function objects don't even have to be declared with a name - you can write +// an anonymous function definition directly into the arguments of another. +setTimeout(function(){      // this code will be called in 5 seconds' time -}, 5000) +}, 5000);  // JavaScript has function scope; functions get their own scope but other blocks  // do not.  if (true){ -    var i = 5 +    var i = 5;  } -i // = 5 - not undefined as you'd expect in a block-scoped language +i; // = 5 - not undefined as you'd expect in a block-scoped language  // This has led to a common pattern of "immediately-executing anonymous  // functions", which prevent temporary variables from leaking into the global  // scope.  (function(){ -    var temporary = 5 +    var temporary = 5;      // We can access the global scope by assiging to the 'global object', which      // in a web browser is always 'window'. The global object may have a      // different name in non-browser environments such as Node.js. -    window.permanent = 10 -    // Or, as previously mentioned, we can just leave the var keyword off. -    permanent2 = 15 -})() -temporary // raises ReferenceError -permanent // = 10 -permanent2 // = 15 +    window.permanent = 10; +})(); +temporary; // raises ReferenceError +permanent; // = 10  // One of JavaScript's most powerful features is closures. If a function is  // defined inside another function, the inner function has access to all the -// outer function's variables. +// outer function's variables, even after the outer function exits.  function sayHelloInFiveSeconds(name){ -    var prompt = "Hello, " + name + "!" +    var prompt = "Hello, " + name + "!";      function inner(){ -        alert(prompt) +        alert(prompt);      } -    setTimeout(inner, 5000) -    // setTimeout is asynchronous, so this function will finish without waiting -    // 5 seconds. However, once the 5 seconds is up, inner will still have -    // access to the value of prompt. +    setTimeout(inner, 5000); +    // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will +    // exit immediately, and setTimeout will call inner afterwards. However, +    // because inner is "closed over" sayHelloInFiveSeconds, inner still has +    // access to the 'prompt' variable when it is finally called.  } -sayHelloInFiveSeconds("Adam") // will open a popup with "Hello, Adam!" in 5s +sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s  ///////////////////////////////////  // 5. More about Objects; Constructors and Prototypes @@ -275,44 +267,44 @@ sayHelloInFiveSeconds("Adam") // will open a popup with "Hello, Adam!" in 5s  // Objects can contain functions.  var myObj = {      myFunc: function(){ -        return "Hello world!" +        return "Hello world!";      } -} -myObj.myFunc() // = "Hello world!" +}; +myObj.myFunc(); // = "Hello world!"  // When functions attached to an object are called, they can access the object  // they're attached to using the this keyword.  myObj = {      myString: "Hello world!",      myFunc: function(){ -        return this.myString +        return this.myString;      } -} -myObj.myFunc() // = "Hello world!" +}; +myObj.myFunc(); // = "Hello world!"  // What this is set to has to do with how the function is called, not where  // it's defined. So, our function doesn't work if it isn't called in the  // context of the object. -var myFunc = myObj.myFunc -myFunc() // = undefined +var myFunc = myObj.myFunc; +myFunc(); // = undefined  // Inversely, a function can be assigned to the object and gain access to it  // through this, even if it wasn't attached when it was defined.  var myOtherFunc = function(){ -    return this.myString.toUpperCase() +    return this.myString.toUpperCase();  } -myObj.myOtherFunc = myOtherFunc -myObj.myOtherFunc() // = "HELLO WORLD!" +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!"  // When you call a function with the new keyword, a new object is created, and  // made available to the function via this. Functions designed to be called  // like this are called constructors.  var MyConstructor = function(){ -    this.myNumber = 5 +    this.myNumber = 5;  } -myNewObj = new MyConstructor() // = {myNumber: 5} -myNewObj.myNumber // = 5 +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5  // Every JavaScript object has a 'prototype'. When you go to access a property  // on an object that doesn't exist on the actual object, the interpreter will @@ -323,31 +315,31 @@ myNewObj.myNumber // = 5  // part of the standard; we'll get to standard ways of using prototypes later.  var myObj = {      myString: "Hello world!", -} +};  var myPrototype = {      meaningOfLife: 42,      myFunc: function(){          return this.myString.toLowerCase()      } -} -myObj.__proto__ = myPrototype -myObj.meaningOfLife // = 42 +}; +myObj.__proto__ = myPrototype; +myObj.meaningOfLife; // = 42  // This works for functions, too. -myObj.myFunc() // = "hello world!" +myObj.myFunc(); // = "hello world!"  // Of course, if your property isn't on your prototype, the prototype's  // prototype is searched, and so on.  myPrototype.__proto__ = {      myBoolean: true -} -myObj.myBoolean // = true +}; +myObj.myBoolean; // = true  // There's no copying involved here; each object stores a reference to its  // prototype. This means we can alter the prototype and our changes will be  // reflected everywhere. -myPrototype.meaningOfLife = 43 -myObj.meaningOfLife // = 43 +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43  // We mentioned that __proto__ was non-standard, and there's no standard way to  // change the prototype of an existing object. However, there's two ways to @@ -355,8 +347,8 @@ myObj.meaningOfLife // = 43  // The first is Object.create, which is a recent addition to JS, and therefore  // not available in all implementations yet. -var myObj = Object.create(myPrototype) -myObj.meaningOfLife // = 43 +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43  // The second way, which works anywhere, has to do with constructors.  // Constructors have a property called prototype. This is *not* the prototype of @@ -366,20 +358,20 @@ myConstructor.prototype = {      getMyNumber: function(){          return this.myNumber      } -} -var myNewObj2 = new myConstructor() -myNewObj2.getMyNumber() // = 5 +}; +var myNewObj2 = new myConstructor(); +myNewObj2.getMyNumber(); // = 5  // Built-in types like strings and numbers also have constructors that create  // equivalent wrapper objects. -var myNumber = 12 -var myNumberObj = new Number(12) -myNumber == myNumberObj // = true +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true  // Except, they aren't exactly equivalent. -typeof(myNumber) // = 'number' -typeof(myNumberObj) // = 'object' -myNumber === myNumberObj // = false +typeof(myNumber); // = 'number' +typeof(myNumberObj); // = 'object' +myNumber === myNumberObj; // = false  if (0){      // This code won't execute, because 0 is falsy.  } @@ -390,9 +382,9 @@ if (Number(0)){  // However, the wrapper objects and the regular builtins share a prototype, so  // you can actually add functionality to a string, for instance.  String.prototype.firstCharacter = function(){ -    return this.charAt(0) +    return this.charAt(0);  } -"abc".firstCharacter() // = "a" +"abc".firstCharacter(); // = "a"  // This fact is often used in "polyfilling", which is implementing newer  // features of JavaScript in an older subset of JavaScript, so that they can be @@ -403,10 +395,10 @@ String.prototype.firstCharacter = function(){  if (Object.create === undefined){ // don't overwrite it if it exists      Object.create = function(proto){          // make a temporary constructor with the right prototype -        var Constructor = function(){} -        Constructor.prototype = proto +        var Constructor = function(){}; +        Constructor.prototype = proto;          // then use it to create a new, appropriately-prototyped object -        return new Constructor() +        return new Constructor();      }  }  ``` diff --git a/ko-kr/java-kr.html.markdown b/ko-kr/java-kr.html.markdown new file mode 100644 index 00000000..dcca9b2e --- /dev/null +++ b/ko-kr/java-kr.html.markdown @@ -0,0 +1,406 @@ +--- +language: java +category: language +contributors: +    - ["Jake Prather", "http://github.com/JakeHP"] +translators: +    - ["wikibook", "http://wikibook.co.kr"] +lang: ko-kr +--- + +자바는 일반 목적으로 사용할 수 있고 동시성을 지원하며, 클래스 기반의 객체지향 컴퓨터 프로그래밍 언어입니다. +[더 자세한 사항](http://docs.oracle.com/javase/tutorial/java/index.html) + +```java +// 한 줄짜리 주석은 //로 시작합니다. +/* +여러 줄 주석은 다음과 같은 형태입니다. +*/ +/** +자바독(JavaDoc) 주석은 이렇게 생겼습니다. 자바독 주석은 클래스나 클래스의 +다양한 속성을 기술하는 데 사용됩니다. +*/ + +// java.util 패키지 안에 있는 ArrayList 클래스를 임포트합니다. +import java.util.ArrayList; +// java.security 패키지 안에 있는 모든 클래스를 임포트합니다. +import java.security.*; + +// 각 .java 파일에는 공용(public) 클래스가 들어 있으며, 클래스의 이름은 파일명과 동일합니다. +public class LearnJava { + +    // 프로그램에는 반드시 진입점 역할을 하는 main 메서드가 하나 있어야 합니다. +    public static void main (String[] args) { + +        // System.out.println을 이용해 한 줄을 출력합니다. +        System.out.println("Hello World!"); +        System.out.println( +            "Integer: " + 10 + +            " Double: " + 3.14 + +            " Boolean: " + true); + +        // 줄바꿈 없이 뭔가를 출력하려면 System.out.print를 사용합니다. +        System.out.print("Hello "); +        System.out.print("World"); + + +        /////////////////////////////////////// +        // 타입 & 변수 +        /////////////////////////////////////// + +        // <타입> <이름>과 같은 형태로 변수를 선언합니다. +        // Byte - 부호가 있는 8비트 2의 보수 정수 +        // (-128 <= byte <= 127) +        byte fooByte = 100; + +        // Short - 부호가 있는 16비트 2의 보수 정수 +        // (-32,768 <= short <= 32,767) +        short fooShort = 10000; + +        // Integer - 부호가 있는 32비트 2의 보수 정수 +        // (-2,147,483,648 <= int <= 2,147,483,647) +        int fooInt = 1; + +        // Long - 부호가 있는 64비트 2의 보수 정수 +        // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) +        long fooLong = 100000L; +        // L은 이 변수의 값이 Long 타입임을 나타내는 데 사용됩니다. +        // L이 없는 것들은 기본적으로 정수로 간주됩니다. + +        // 참고: 자바에는 부호 없는(unsigned) 타입이 없습니다. + +        // Float - 단정도 32비트 IEEE 754 부동 소수점 수 +        float fooFloat = 234.5f; +        // f는 이 변수의 값이 float 타입임을 나타내는 데 사용됩니다. +        // f를 지정하지 않으면 double로 간주됩니다. + +        // Double - 배정도 64비트 IEEE 754 부동 소수점 수 +        double fooDouble = 123.4; + +        // Boolean - 참(true) & 거짓(false) +        boolean fooBoolean = true; +        boolean barBoolean = false; + +        // Char - 단일 16비트 유니코드 문자 +        char fooChar = 'A'; + +        // 변수를 변경할 수 없게 만들려면 final을 지정합니다. +        final int HOURS_I_WORK_PER_WEEK = 9001; + +        // 문자열 +        String fooString = "My String Is Here!"; + +        // \n은 새로운 줄을 시작하는 이스케이프 문자입니다. +        String barString = "Printing on a new line?\nNo Problem!"; +        // \t는 탭 문자를 추가하는 이스케이프 문자입니다. +        String bazString = "Do you want to add a tab?\tNo Problem!"; +        System.out.println(fooString); +        System.out.println(barString); +        System.out.println(bazString); + +        // 배열 +        // 배열의 크기는 반드시 선언할 때 결정해야 합니다. +        // 배열을 선언하는 형식은 다음과 같습니다. +        //<자료형> [] <변수명> = new <자료형>[<배열 크기>]; +        int [] intArray = new int[10]; +        String [] stringArray = new String[1]; +        boolean [] booleanArray = new boolean[100]; + +        // 배열을 선언하고 초기화하는 또 다른 방법 +        int [] y = {9000, 1000, 1337}; + +        // 배열 인덱스 - 요소에 접근 +        System.out.println("intArray @ 0: " + intArray[0]); + +        // 배열의 인덱스는 0에서부터 시작하며 변경 가능합니다. +        intArray[1] = 1; +        System.out.println("intArray @ 1: " + intArray[1]); // => 1 + +        // 기타 참고할 만한 자료구조 +        // ArrayLists - 좀 더 많은 기능을 제공하고 크기를 변경 가능하다는 점을 +        //              제외하면 배열과 비슷합니다. +        // LinkedLists +        // Maps +        // HashMaps + +        /////////////////////////////////////// +        // 연산자 +        /////////////////////////////////////// +        System.out.println("\n->Operators"); + +        int i1 = 1, i2 = 2; // 다중 선언의 축약형 + +        // 산술 연산은 이해하기 어렵지 않습니다. +        System.out.println("1+2 = " + (i1 + i2)); // => 3 +        System.out.println("2-1 = " + (i2 - i1)); // => 1 +        System.out.println("2*1 = " + (i2 * i1)); // => 2 +        System.out.println("1/2 = " + (i1 / i2)); // => 0 (0.5를 잘라 버립니다) + +        // 나눗셈 +        System.out.println("11%3 = "+(11 % 3)); // => 2 + +        // 비교 연산자 +        System.out.println("3 == 2? " + (3 == 2)); // => false +        System.out.println("3 != 2? " + (3 != 2)); // => true +        System.out.println("3 > 2? " + (3 > 2)); // => true +        System.out.println("3 < 2? " + (3 < 2)); // => false +        System.out.println("2 <= 2? " + (2 <= 2)); // => true +        System.out.println("2 >= 2? " + (2 >= 2)); // => true + +        // 비트 연산자! +        /* +        ~       단항 보수 연산 +        <<      산술적 왼쪽 시프트 +        >>      산술적 오른쪽 시프트 +        >>>     논리적 오른쪽 시프트 +        &       비트 단위 논리곱(AND) +        ^       비트 단위 배타적 논리합(OR) +        |       비트 단위 논리합(OR) +        */ + +        // 증감 연산자 +        int i = 0; +        System.out.println("\n->Inc/Dec-rementation"); +        System.out.println(i++); //i = 1. 후치 증가 연산 +        System.out.println(++i); //i = 2. 전치 증가 연산 +        System.out.println(i--); //i = 1. 후치 감소 연산 +        System.out.println(--i); //i = 0. 전치 감소 연산 + +        /////////////////////////////////////// +        // 에저 구조 +        /////////////////////////////////////// +        System.out.println("\n->Control Structures"); + +        // if 문은 C 언어와 비슷합니다. +        int j = 10; +        if (j == 10){ +            System.out.println("I get printed"); +        } else if (j > 10) { +            System.out.println("I don't"); +        } else { +            System.out.println("I also don't"); +        } + +        // while 루프 +        int fooWhile = 0; +        while(fooWhile < 100) +        { +            // System.out.println(fooWhile); +            // 카운터를 증가 +            // 99번 반복, fooWhile 0->99 +            fooWhile++; +        } +        System.out.println("fooWhile Value: " + fooWhile); + +        // do-while 루프 +        int fooDoWhile = 0; +        do +        { +            // System.out.println(fooDoWhile); +            // 카운터를 증가 +            // 99번 반복, fooDoWhile 0->99 +            fooDoWhile++; +        }while(fooDoWhile < 100); +        System.out.println("fooDoWhile Value: " + fooDoWhile); + +        // for 루프 +        int fooFor; +        // for 루프 구조 => for(<초기식>; <조건식>; <증감식>) +        for(fooFor=0; fooFor<10; fooFor++){ +            // System.out.println(fooFor); +            // 10번 반복, fooFor 0->9 +        } +        System.out.println("fooFor Value: " + fooFor); + +        // switch-case 문 +        // switch는 byte, short, char, int 자료형을 대상으로 동작합니다. +        // 아울러 열거형을 비롯해 String 클래스 및 원시 타입을 감싼 Character,  +        // Byte, Short, Integer와 같은 몇 가지 특별한 클래스에 대해서도 동작합니다. +        int month = 3; +        String monthString; +        switch (month){ +            case 1: +                    monthString = "January"; +                    break; +            case 2: +                    monthString = "February"; +                    break; +            case 3: +                    monthString = "March"; +                    break; +            default: +                    monthString = "Some other month"; +                    break; +        } +        System.out.println("Switch Case Result: " + monthString); + + +        /////////////////////////////////////// +        // 자료형 변환과 형변환 +        /////////////////////////////////////// + +        // 데이터 변환 + +        // 문자열에서 정수로 변환 +        Integer.parseInt("123");// 정수 버전의 "123"을 반환 + +        // 정수를 문자열로 변환 +        Integer.toString(123);// 문자열 버전의 123을 반환 + +        // 다른 변환에 대해서는 아래 클래스를 확인해 보세요. +        // Double +        // Long +        // String + +        // 형변환 +        // 자바 객채 또한 형변환할 수 있으며, 이와 관련해서 알아야 할 세부사항이 많을뿐더러 +        // 다소 중급 수준에 해당하는 개념들도 다뤄야 합니다. +        // 이와 관련된 사항은 아래 링크를 참고하세요. +        // http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html + + +        /////////////////////////////////////// +        // 클래스와 함수 +        /////////////////////////////////////// + +        System.out.println("\n->Classes & Functions"); + +        // (Bicycle 클래스의 정의) + +        // 클래스를 인스턴스화하려면 new를 사용합니다. +        Bicycle trek = new Bicycle(); + +        // 객체의 메서드를 호출합니다. +        trek.speedUp(3); // 항상 설정자 메서드와 접근자 메서드를 사용해야 합니다. +        trek.setCadence(100); + +        // 현재 객체의 값을 표시할 때는 관례적으로 toString을 사용합니다. +        System.out.println("trek info: " + trek.toString()); + +    } // main 메서드 끝 +} // LearnJava 클래스 끝 + + +// .java 파일 안에 다른 비공개 클래스를 포함할 수 있습니다. + + +// 클래스 선언 문법: +// <public/private/protected> class <클래스명>{ +//    // 데이터 필드, 생성자, 함수가 모두 이곳에 들어갑니다. +//    // 자바에서는 함수를 메서드라고 부릅니다. +// } + +class Bicycle { + +    // Bicycle의 필드와 변수 +    public int cadence; // Public: 어느 곳에서도 접근할 수 있습니다. +    private int speed;  // Private: 클래스 안에서만 접근할 수 있습니다. +    protected int gear; // Protected: 현재 클래스와 하위 클래스에서 접근할 수 있습니다. +    String name; // default: 현재 패키지 안에서만 접근할 수 있습니다. + +    // 생성자는 클래스를 생성하는 방법 중 하나입니다. +    // 다음은 기본 생성자입니다. +    public Bicycle() { +        gear = 1; +        cadence = 50; +        speed = 5; +        name = "Bontrager"; +    } + +    // 다음은 구체화된 생성자입니다(인자를 담고 있습니다) +    public Bicycle(int startCadence, int startSpeed, int startGear, String name) { +        this.gear = startGear; +        this.cadence = startCadence; +        this.speed = startSpeed; +        this.name = name; +    } + +    // 함수 문법: +    // <public/private/protected> <반환형> <함수명>(<인자>) + +    // 자바 클래스는 필드에 대해 접근자 메서드와 설정자 메서드를 구현할 때가 많습니다. + +    // 메서드 선언 문법: +    // <유효범위> <반환형> <메서드명>(<인자>) +    public int getCadence() { +        return cadence; +    } + +    // void 메서드는 반환형이 필요하지 않습니다. +    public void setCadence(int newValue) { +        cadence = newValue; +    } + +    public void setGear(int newValue) { +        gear = newValue; +    } + +    public void speedUp(int increment) { +        speed += increment; +    } + +    public void slowDown(int decrement) { +        speed -= decrement; +    } + +    public void setName(String newName) { +        name = newName; +    } + +    public String getName() { +        return name; +    } + +    // 현재 객체의 속성값을 표시하는 메서드 +    @Override +    public String toString() { +        return "gear: " + gear + +                " cadence: " + cadence + +                " speed: " + speed + +                " name: " + name; +    } +} // Bicycle 클래스의 끝 + +// PennyFarthing은 Bicycle의 하위 클래스입니다. +class PennyFarthing extends Bicycle { +    // (페니 파딩은 앞바퀴가 굉장히 큰 자전거입니다. 기어가 없죠.) + +    public PennyFarthing(int startCadence, int startSpeed){ +        // super를 이용해 부모 생성자를 호출합니다. +        super(startCadence, startSpeed, 0, "PennyFarthing"); +    } + +    // @annotation을 이용해 재정의하는 메서드를 표시해야 합니다. +    // 애노테이션과 애노테이션의 용도에 관한 자세한 내용은 아래 링크를 참고하세요. +    // 애노테이션: http://docs.oracle.com/javase/tutorial/java/annotations/ +    @Override +    public void setGear(int gear) { +        gear = 0; +    } + +} + +``` + +## 기타 참고자료 + +다음 링크를 통해 다양한 주제를 이해하고 구글을 통해 구체적인 예제들을 찾아보세요. + +공부할 만한 기타 주제: + +* [썬/오라클의 자바 자습서](http://docs.oracle.com/javase/tutorial/index.html) + +* [자바 접근 제한자](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) + +* [객체 지향 프로그래밍 개념](http://docs.oracle.com/javase/tutorial/java/concepts/index.html): +    * [상속(Inheritance)](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) +    * [다형성(Polymorphism)](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) +    * [추상화(Abstraction)](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) + +* [예외(Exceptions)](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) + +* [인터페이스(Interfaces)](http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html) + +* [제네릭(Generics)](http://docs.oracle.com/javase/tutorial/java/generics/index.html) + +* [자바 코딩 관례(Java Code Conventions)](http://www.oracle.com/technetwork/java/codeconv-138413.html)
\ No newline at end of file diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 2b1b3c67..b92e3218 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -160,7 +160,7 @@ int main (int argc, const char * argv[])      int jj;      for (jj=0; jj < 4; jj++)      { -        NSLog(@"%d,", ii++); +        NSLog(@"%d,", jj++);      } // => prints "0,"         //           "1,"        //           "2," @@ -256,7 +256,7 @@ int main (int argc, const char * argv[])  }  // Constructors are a way of creating classes -// This is a default constructor which is call when the object is creating +// This is a default constructor which is called when the object is creating  - (id)init  {      if ((self = [super init])) diff --git a/pt-br/ruby-pt.html.markdown b/pt-br/ruby-pt.html.markdown new file mode 100644 index 00000000..8e8ce6a8 --- /dev/null +++ b/pt-br/ruby-pt.html.markdown @@ -0,0 +1,384 @@ +--- +language: ruby +filename: learnruby.rb +contributors: +  - ["Bruno Henrique - Garu", "http://garulab.com"] +  - ["Katyanna Moura", "https://twitter.com/amelie_kn"] +--- + +```ruby +# Isso é um comentário + +=begin +Isso é um comentário multilinha +Ninguém os usa +Você não deve usar também +=end + +# Primeiro e principal: Tudo é um objeto. + +# Números são objetos + +3.class #=> Fixnum + +3.to_s #=> "3" + + +# Um pouco de aritmética básica + +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# Aritimética é apenas açúcar sintático +# para chamar um método de um objeto +1.+(3) #=> 4 +10.* 5 #=> 50 + +# Valores especiais são objetos +nil # Nada para ver aqui +true # verdadeiro +false # falso + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# Igualdade +1 == 1 #=> true +2 == 1 #=> false + +# Desigualdade +1 != 1 #=> false +2 != 1 #=> true +!true  #=> false +!false #=> true + +# além de 'false', 'nil' é o único outro valor falso + +!nil   #=> true +!false #=> true +!0     #=> false + +# Mais comparações +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# Strings são objects + +'Eu sou uma string'.class #=> String +"Eu também sou uma string".class #=> String + +placeholder = "usar interpolação de string" +"Eu posso #{placeholder} quando estiver usando aspas duplas" +#=> "Eu posso usar insterpolação de string quando estiver usando aspas duplas" + +# imprime para output (saída) +puts "Estou imprimindo" + +# Variáveis +x = 25 #=> 25 +x #=> 25 + +# Note que uma atribuição retorna o valor atribuido +# Isso significa que você pode fazer múltiplas atribuições: + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# Por convenção, use snake_case para nomes de variáveis +snake_case = true + +# Use nomes de variáveis descritivos +caminho_para_a_raiz_do_projeto = '/bom/nome/' +caminho = '/nome/ruim/' + +# Símbolos (são objetos) +# Símbolos são imutáveis, são constantes reutilizáveis representadadas internamente por um +# valor inteiro. Eles são frequentemente usados no lugar de strings para transmitir com eficiência os valores +# específicos e significativos + +:pendente.class #=> Symbol + +status = :pendente + +status == :pendente #=> true + +status == 'pendente' #=> false + +status == :aprovado #=> false + +# Arrays + +# Isso é um array +[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# Arrays podem conter diferentes tipos de itens + +array = [1, "Oi", false] #=> => [1, "Oi", false] + +# Arrays podem ser indexados +# a partir do começo +array[0] #=> 1 +array[12] #=> nil + +# Como aritimética, o acesso via [var] +# é apenas açúcar sintático +# para chamar o método [] de um objeto +array.[] 0 #=> 1 +array.[] 12 #=> nil + +# a partir do final +array[-1] #=> 5 + +# Com um índice de começo e fim +array[2, 4] #=> [3, 4, 5] + +# Ou com um intervalo de valores +array[1..3] #=> [2, 3, 4] + +# Adicionar a um array como este +array << 6 #=> [1, 2, 3, 4, 5, 6] + +# Hashes são o principal dicionário de Ruby com pares de chaves(keys)/valor(value). +# Hashes são simbolizados com chaves "{}" +hash = {'cor' => 'verde', 'numero' => 5} + +hash.keys #=> ['cor', 'numero'] + +# Hashes podem ser rapidamente pesquisados pela chave (key) +hash['cor'] #=> 'verde' +hash['numero'] #=> 5 + +# Procurar em um hash por uma chave que não existe retorna nil: +hash['nada aqui'] #=> nil + +# Interar sobre hashes com o método #each: +hash.each do |k, v| +  puts "#{k} is #{v}" +end + +hash.each do |k, v| +  puts "#{k} é #{v}" +end + +# Desde o Ruby 1.9, temos uma sintaxe especial quando usamos símbolos como chaves (keys) + +novo_hash = { defcon: 3, acao: true} + +novo_hash.keys #=> [:defcon, :acao] + +# Dica: Tanto Arrays quanto Hashes são Enumerable. +# Eles compartilham um monte de métodos úteis como each, map, count e mais + +# Estruturas de controle + +if true +  "Se verdadeiro" +elsif false + "else if, opicional" +else + "else, também é opicional" +end + +for contador in 1..5 +  puts "interação #{contador}" +end +#=> contador 1 +#=> contador 2 +#=> contador 3 +#=> contador 4 +#=> contador 5 + +# PORÉM +# Ninguém usa para loops +# Use "each" em vez, dessa forma: + +(1..5).each do |contador| +  puts "interação #{contador}" +end +#=> contador 1 +#=> contador 2 +#=> contador 3 +#=> contador 4 +#=> contador 5 + +contador = 1 +while contador <= 5 do +  puts "interação #{contador}" +  contador += 1 +end +#=> contador 1 +#=> contador 2 +#=> contador 3 +#=> contador 4 +#=> contador 5 + +grau = 'B' + +case grau +when 'A' +  puts "Um longo caminho a percorrer, pequeno gafanhoto" +when 'B' +  puts "Melhor sorte da próxima vez" +when 'C' +  puts "Você pode fazer melhor" +when 'D' +  puts "Scraping through" +when 'F' +  puts "Você falhou" +else +  puts "Alternative grading system, eh?" +end + +# Funções + +def dobrar(x) +  x * 2 +end + +# Funções (e todos os blocos) retornam implicitamente o valor da última linha +dobrar(2) #=> 4 + +# Parênteses são opicionais onde o resultado é claro +dobrar 3 #=> 6 + +dobrar dobrar 3 #=> 12 + +def somar(x,y) +  x + y +end + +# Argumentos de métodos são separados por uma vírgula +somar 3, 4 #=> 7 + +somar somar(3,4), 5 #=> 12 + +# yield +# Todos os métodos possuem implicitamente um paramêntro opcional que é um bloco +# ele pode ser chamado com a palavra chave 'yield' + +def ao_redor +  puts "{" +  yield +  puts "}" +end + +ao_redor { puts 'Olá mundo' } + +# { +# Olá mundo +# } + + +# Define uma classe com a palavra chave 'class' + +class Humano + +  # Uma variável de classe. Ela é compartilhada por todas as instâncias dessa classe +  @@especies = "H. sapiens" + +  # Inicialização básica (contructor) +  def initialize(nome, idade=0) +    # Atribui o argumento para a variável de instancia "nome" do objeto +    @nome = nome +    # Se a idade não for passada, nós definimos um valor padrão na lista de argumentos +    @idade = idade +  end + +  # Método básico para atribuir valor +  def nome=(nome) +    @nome = nome +  end + +  # Método básico de resgatar valor +  def nome +    @nome +  end + +  # Um método de classe usa a palavra chave self para se defenciar dos métodos de instância. +  # Ele só pode ser chamado na classe, não na instancia +  def self.diz(msg) +    puts "#{msg}" +  end + +  def especies +    @@especies +  end + +end + + +# Instanciando uma classe +jim = Humano.new("Jim Halpert") + +dwight = Humano.new("Dwight K. Schrute") + +# Vamos chamar um par de métodos +jim.especies #=> "H. sapiens" + +jim.nome #=> "Jim Halpert" + +jim.nome = "Jim Halpert II" #=> "Jim Halpert II" + +jim.nome #=> "Jim Halpert II" + +dwight.especies #=> "H. sapiens" + +dwight.nome #=> "Dwight K. Schrute" + +# Chamar o método de classe +Humano.diz("Oi") #=> "Oi" + +# Uma classe também é objeto em Ruby. Então uma classe pode possuir variável de instância +# Variáveis de classe são compartilhadas entre a classe e todos os seus descendentes. + + +# Classe base +class Humano +  @@foo = 0 + +  def self.foo +    @@foo +  end + +  def self.foo=(value) +    @@foo = value +  end +end + +#  classe filha +class Trabalhador < Humano +end + +Humano.foo # 0 +Trabalhador.foo # 0 + +Humano.foo = 2 # 2 +Trabalhador.foo # 2 + +# Uma variável de instância não é compartilhada por suas classes decendentes. + +class Humano +  @bar = 0 + +  def self.bar +    @bar +  end + +  def self.bar=(value) +    @bar = value +  end +end + +class Doutor < Humano +end + +Humano.bar # 0 +Doutor.bar # nil + +``` diff --git a/ru-ru/clojure-ru.html.markdown b/ru-ru/clojure-ru.html.markdown new file mode 100644 index 00000000..48c16192 --- /dev/null +++ b/ru-ru/clojure-ru.html.markdown @@ -0,0 +1,426 @@ +--- +language: clojure +filename: learnclojure-ru.clj +contributors: +    - ["Adam Bard", "http://adambard.com/"] +    - ["Alexey Pirogov", "http://twitter.com/alex_pir"] + +--- + +Clojure, это представитель семейства Lisp-подобных языков, разработанный +для Java Virtual Machine. Язык идейно гораздо ближе к чистому +[функциональному программированию](https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5) чем его прародитель Common Lisp, но в то же время обладает набором инструментов для работы с состоянием, +таких как [STM](https://ru.wikipedia.org/wiki/Software_transactional_memory). + +Благодаря такому сочетанию технологий в одном языке, разработка программ, +предполагающих конкурентное выполнение, значительно упрощается +и даже может быть автоматизирована. + +(Последующие примеры кода предполагают выполнение в Clojure версии 1.2 и выше) + + +```clojure +; Комментарии начинаются символом ";". + +; Код на языке Clojure записывается в виде "форм", +; которые представляют собой обычные списки элементов, разделенных пробелами, +; заключённые в круглые скобки +; +; Clojure Reader (инструмент языка, отвечающий за чтение исходного кода), +; анализируя форму, предполагает, что первым элементом формы (т.е. списка) +; является функция или макрос, который следует вызвать, передав ему +; в качестве аргументов остальные элементы списка-формы. + +; Первым вызовом в файле должен быть вызов функции ns, +; которая отвечает за выбор текущего пространства имен (namespace) +(ns learnclojure-ru) + +; Несколько простых примеров: + +; str объединяет в единую строку все свои аргументы +(str "Hello" " " "World") ; => "Hello World" + +; Арифметика тоже выглядит несложно +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 + +; Проверка на равенство (Equality) +(= 1 1) ; => true +(= 2 1) ; => false + +; Для булевой логики вам может понадобиться not +(not true) ; => false + +; Вложенные формы, конечно же, допустимы и работают вполне предсказуемо +(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 + +; Типы +;;;;;;;;;;;;; + +; Clojure использует типы Java для представления булевых значений, +; строк и чисел +; Узнать тип мы можем, использую функцию `class +(class 1)     ; Целочисленные литералы типа по-умолчанию являются java.lang.Long +(class 1.)    ; Числа с плавающей точкой, это java.lang.Double +(class "")    ; Строки всегда заключаются в двойные кавычки +              ; и представляют собой java.lang.String +(class false) ; Булевы значения, это экземпляры java.lang.Boolean +(class nil)   ; "Пустое" значение называется "nil" + +; Если Вы захотите создать список из чисел, вы можете просто +; предварить форму списка символом "'", который подскажет Reader`у, +; что эта форма не требует вычисления +'(+ 1 2) ; => (+ 1 2) +; ("'", это краткая запись формы (quote (+ 1 2)) + +; "Квотированный" список можно вычислить, передав его функции eval +(eval '(+ 1 2)) ; => 3 + +; Коллекции и Последовательности +;;;;;;;;;;;;;;;;;;; + +; Списки (Lists) в clojure структурно представляют собой "связанные списки", +; тогда как Векторы (Vectors), устроены как массивы. +; Векторы и Списки тоже являются классами Java! +(class [1 2 3]); => clojure.lang.PersistentVector +(class '(1 2 3)); => clojure.lang.PersistentList + +; Список может быть записан, как (1 2 3), но в этом случае +; он будет воспринят reader`ом, как вызов функции. +; Есть два способа этого избежать: +; '(1 2 3)     - квотирование, +; (list 1 2 3) - явное конструирование списка с помощью функции list. + +; "Коллекции", это некие наборы данных +; И списки, и векторы являются коллекциями: +(coll? '(1 2 3)) ; => true +(coll? [1 2 3]) ; => true + +; "Последовательности" (seqs), это абстракция над наборами данных, +; элементы которых "упакованы" последовательно. +; Списки - последовательности, а вектора - нет. +(seq? '(1 2 3)) ; => true +(seq? [1 2 3]) ; => false + +; Любая seq предоставляет доступ только к началу последовательности данных, +; не предоставляя информацию о её длине. +; При этом последовательности могут быть и бесконечными, +; т.к. являются ленивыми и предоставляют данные только по требованию! +(range 4) ; => (0 1 2 3) +(range) ; => (0 1 2 3 4 ...) (бесконечная последовательность!) +(take 4 (range)) ;  (0 1 2 3) + +; Добавить элемент в начало списка или вектора можно с помощью функции cons +(cons 4 [1 2 3]) ; => (4 1 2 3) +(cons 4 '(1 2 3)) ; => (4 1 2 3) + +; Функция conj добавляет элемент в коллекцию +; максимально эффективным для неё способом. +; Для списков эффективно добавление в начло, а для векторов - в конец. +(conj [1 2 3] 4) ; => [1 2 3 4] +(conj '(1 2 3) 4) ; => (4 1 2 3) + +; Функция concat объединяет несколько списков и векторов в единый список +(concat [1 2] '(3 4)) ; => (1 2 3 4) + +; Работать с коллекциями удобно с помощью функций filter и map +(map inc [1 2 3]) ; => (2 3 4) +(filter even? [1 2 3]) ; => (2) + +; reduce поможет "свернуть" коллекцию +(reduce + [1 2 3 4]) +; = (+ (+ (+ 1 2) 3) 4) +; => 10 + +; Вызывая reduce, мы можем указать начальное значение +(reduce conj [] '(3 2 1)) +; = (conj (conj (conj [] 3) 2) 1) +; => [3 2 1] + +; Функции +;;;;;;;;;;;;;;;;;;;;; + +; Функция создается специальной формой fn. +; "Тело"" функции может состоять из нескольких форм, +; но результатом вызова функции всегда будет результат вычисления +; последней из них. +(fn [] "Hello World") ; => fn + +; (Вызов функции требует "оборачивания" fn-формы в форму вызова) +((fn [] "Hello World")) ; => "Hello World" + +; Назначить значению имя можно специальной формой def +(def x 1) +x ; => 1 + +; Назначить имя можно любому значению, в т.ч. и функции: +(def hello-world (fn [] "Hello World")) +(hello-world) ; => "Hello World" + +; Поскольку именование функций - очень частая операция, +; clojure позволяет, сделать это проще: +(defn hello-world [] "Hello World") + +; Вектор [] в форме описания функции, следующий сразу за именем, +; описывает параметры функции: +(defn hello [name] +  (str "Hello " name)) +(hello "Steve") ; => "Hello Steve" + +; Одна функция может иметь сразу несколько наборов аргументов: +(defn hello3 +  ([] "Hello World") +  ([name] (str "Hello " name))) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" + +; Также функция может иметь набор аргументов переменной длины +(defn count-args [& args] ; args будет содержать seq аргументов +  (str "You passed " (count args) " args: " args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" + +; Можно комбинировать оба подхода задания аргументов +(defn hello-count [name & args] +  (str "Hello " name ", you passed " (count args) " extra args")) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" + +; Для создания анонимных функций есть специальный синтаксис: +; функциональные литералы +(def hello2 #(str "Hello " %1)) +(hello2 "Fanny") ; => "Hello Fanny" + +; такие функциональные литералы удобно использовать с map, filter и reduce +(map #(* 10 %1) [1 2 3 5])          ; => (10 20 30 50) +(filter #(> %1 3) [1 2 3 4 5 6 7])  ; => (4 5 6 7) +(reduce #(str %1 "," %2) [1 2 3 4]) ; => "1,2,3,4" + +; Отображения (Maps) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Hash maps и array maps имеют одинаковый интерфейс. +; Hash maps производят поиск по ключу быстрее, но не сохраняют порядок ключей +(class {:a 1 :b 2 :c 3})          ; => clojure.lang.PersistentArrayMap +(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap + +; Array maps автоматически преобразуются в hash maps, +; как только разрастутся до определенного размера + +; Отображения могут использовать в качестве ключей любые хэшируемые значения, +; однако предпочтительными являются ключи, +; являющиеся "ключевыми словами" (keywords) +(class :a) ; => clojure.lang.Keyword + +(def stringmap {"a" 1, "b" 2, "c" 3}) +stringmap  ; => {"a" 1, "b" 2, "c" 3} + +(def keymap {:a 1, :b 2, :c 3}) +keymap ; => {:a 1, :c 3, :b 2} + +; Предыдущий пример содержит запятые в коде, однако reader не использует их, +; при обработке литералов - запятые просто воспринимаются, +; как "пробельные символы" (whitespaces) + +; Отображение может выступать в роли функции, возвращающей значение по ключу +(stringmap "a")          ; => 1 +(keymap :a)              ; => 1 + +; При попытке получить отсутствующее значение, будет возвращён nil +(stringmap "d") ; => nil + +; Иногда бывает удобно указать конкретное значение по-умолчанию: +({:a 1 :b 2} :c "Oops!") ; => "Oops!" + +; Keywords тоже могут использоваться в роли функций! +(:b keymap) ; => 2 + +; Однако этот фокус не пройдёт со строками. +;("a" stringmap) +; => Exception: java.lang.String cannot be cast to clojure.lang.IFn + +; Добавить пару ключ-значение в отображение можно функцией assoc +(def newkeymap (assoc keymap :d 4)) +newkeymap ; => {:a 1, :b 2, :c 3, :d 4} + +; Но всегда следует помнить, что значения в Clojure - неизменяемые! +keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут + +; dissoc позволяет исключить значение по ключу +(dissoc keymap :a :b) ; => {:c 3} + +; Множества (Sets) +;;;;;;;;;;;;;;;;;; + +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} + +; Добавляются элементы посредством conj +(conj #{1 2 3} 4) ; => #{1 2 3 4} + +; Исключаются - посредством disj +(disj #{1 2 3} 1) ; => #{2 3} + +; Вызов множества, как функции, позволяет проверить +; принадлежность элемента этому множеству: +(#{1 2 3} 1) ; => 1 +(#{1 2 3} 4) ; => nil + +; В пространстве имен clojure.sets +; содержится множество функций для работы с множествами + +; Полезные формы +;;;;;;;;;;;;;;;;; + +; Конструкции ветвления в clojure, это обычные макросы +; и подобны их собратьям в других языках: +(if false "a" "b") ; => "b" +(if false "a") ; => nil + +; Специальная форма let позволяет присвоить имена значениям локально. +; При этом все изменения будут видны только вложенным формам: +(def a 10) +(let [a 1 b 2] +  (> a b)) ; => false + +; Несколько форм можно объединить в одну форму посредством do +; Значением do-формы будет значение последней формы из списка вложенных в неё: +(do +  (print "Hello") +  "World") ; => "World" (prints "Hello") + +; Множество макросов содержит внутри себя неявную do-форму. +; Пример - макрос определения функции: +(defn print-and-say-hello [name] +  (print "Saying hello to " name) +  (str "Hello " name)) +(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") + +; Ещё один пример - let: +(let [name "Urkel"] +  (print "Saying hello to " name) +  (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") + +; Модули +;;;;;;;;; + +; Форма "use" позволяет добавить в текущее пространство имен +; все имена (вместе со значениями) из указанного модуля: +(use 'clojure.set) + +; Теперь нам доступны операции над множествами: +(intersection #{1 2 3} #{2 3 4}) ; => #{2 3} +(difference #{1 2 3} #{2 3 4}) ; => #{1} + +; use позволяет указать, какие конкретно имена +; должны быть импортированы из модуля: +(use '[clojure.set :only [intersection]]) + +; Также модуль может быть импортирован формой require +(require 'clojure.string) + +; После этого модуль становится доступе в текущем пространстве имен, +; а вызов его функций может быть осуществлен указанием полного имени функции: +(clojure.string/blank? "") ; => true + +; Импортируемому модулю можно назначить короткое имя: +(require '[clojure.string :as str]) +(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." +; (Литерал вида #"" обозначает регулярное выражение) + +; Вместо отдельной формы require (и use, хотя это и не приветствуется) можно +; указать необходимые модули прямо в форме ns: +(ns test +  (:require +    [clojure.string :as str] ; Внимание: при указании внутри формы ns +    [clojure.set :as set]))  ; имена пакетов не квотируются! + +; Java +;;;;;;; + +; Стандартная библиотека Java очень богата, +; и всё это богатство доступно и для Clojure! + +; import позволяет импортировать модули Java +(import java.util.Date) + +; В том числе и из ns +(ns test +  (:import java.util.Date +           java.util.Calendar)) + +; Имя класса, сопровождаемое символом "." позволяет +; инстанцировать объекты Java-классов: +(Date.) ; <a date object> + +; форма . позволяет вызывать методы: +(. (Date.) getTime) ; <a timestamp> +(.getTime (Date.))  ; а можно и так + +; Статические методы вызываются как функции модуля: +(System/currentTimeMillis) ; <a timestamp> (Модуль system всегда доступен!) + +; doto позволяет удобно работать с объектами, изменяющими свое состояние +(import java.util.Calendar) +(doto (Calendar/getInstance) +  (.set 2000 1 1 0 0 0) +  .getTime) ; => A Date. set to 2000-01-01 00:00:00 + +; Работа с изменяемым сотоянием +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Clojure предоставляет набор инструментов +; для работы с изменяемым состоянием: Software Transactional Memory. +; Структуры STM представлены тремя типами: +; - атомы (atoms) +; - агенты (agents) +; - ссылки (references) + +; Самые простые хранители состояния - атомы: +(def my-atom (atom {})) ; {} - начальное состояние атома + +; Обновляется атом посредством swap!. +; swap! применяет функцию аргумент к текущему значению +; атома и помещает в атом результат +(swap! my-atom assoc :a 1) ; Обновляет my-atom, помещая в него (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Обновляет my-atom, помещая в него (assoc {:a 1} :b 2) + +; Получить значение атома можно посредством '@' +; (провести так называемую операцию dereference) +my-atom  ;=> Atom<#...> (Возвращает объект типа Atom) +@my-atom ; => {:a 1 :b 2} + +; Пример реализации счётчика на атоме +(def counter (atom 0)) +(defn inc-counter [] +  (swap! counter inc)) + +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) + +@counter ; => 5 + +; С другими STM-конструкциями - refs и agents - можно ознакомиться тут: +; Refs: http://clojure.org/refs +; Agents: http://clojure.org/agents +``` + +### Для будущего чтения + +Это руководство не претендует на полноту, но мы смеем надеяться, способно вызвать интерес к дальнейшему изучению языка. + +Clojure.org - сайт содержит большое количество статей по языку: +[http://clojure.org/](http://clojure.org/) + +Clojuredocs.org - сайт документации языка с примерами использования функций: +[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) + +4Clojure - отличный способ закрепить навыки программирования на clojure, решая задачи вместе с коллегами со всего мира: +[http://www.4clojure.com/](http://www.4clojure.com/) + +Clojure-doc.org (да, именно) неплохой перечень статей для начинающих: +[http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/ru-ru/php-ru.html.markdown b/ru-ru/php-ru.html.markdown new file mode 100644 index 00000000..6c5720e3 --- /dev/null +++ b/ru-ru/php-ru.html.markdown @@ -0,0 +1,658 @@ +--- +language: php +contributors: +    - ["Malcolm Fell", "http://emarref.net/"] +    - ["Trismegiste", "https://github.com/Trismegiste"] +    - ["SlaF", "https://github.com/SlaF"] +lang: ru-ru +filename: learnphp-ru.php +--- + +Этот документ описывает версию PHP 5 и выше. + +```php +<?php // PHP код должен быть заключен в теги <?php + +// Если ваш файл содержит только PHP код, то можно +// пропустить закрывающийся ?> + +// А так начинаются комментарии + +# Это тоже комментарий но // предпочтительнее + +/* +	Окруженный /* и */ текст превращается +	в многострочный комментарий +*/ + +// Используйте "echo" или "print" для вывода. +print('Hello '); // Напечатать "Hello " без перевода строки + +// () необязательно применять для print и echo +echo "World\n"; // Печатать "World" и перейти на новую строку. +// (все утверждения должны заканчиваться ;) + +// Любые символы за пределами закрывающегося тега выводятся автоматически: +?> +Hello World Again! +<?php + + +/************************************ + * Типы и Переменные + */ + +// Переменные начинаются с символа $. +// Правильное имя переменной начинается с буквы или знака подчеркивания, +// и может содержать любые цифры, буквы, или знаки подчеркивания. +// Не рекомендуется использовать кирилические символы в именах (прим. пер.) + +// Логические значения нечувствительны к регистру +$boolean = true;  // или TRUE или True +$boolean = false; // или FALSE или False + +// Целые числа +$int1 = 12;   // => 12 +$int2 = -12;  // => -12- +$int3 = 012;  // => 10 (ведущий 0 обозначает восьмеричное число) +$int4 = 0x0F; // => 15 (ведущие символы 0x означает шестнадцатеричное число) + +// Дробные числа +$float = 1.234; +$float = 1.2e3; +$float = 7E-10; + +// Арифметика +$sum        = 1 + 1; // 2 +$difference = 2 - 1; // 1 +$product    = 2 * 2; // 4 +$quotient   = 2 / 1; // 2 + +// Арифметические сокращения +$number = 0; +$number += 1;      // Увеличивает $number на 1 +echo $number++;    // Печатает 1 (инкрементируется после вывода) +echo ++$number;    // Печатает 3 (инкрементируется до вывода) +$number /= $float; // Делится и результат присваивается $number + +// Строки должны быть заключены в одинарные кавычки; +$sgl_quotes = '$String'; // => '$String' + +// Избегайте двойных кавычек за исключением случаев интерполирования переменной +$dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.' + +// Специальные (escape) символы работают только в двойных кавычках +$escaped   = "This contains a \t tab character."; +$unescaped = 'This just contains a slash and a t: \t'; + +// Заключайте переменные в фигурные скобки если это необходимо +$money = "I have $${number} in the bank."; + +// Начиная с PHP 5.3, синтаксис nowdocs может использоваться для неинтерполированного многострочного текста +$nowdoc = <<<'END' +Multi line +string +END; + +// Heredocs поддерживает интерполяцию переменных +$heredoc = <<<END +Multi line +$sgl_quotes +END; + +// Строки соединяются при помощи . +echo 'This string ' . 'is concatenated'; + + +/******************************** + * Константы + */ +  +// Константа определяется при помощи define() +// и никогда не может быть изменена во время выполнения программы! + +// Правильное имя константы начинается с буквы или символа подчеркивания, +// и содержит любое колличество букв, цифр и знаков подчеркивания. +define("FOO", "something"); + +// Доступ к константе возможен через прямое указание её имени +echo 'This outputs '.FOO; + +/******************************** + * Массивы + */ + +// Все массивы в PHP - это ассоциативные массивы или хеши, + +// Ассоциативные массивы, известные в других языках как хеш-карты. + +// Работает во всех версиях РHP +$associative = array('One' => 1, 'Two' => 2, 'Three' => 3); + +// В PHP 5.4 появился новый синтаксис +$associative = ['One' => 1, 'Two' => 2, 'Three' => 3]; + +echo $associative['One']; // печатает 1 + +// Список тоже содержит целочисленные ключи +$array = ['One', 'Two', 'Three']; +echo $array[0]; // => "One" + + +/******************************** + * Вывод + */ + +echo('Hello World!'); +// Печатает Hello World! на stdout. +// Stdout это веб-страница запущенная в браузере. + +print('Hello World!'); // Аналогично echo + +// echo - это конструкция языка, вы можете опустить скобки. +echo 'Hello World!'; +print 'Hello World!'; // Выводит Hello World! + +$paragraph = 'paragraph'; + +echo 100;        // Печать скалярной переменной напрямую +echo $paragraph; // или печать переменной + +// Если короткие теги разрешены, или ваша версия PHP >= 5.4 +// вы можете использовать сокращенный синтаксис echo +?> +<p><?= $paragraph ?></p> +<?php + +$x = 1; +$y = 2; +$x = $y; // $x теперь содержит значение переменной $y +$z = &$y; +// $z содержит ссылку на $y. Изменение значения $z затронет значение $y и наоборот. +// Значение $x остается неизменным.  + +echo $x; // => 2 +echo $z; // => 2 +$y = 0; +echo $x; // => 2 +echo $z; // => 0 + + +/******************************** + * Логические выражения + */ +$a = 0; +$b = '0'; +$c = '1'; +$d = '1'; + +// Утверждение (assert) выдает предупреждение если аргумент не true + +// Эти сравнения всегда будут истинными, даже если типы будут различаться +assert($a == $b); // "равно" +assert($c != $a); // "не равно" +assert($c <> $a); // другое обозначение "не равно" +assert($a < $c); // меньше +assert($c > $b); // больше +assert($a <= $b); // меньше или равно +assert($c >= $d); // больше или равно + +// Следующие утверждения истинны если переменные имеют одинаковый тип. +assert($c === $d); +assert($a !== $d); +assert(1 == '1'); +assert(1 !== '1'); + +// Переменные могут изменять тип, в зависимости от их использования. +$integer = 1; +echo $integer + $integer; // => 2 + +$string = '1'; +echo $string + $string; // => 2 (строка превращается в число) + +// Выводится 0 по той причине, что оператор + не может привести строку 'one' к числовому типу +$string = 'one'; +echo $string + $string; // => 0 + +// Приведение типов (type casting) может быть использовано для преобразование переменной в другой тип +$boolean = (boolean) 1; // => true + +$zero = 0; +$boolean = (boolean) $zero; // => false + +// Также существуют функции выполняющие приведение типов +$integer = 5; +$string = strval($integer); +$float = floatval($integer); + +$var = null; // Null + +// И похожая по действию функция +$integer = 10; +$boolen = settype($integer, "string") // теперь $integer имеет строковый тип + +// settype возвращает true - если преобразование удалось и false в противном случае + +/******************************** + * Управляющие структуры + */ + +if (true) { +    print 'I get printed'; +} + +if (false) { +    print 'I don\'t'; +} else { +    print 'I get printed'; +} + +if (false) { +    print 'Does not get printed'; +} elseif(true) { +    print 'Does'; +} + +// Тернарный оператор +print (false ? 'Does not get printed' : 'Does'); + +$x = 0; +if ($x === '0') { +    print 'Does not print'; +} elseif($x == '1') { +    print 'Does not print'; +} else { +    print 'Does print'; +} + +// Альтернативный синтаксис полезный для шаблонов +?> + +<?php if ($x): ?> +This is displayed if the test is truthy. +<?php else: ?> +This is displayed otherwise. +<?php endif; ?> + +<?php + +// Использование switch. +switch ($x) { +    case '0': +        print 'Switch does type coercion'; +        break; // You must include a break, or you will fall through +               // to cases 'two' and 'three' +    case 'two': +    case 'three': +        // Do something if $variable is either 'two' or 'three' +        break; +    default: +        // Do something by default +} + +// Циклы: while, do...while и for +$i = 0; +while ($i < 5) { +    echo $i++; +}; // Prints "01234" + +echo "\n"; + +$i = 0; +do { +    echo $i++; +} while ($i < 5); // Prints "01234" + +echo "\n"; + +for ($x = 0; $x < 10; $x++) { +    echo $x; +} // Prints "0123456789" + +echo "\n"; + +$wheels = ['bicycle' => 2, 'car' => 4]; + +// Циклы foreach могут обходить массивы +foreach ($wheels as $wheel_count) { +    echo $wheel_count; +} // Prints "24" + +echo "\n"; + +// Вы можете обходить как ключи, так и их значения +foreach ($wheels as $vehicle => $wheel_count) { +    echo "A $vehicle has $wheel_count wheels"; +} + +echo "\n"; + +$i = 0; +while ($i < 5) { +    if ($i === 3) { +        break; // Exit out of the while loop +    } +    echo $i++; +} // Prints "012" + +for ($i = 0; $i < 5; $i++) { +    if ($i === 3) { +        continue; // Skip this iteration of the loop +    } +    echo $i; +} // Prints "0124" + + +/******************************** + * Функции + */ + +// Определение функции: +function my_function () { +  return 'Hello'; +} + +echo my_function(); // => "Hello" + +// Правильное имя функции начинается с буквы или символа подчеркивания +// и состоит из букв, цифр или знаков подчеркивания. + +function add ($x, $y = 1) { // $y по умолчанию равно 1 +  $result = $x + $y; +  return $result; +} + +echo add(4); // => 5 +echo add(4, 2); // => 6 + +// $result недоступна за пределами функции +// print $result; // Выдает предупреждение + +// Начиная с PHP 5.3 вы можете объявлять анонимные функции: +$inc = function ($x) { +  return $x + 1; +}; + +echo $inc(2); // => 3 + +function foo ($x, $y, $z) { +  echo "$x - $y - $z"; +} + +// Функции могут возвращать функции +function bar ($x, $y) { +  // Используйте 'use' для передачи внешних переменных +  return function ($z) use ($x, $y) { +    foo($x, $y, $z); +  }; +} + +$bar = bar('A', 'B'); +$bar('C'); // Prints "A - B - C" + +// Вы можете вызывать именованные функции используя строки +$function_name = 'add'; +echo $function_name(1, 2); // => 3 +// Полезно для программного определения запущенной функции. +// Или используйте call_user_func(callable $callback [, $parameter [, ... ]]); + + +/******************************** + * Includes + */ + +<?php +// PHP код внутри включаемого файла должен начинаться с тега PHP. + +include 'my-file.php'; +// Код в файле my-file.php теперь доступен в текущем в текущем пространстве имен. +// Если файл не удалось включить, будет выдано предупреждение. + +include_once 'my-file.php'; +// Если код в файле my-file.php уже был включен, он не будет включен повторно. +// Это предотвращает ошибку повторного включения файла. + +require 'my-file.php'; +require_once 'my-file.php'; + +// Same as include(), except require() will cause a fatal error if the +// file cannot be included. +// Действует также как и include(), но если файл не удалось подключить, +// функция выдает неисправимую ошибку + +// Содержимое файла my-include.php: +<?php + +return 'Anything you like.'; +// Конец файла + +// Эти функции могут также возвращать значения. +$value = include 'my-include.php'; + +// Имена файлов содержат их путь в файловой системе, или если передано просто имя файла, +// PHP обращается к директиве include_path. Если файл не найден в include_path, предпринимается +// попытка поиска в папке, где выполняется скрипт или в текущей рабочей директории. +// Если не в одном из этих мест файл не найден - выдается ошибка +/* */ + +/******************************** + * Классы + */ + +// Классы определяются при помощи ключевого слова "class" + +class MyClass +{ +    const MY_CONST      = 'value'; // A constant + +    static $staticVar   = 'static'; + +    // Properties must declare their visibility +    public $property    = 'public'; +    public $instanceProp; +    protected $prot = 'protected'; // Accessible from the class and subclasses +    private $priv   = 'private';   // Accessible within the class only + +    // Create a constructor with __construct +    public function __construct($instanceProp) { +        // Access instance variables with $this +        $this->instanceProp = $instanceProp; +    } + +    // Methods are declared as functions inside a class +    public function myMethod() +    { +        print 'MyClass'; +    } + +    final function youCannotOverrideMe() +    { +    } + +    public static function myStaticMethod() +    { +        print 'I am static'; +    } +} + +echo MyClass::MY_CONST;    // Выведет 'value'; +echo MyClass::$staticVar;  // Выведет 'static'; +MyClass::myStaticMethod(); // Выведет 'I am static'; + +// Новый экземпляр класса используя new +$my_class = new MyClass('An instance property'); + +// Если аргументы отсутствуют, можно не ставить круглые скобки + +// Доступ к членам класса используя -> +echo $my_class->property;     // => "public" +echo $my_class->instanceProp; // => "An instance property" +$my_class->myMethod();        // => "MyClass" + +// Наследование классов используя "extends" +class MyOtherClass extends MyClass +{ +    function printProtectedProperty() +    { +        echo $this->prot; +    } + +    // Override a method +    function myMethod() +    { +        parent::myMethod(); +        print ' > MyOtherClass'; +    } +} + +$my_other_class = new MyOtherClass('Instance prop'); +$my_other_class->printProtectedProperty(); // => Выведет "protected" +$my_other_class->myMethod();               // Выведет "MyClass > MyOtherClass" + +final class YouCannotExtendMe +{ +} + +// Вы можете использовать "магические методы" для создания геттеров и сеттеров +class MyMapClass +{ +    private $property; + +    public function __get($key) +    { +        return $this->$key; +    } + +    public function __set($key, $value) +    { +        $this->$key = $value; +    } +} + +$x = new MyMapClass(); +echo $x->property; // Будет использован метод __get() +$x->property = 'Something'; // Будет использован метод __set() + +// Классы могут быть абстрактными (используя ключевое слово abstract) +// или реализовывать интерфейсы (используя ключевое слово implements). +// Интерфейсы определяются при помощи ключевого слова interface + +interface InterfaceOne +{ +    public function doSomething(); +} + +interface InterfaceTwo +{ +    public function doSomethingElse(); +} + +// Интерфейсы могут быть расширены +interface InterfaceThree extends InterfaceTwo +{ +    public function doAnotherContract(); +} + +abstract class MyAbstractClass implements InterfaceOne +{ +    public $x = 'doSomething'; +} + +class MyConcreteClass extends MyAbstractClass implements InterfaceTwo +{ +    public function doSomething() +    { +        echo $x; +    } + +    public function doSomethingElse() +    { +        echo 'doSomethingElse'; +    } +} + +// Классы могут реализовывать более одного интерфейса +class SomeOtherClass implements InterfaceOne, InterfaceTwo +{ +    public function doSomething() +    { +        echo 'doSomething'; +    } + +    public function doSomethingElse() +    { +        echo 'doSomethingElse'; +    } +} + + +/******************************** + * Трейты + */ + +// Трейты появились в PHP 5.4.0 и объявляются при помощи ключевого слова trait + +trait MyTrait +{ +    public function myTraitMethod() +    { +        print 'I have MyTrait'; +    } +} + +class MyTraitfulClass +{ +    use MyTrait; +} + +$cls = new MyTraitfulClass(); +$cls->myTraitMethod(); // Prints "I have MyTrait" + + +/******************************** + * Пространства имен + */ + +// Это секция особая, ведь объявление пространства имен +// должно быть самым первым в файле. Позвольте сделать вид, что это не так + +<?php + +// По умолчанию, классы существуют в глобальном пространстве имен и могут быть +// вызваны с обратным слешем. + +$cls = new \MyClass(); + +// Задание пространства имен файла +namespace My\Namespace; + +class MyClass +{ +} + +// (из другого файла) +$cls = new My\Namespace\MyClass; + +// Или внутри другого пространства имен. +namespace My\Other\Namespace; + +use My\Namespace\MyClass; + +$cls = new MyClass(); + +// Или вы можете создать псевдоним для пространства имен: +namespace My\Other\Namespace; + +use My\Namespace as SomeOtherNamespace; + +$cls = new SomeOtherNamespace\MyClass(); + +*/ + +``` + +## Смотрите также: +Посетите страницу [официальной документации PHP](http://www.php.net/manual/) для справки.  +Если вас интересуют полезные приемы использования PHP посетите [PHP The Right Way](http://www.phptherightway.com/). +Если вы раньше пользовались языком с хорошей организацией пакетов, посмотрите [Composer](http://getcomposer.org/). +Для изучения стандартов использования языка посетите PHP Framework Interoperability Group's [PSR standards](https://github.com/php-fig/fig-standards).  diff --git a/ru-ru/python-ru.html.markdown b/ru-ru/python-ru.html.markdown new file mode 100644 index 00000000..58b0adcc --- /dev/null +++ b/ru-ru/python-ru.html.markdown @@ -0,0 +1,486 @@ +--- +language: python +contributors: +    - ["Yury Timofeev", "http://twitter.com/gagar1n"] +filename: learnpython-ru.py +--- + +Язык Python был создан Гвидо ван Россумом в ранние 90-е. Сегодня это один из самых популярных  +языков. Я влюбился в него благодаря его понятному и доходчивому синтаксису - это почти что исполняемый псевдокод. + +Обратная связь будет высоко оценена! Вы можете связаться со мной: [@louiedinh](http://twitter.com/louiedinh) или louiedinh [at] [google's email service] + +Замечание: Эта статья относится к Python 2.7, но должна быть применима к Python 2.x. Скоро ожидается версия и для Python 3! + +```python +# Однострочные комментарии начинаются с hash-символа. +""" Многострочный текст может быть  +    записан, используя 3 знака " и обычно используется +    в качестве комментария +""" + +#################################################### +## 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 + +# Строки создаются при символом " или ' +"Это строка." +'Это тоже строка.' + +# Строки тоже могут складываться! +"Привет " + "мир!" #=> "Привет мир!" + +# Со строкой можно работать как со списком символов +"Это строка"[0] #=> 'Э' + +# % используется для форматирования строк, например: +"%s могут быть %s" % ("строки", "интерполированы") + +# Новый метод форматирования строк - использование метода format. +# Это предпочитаемый способ. +"{0} могут быть {1}".format("строки", "форматированы") +# Вы можете использовать ключевые слова, если не хотите считать. +"{name} хочет есть {food}".format(name="Боб", food="лазанью") + +# 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 "Я Python. Приятно познакомиться!" + + +# Необязательно объявлять переменные перед присваиванием им значения. +some_var = 5    # По соглашению используется нижний_регистр_с_подчеркиваниями +some_var #=> 5 + +# При попытке доступа к переменной, которой не было ранее присвоено значение, +# выбрасывается исключение. +# См. раздел "Поток управления" для информации об исключениях. +some_other_var  # Выбрасывает ошибку именования + +# if может быть использован как выражение +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Списки хранят последовательности +li = [] +# Можно сразу начать с заполненным списком +other_li = [4, 5, 6] + +# Объекты добавляются в конец списка методом append +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] +# Удаляются с конца методом pop +li.pop()        #=> 3 и li содержит [1, 2, 4] +# Положим его обратно +li.append(3)    # li содержит [1, 2, 4, 3] опять. + +# Обращайтесь со списком, как с обычным массивом +li[0] #=> 1 +# Посмотрим на последний элемент +li[-1] #=> 3 + +# Попытка выйти за границы массива приводит к IndexError +li[4] # Выдает IndexError + +# Можно обращаться к диапазону, используя "кусочный синтаксис" (slice syntax) +# (Для тех из вас, кто любит математику, это замкнуто/открытый интервал.) +li[1:3] #=> [2, 4] +# Опускаем начало +li[2:] #=> [4, 3] +# Опускаем конец +li[:3] #=> [1, 2, 4] + +# Удаляем произвольные элементы из списка оператором del +del li[2] # li содержит [1, 2, 3] + +# Вы можете складывать списки +li + other_li #=> [1, 2, 3, 4, 5, 6] - ЗАмечание: li и other_li остаются нетронутыми + +# Конкатенировать списки можно методом extend +li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6] + +# Проверять элемент на вхождение на список оператором in +1 in li #=> True + +# Длина списка вычисляется при помощи len +len(li) #=> 6 + + +# Кортежи - это как списки, только неизменяемые +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3  # Выдает TypeError + +# Все те же штуки можно делать и с кортежами +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 теперь равно 1, b равно 2 и c равно 3 +# Кортежи создаются по умолчанию, если опущены скобки +d, e, f = 4, 5, 6 +# Обратите внимание, как легко поменять местами значения двух переменных +e, d = d, e     # d теперь равно 5 and e равно 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] +# Замечание - то же самое, что и выше, насчет порядка ключей + +# При помощи оператора in можно проверять ключи на вхождение в словарь +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# Попытка получить значение по несуществующему ключу выбросит KeyError +filled_dict["four"] # KeyError + +# Чтобы избежать этого, используйте метод get +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# Метод get также принимает аргумент default, значение которого будет возвращено при отсутствии указанного ключа +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]) # some_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 меньше, чем 10" +if some_var > 10: +    print "some_var намного больше, чем 10." +elif some_var < 10:    # Выражение elif необязательно. +    print "some_var меньше, чем 10." +else:           # Это тоже необязательно. +    print "some_var равно 10." + + +""" +Циклы For проходят по циклам +результат: +    собака это млекопитающее +    кошка это млекопитающее +    мышь это млекопитающее +""" +for animal in ["собака", "кошка", "мышь"]: +    # Можете использовать оператор % для интерполяции форматированных строк +    print "%s это млекопитающее" % animal +     +""" +`range(number)` возвращает список чисел +от нуля до заданного числа +результат: +    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  # То же самое, что x = x + 1 + +# Обрабывайте исключения блоками try/except + +# Работает в Python 2.6 и выше: +try: +    # Для выбора ошибки используется raise +    raise IndexError("Это IndexError") +except IndexError as e: +    pass    # pass это просто отсутствие оператора. Обычно здесь происходит восстановление от ошибки. + + +#################################################### +## 4. Функции +#################################################### + +# Используйте def для создания новых функций +def add(x, y): +    print "x равен %s, а y равен %s" % (x, y) +    return x + y    # Возвращайте результат выражением return + +# Вызов функции с аргументами +add(5, 6) #=> prints out "x равен 5, а y равен 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) выводит: +    (1, 2) +    {"a": 3, "b": 4} +""" + +# Вызывая функции, можете сделать наоборот! +# Используйте символ * для передачи кортежей и ** для передачи словарей +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # эквивалент foo(1, 2, 3, 4) +all_the_args(**kwargs) # эквивалент foo(a=3, b=4) +all_the_args(*args, **kwargs) # эквивалент 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): +        # Присваивание значения аргумента атрибуту класса 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="Иван") +print i.say("привет")     # выводит "Иван: привет" + +j = Human("Петр") +print j.say("Привет")  #выводит "Петр: привет" + +# Вызов метода класса +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/) + +### Готовьте деньги + +* [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) + diff --git a/ruby-ecosystem.html.markdown b/ruby-ecosystem.html.markdown index cae55cd3..54c1d178 100644 --- a/ruby-ecosystem.html.markdown +++ b/ruby-ecosystem.html.markdown @@ -81,7 +81,7 @@ development.  Less mature/compatible:  * Topaz - Written in RPython (using the PyPy toolchain), Topaz is fairly young -  and not yet compatable. It shows promise to be a high-performance ruby +  and not yet compatible. It shows promise to be a high-performance ruby  implementation.  * IronRuby - Written in C# targeting the .NET platform, work on IronRuby seems    to have stopped since Microsoft pulled their support. diff --git a/ruby.html.markdown b/ruby.html.markdown index 19f2ec86..3a233d98 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -36,7 +36,7 @@ You shouldn't either  # Arithmetic is just syntactic sugar  # for calling a method on an object  1.+(3) #=> 4 -10.* 5 #=> 50  +10.* 5 #=> 50  # Special values are objects  nil # Nothing to see here @@ -242,7 +242,7 @@ when 'D'    puts "Scraping through"  when 'F'    puts "You failed!" -else  +else    puts "Alternative grading system, eh?"  end @@ -252,7 +252,7 @@ def double(x)    x * 2  end -# Functions (and all blocks) implcitly return the value of the last statement +# Functions (and all blocks) implicitly return the value of the last statement  double(2) #=> 4  # Parentheses are optional where the result is unambiguous diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown new file mode 100644 index 00000000..25fd1f03 --- /dev/null +++ b/zh-cn/go-zh.html.markdown @@ -0,0 +1,279 @@ +--- +名字:Go +分类:编程语言 +文件名:learngo.go +贡献者: +    - ["Sonia Keys", "https://github.com/soniakeys"] +    - ["pantaovay", "https://github.com/pantaovay"] +--- + +发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 + +Go拥有命令式语言的静态类型,编译很快,执行也很快,同时加入了对于目前多核CPU的并发计算支持,也有相应的特性来实现大规模编程。 + +Go语言有非常棒的标准库,还有一个充满热情的社区。 + +```Go +// 单行注释 +/* 多行 +    注释 */ + +// 导入包的子句在每个源文件的开头。 +// Main比较特殊,它用来声明可执行文件,而不是一个库。 +package main + +// Import语句声明了当前文件引用的包。 +import ( +    "fmt"       // Go语言标准库中的包 +    "net/http"  // 一个web服务器包 +    "strconv"   // 字符串转换 +) + +//函数声明:Main是程序执行的入口。不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 +func main() { +    // 往标准输出打印一行。 +    // 用包名fmt限制打印函数。 +    fmt.Println("Hello world!") + +    // 调用当前包的另一个函数。 +    beyondHello() +} + +// 函数可以在括号里加参数。 +// 如果没有参数的话,也需要一个空括号。 +func beyondHello() { +    var x int   // 变量声明,变量必须在使用之前声明。 +    x = 3       // 变量赋值。 +    // 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。 +    y := 4 +    sum, prod := learnMultiple(x, y)        // 多个返回变量的函数 +    fmt.Println("sum:", sum, "prod:", prod) // 简单输出 +    learnTypes()                            // 少于y分钟,学的更多! +} + +// 多变量和多返回值的函数 +func learnMultiple(x, y int) (sum, prod int) { +    return x + y, x * y // 返回两个值 +} + +// 内置变量类型和关键词 +func learnTypes() { +    // 短声明给你所想。 +    s := "Learn Go!" // String类型 + +    s2 := `A "raw" string literal +can include line breaks.` // 同样是String类型 +     +    // 非ascii字符。Go使用UTF-8编码。 +	g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 + +	f := 3.14195 // float64类型,IEEE-754 64位浮点数 +	c := 3 + 4i  // complex128类型,内部使用两个float64表示 + +    // Var变量可以直接初始化。 +    var u uint = 7  // unsigned 无符号变量,但是实现依赖int型变量的长度 +    var pi float32 = 22. / 7 + +    // 字符转换 +    n := byte('\n') // byte是uint8的别名 + +    // 数组类型编译的时候大小固定。 +    var a4 [4] int              // 有4个int变量的数组,初始为0 +    a3 := [...]int{3, 1, 5}     // 有3个int变量的数组,同时进行了初始化 + +    // Slice 有动态大小。Array和Slice各有千秋,但是使用slice的地方更多些。 +    s3 := []int{4, 5, 9}        // 和a3相比,这里没有省略号 +    s4 := make([]int, 4)        // 分配一个有4个int型变量的slice,全部被初始化为0 + +    var d2 [][]float64          // 声明而已,什么都没有分配 +    bs := []byte("a slice")     // 类型转换的语法 + +    p, q := learnMemory()       // 声明p,q为int型变量的指针 +    fmt.Println(*p, *q)         // * 取值 + +    // Map是动态可增长关联数组,和其他语言中的hash或者字典相似。 +    m := map[string]int{"three": 3, "four": 4} +    m["one"] = 1 + +    // 在Go语言中未使用的变量在编译的时候会报错,而不是warning。 +    // 下划线 _ 可以使你“使用”一个变量,但是丢弃它的值。 +    _,_,_,_,_,_,_,_,_ = s2, g, f, u, pi, n, a3, s4, bs +    // 输出变量 +	fmt.Println(s, c, a4, s3, d2, m) + +	learnFlowControl() // 回到流程控制  +} + +// Go全面支持垃圾回收。Go有指针,但是不支持指针运算。 +// 你会因为空指针而犯错,但是不会因为增加指针而犯错。 +func learnMemory() (p, q *int) { +    // 返回int型变量指针p和q +    p = new(int)    // 内置函数new分配内存 +    // 自动将分配的int赋值0,p不再是空的了。 +    s := make([]int, 20)    // 给20个int变量分配一块内存 +    s[3] = 7                // 赋值 +    r := -2                 // 声明另一个局部变量 +    return &s[3], &r        // & 取址 +} + +func expensiveComputation() int { +	return 1e6 +} + +func learnFlowControl() { +    // If需要花括号,括号就免了 +	if true { +		fmt.Println("told ya") +	} +    // 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了,也不用容忍被人的代码风格。 +	if false { +		// pout +	} else { +		// gloat +	} +    // 如果太多嵌套的if语句,推荐使用switch +	x := 1 +	switch x { +	case 0: +	case 1: +        // 隐式调用break语句,匹配上一个即停止 +	case 2: +        // 不会运行 +	} +    // 和if一样,for也不用括号 +	for x := 0; x < 3; x++ { // ++ 自增 +		fmt.Println("iteration", x) +	} +    // x在这里还是1。为什么? + +    // for 是go里唯一的循环关键字,不过它有很多变种 +	for { // 无限循环 +		break    // 骗你的  +		continue // 不会运行的 +	} +    // 和for一样,if中的:=先给y赋值,然后再和x作比较。 +	if y := expensiveComputation(); y > x { +		x = y +	} +    // 闭包函数 +	xBig := func() bool { +		return x > 100 // x是上面声明的变量引用 +	} +	fmt.Println("xBig:", xBig()) // true (上面把y赋给x了)  +	x /= 1e5                     // x变成10 +	fmt.Println("xBig:", xBig()) // 现在是false + +    // 当你需要goto的时候,你会爱死它的! +	goto love +love: + +	learnInterfaces() // 好东西来了! +} + +// 定义Stringer为一个接口类型,有一个方法String +type Stringer interface { +	String() string +} + +// 定义pair为一个结构体,有x和y两个int型变量。 +type pair struct { +	x, y int +} + +// 定义pair类型的方法,实现Stringer接口。 +func (p pair) String() string { // p被叫做“接收器” +    // Sprintf是fmt包中的另一个公有函数。 +    // 用 . 调用p中的元素。 +	return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func learnInterfaces() { +    // 花括号用来定义结构体变量,:=在这里将一个结构体变量赋值给p。 +	p := pair{3, 4} +	fmt.Println(p.String()) // 调用pair类型p的String方法  +	var i Stringer          // 声明i为Stringer接口类型  +	i = p                   // 有效!因为p实现了Stringer接口(类似java中的塑型)  +    // 调用i的String方法,输出和上面一样 +	fmt.Println(i.String()) + +    // fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。(类似java中的序列化) +	fmt.Println(p) // 输出和上面一样,自动调用String函数。 +	fmt.Println(i) // 输出和上面一样。 + +	learnErrorHandling() +} + +func learnErrorHandling() { +	// ", ok"用来判断有没有正常工作  +	m := map[int]string{3: "three", 4: "four"} +	if x, ok := m[1]; !ok { // ok 为false,因为m中没有1 +		fmt.Println("no one there") +	} else { +		fmt.Print(x) // 如果x在map中的话,x就是那个值喽。 +	} +    // 错误可不只是ok,它还可以给出关于问题的更多细节。 +	if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value +		// 输出"strconv.ParseInt: parsing "non-int": invalid syntax" +		fmt.Println(err) +	} +    // 待会再说接口吧。同时, +	learnConcurrency() +} + +// c是channel类型,一个并发安全的通信对象。 +func inc(i int, c chan int) { +	c <- i + 1 // <-把右边的发送到左边的channel。 +} + +// 我们将用inc函数来并发地增加一些数字。 +func learnConcurrency() { +    // 用make来声明一个slice,make会分配和初始化slice,map和channel。 +	c := make(chan int) +    // 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。三个都被发送到同一个channel。 +	go inc(0, c) // go is a statement that starts a new goroutine. +	go inc(10, c) +	go inc(-805, c) +    // 从channel中独处结果并打印。 +    // 打印出什么东西是不可预知的。 +	fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 + +	cs := make(chan string)       // 操作string的channel +	cc := make(chan chan string)  // 操作channel的channel +	go func() { c <- 84 }()       // 开始一个goroutine来发送一个新的数字  +	go func() { cs <- "wordy" }() // 发送给cs +    // Select类似于switch,但是每个case包括一个channel操作。它随机选择一个准备好通讯的case。 +	select { +	case i := <-c: // 从channel接收的值可以赋给其他变量 +		fmt.Println("it's a", i) +	case <-cs: // 或者直接丢弃 +		fmt.Println("it's a string") +	case <-cc: // 空的,还没作好通讯的准备  +		fmt.Println("didn't happen.") +	} +    // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 + +	learnWebProgramming() // Go很适合web编程,我知道你也想学! +} + +// http包中的一个简单的函数就可以开启web服务器。 +func learnWebProgramming() { +    // ListenAndServe第一个参数指定了监听端口,第二个参数是一个接口,特定是http.Handler。 +	err := http.ListenAndServe(":8080", pair{}) +	fmt.Println(err) // 不要无视错误。 +} + +// 使pair实现http.Handler接口的ServeHTTP方法。 +func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { +    // 使用http.ResponseWriter返回数据 +	w.Write([]byte("You learned Go in Y minutes!")) +} +``` + +## 更进一步 + +Go的根源在[Go官方网站](http://golang.org/)。 +在那里你可以学习入门教程,通过浏览器交互式地学习,而且可以读到很多东西。 + +强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.) + +学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了! | 
