summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c.html.markdown678
-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--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--ruby-ecosystem.html.markdown2
-rw-r--r--ruby.html.markdown6
-rw-r--r--zh-cn/go-zh.html.markdown279
10 files changed, 1906 insertions, 286 deletions
diff --git a/c.html.markdown b/c.html.markdown
index 2b50efa0..8e16837c 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,22 +456,29 @@ 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
///////////////////////////////////////
@@ -379,10 +490,11 @@ 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.
}
@@ -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/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/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。在文档中点击函数名,源代码就出来了!