summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c.html.markdown682
-rw-r--r--es-es/c-es.html.markdown2
-rw-r--r--fr-fr/ruby-fr.html.markdown407
-rw-r--r--java.html.markdown4
-rw-r--r--javascript.html.markdown246
-rw-r--r--ko-kr/java-kr.html.markdown406
-rw-r--r--objective-c.html.markdown4
-rw-r--r--pt-br/ruby-pt.html.markdown384
-rw-r--r--ru-ru/clojure-ru.html.markdown426
-rw-r--r--ru-ru/python-ru.html.markdown486
-rw-r--r--ruby-ecosystem.html.markdown2
-rw-r--r--ruby.html.markdown6
-rw-r--r--zh-cn/go-zh.html.markdown279
13 files changed, 2919 insertions, 415 deletions
diff --git a/c.html.markdown b/c.html.markdown
index 2b50efa0..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,264 +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;
-
-
-// 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", px); // => Prints some address in memory
-printf("%d, %d\n", (int)sizeof(px), (int)sizeof(not_a_pointer));
-// => Prints "8, 4" on 64-bit system
-
-// 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
///////////////////////////////////////
@@ -300,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
}
@@ -312,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;
@@ -336,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 .
@@ -352,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.
}
@@ -394,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;
@@ -403,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/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/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。在文档中点击函数名,源代码就出来了!